Skip to content

Commit 75d8c90

Browse files
committed
Fix vector functions
1 parent c010b53 commit 75d8c90

9 files changed

Lines changed: 767 additions & 8 deletions

File tree

src/ConicProgram/ConicProgram.jl

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,15 @@ function MOI.supports_constraint(
148148
return false
149149
end
150150

151+
# Disambiguate when T = Float64
152+
function MOI.supports_constraint(
153+
::Model,
154+
::Type{MOI.VectorAffineFunction{Float64}},
155+
::Type{MOI.PositiveSemidefiniteConeSquare},
156+
)
157+
return false
158+
end
159+
151160
function MOI.set(
152161
model::Model,
153162
::MOI.ConstraintPrimalStart,

src/bridges.jl

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,88 @@ function MOI.set(
104104
return MOI.set(model, attr, bridge.constraint, mapped_func)
105105
end
106106

107+
"""
108+
_square_offset(s::MOI.AbstractSymmetricMatrixSetSquare)
109+
110+
Number of extra entries before the matrix in a square-form set.
111+
Own implementation to avoid depending on the private
112+
`MOI.Bridges.Constraint._square_offset`.
113+
"""
114+
_square_offset(::MOI.AbstractSymmetricMatrixSetSquare) = 0
115+
_square_offset(::MOI.RootDetConeSquare) = 1
116+
_square_offset(::MOI.LogDetConeSquare) = 2
117+
118+
function _square_to_triangle_indices(
119+
bridge::MOI.Bridges.Constraint.SquareBridge,
120+
)
121+
s = bridge.square_set
122+
dim = MOI.side_dimension(s)
123+
offset = _square_offset(s)
124+
upper_triangle_indices = collect(1:offset)
125+
sizehint!(upper_triangle_indices, offset + div(dim * (dim + 1), 2))
126+
k = offset
127+
for j in 1:dim
128+
for i in 1:j
129+
k += 1
130+
push!(upper_triangle_indices, k)
131+
end
132+
k += dim - j
133+
end
134+
return upper_triangle_indices
135+
end
136+
137+
"""
138+
_triangle_to_square_scalars(tri_scalars, s)
139+
140+
Expand triangle-vectorized scalars to square column-major form, mirroring
141+
off-diagonal entries. `s` is the square set (e.g. `PositiveSemidefiniteConeSquare`).
142+
"""
143+
function _triangle_to_square_scalars(tri_scalars, s)
144+
dim = MOI.side_dimension(s)
145+
offset = _square_offset(s)
146+
square_dim = offset + dim * dim
147+
square = Vector{eltype(tri_scalars)}(undef, square_dim)
148+
for i in 1:offset
149+
square[i] = tri_scalars[i]
150+
end
151+
tri_k = offset
152+
for j in 1:dim
153+
for i in 1:j
154+
tri_k += 1
155+
ij = offset + i + (j - 1) * dim
156+
square[ij] = tri_scalars[tri_k]
157+
if i != j
158+
ji = offset + j + (i - 1) * dim
159+
square[ji] = tri_scalars[tri_k]
160+
end
161+
end
162+
end
163+
return square
164+
end
165+
166+
function MOI.set(
167+
model::MOI.ModelLike,
168+
attr::DiffOpt.ForwardConstraintFunction,
169+
bridge::MOI.Bridges.Constraint.SquareBridge{T},
170+
func::MOI.VectorAffineFunction{T},
171+
) where {T}
172+
indices = _square_to_triangle_indices(bridge)
173+
tri_func = MOI.Utilities.eachscalar(func)[indices]
174+
return MOI.set(model, attr, bridge.triangle, tri_func)
175+
end
176+
177+
function MOI.get(
178+
model::MOI.ModelLike,
179+
attr::DiffOpt.ReverseConstraintFunction,
180+
bridge::MOI.Bridges.Constraint.SquareBridge{T},
181+
) where {T}
182+
tri_func_raw = MOI.get(model, attr, bridge.triangle)
183+
tri_func = DiffOpt.standard_form(tri_func_raw)
184+
tri_scalars = MOI.Utilities.eachscalar(tri_func)
185+
square_scalars = _triangle_to_square_scalars(tri_scalars, bridge.square_set)
186+
return MOI.Utilities.operate(vcat, T, square_scalars...)
187+
end
188+
107189
function _variable_to_index_map(bridge)
108190
return Dict{MOI.VariableIndex,MOI.VariableIndex}(
109191
v => MOI.VariableIndex(i) for

src/jump_moi_overloads.jl

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
# done after the model is optimized, so we add function to bypass the
1313
# dirty state.
1414

15+
# DEPRECATE
1516
function MOI.set(
1617
model::JuMP.Model,
1718
attr::ForwardObjectiveFunction,
@@ -37,6 +38,7 @@ function MOI.set(
3738
return MOI.set(JuMP.backend(model), attr, allow)
3839
end
3940

41+
# DEPRECATE
4042
function MOI.set(
4143
model::JuMP.Model,
4244
attr::ForwardObjectiveFunction,
@@ -45,6 +47,7 @@ function MOI.set(
4547
return MOI.set(model, attr, JuMP.AffExpr(func))
4648
end
4749

50+
# DEPRECATE
4851
function MOI.set(
4952
model::JuMP.Model,
5053
attr::ForwardConstraintFunction,
@@ -55,6 +58,7 @@ function MOI.set(
5558
return MOI.set(model, attr, con_ref, JuMP.moi_function(func))
5659
end
5760

61+
# DEPRECATE
5862
function MOI.set(
5963
model::JuMP.Model,
6064
attr::ForwardConstraintFunction,
@@ -64,6 +68,7 @@ function MOI.set(
6468
return MOI.set(model, attr, con_ref, JuMP.AffExpr(func))
6569
end
6670

71+
# DEPRECATE - then modify
6772
function MOI.get(
6873
model::JuMP.Model,
6974
attr::ForwardConstraintDual,
@@ -74,11 +79,13 @@ function MOI.get(
7479
return JuMP.jump_function(model, moi_func)
7580
end
7681

82+
# DEPRECATE - then modify
7783
function MOI.get(model::JuMP.Model, attr::ReverseObjectiveFunction)
7884
func = MOI.get(JuMP.backend(model), attr)
7985
return JuMP.jump_function(model, func)
8086
end
8187

88+
# DEPRECATE - then modify
8289
function MOI.get(
8390
model::JuMP.Model,
8491
attr::ReverseConstraintFunction,
@@ -106,6 +113,7 @@ function _moi_get_result(model::MOI.Utilities.CachingOptimizer, args...)
106113
return MOI.get(model, args...)
107114
end
108115

116+
# DEPRECATE
109117
function MOI.get(
110118
model::JuMP.Model,
111119
attr::ForwardVariablePrimal,
@@ -115,6 +123,7 @@ function MOI.get(
115123
return _moi_get_result(JuMP.backend(model), attr, JuMP.index(var_ref))
116124
end
117125

126+
# REVIEW
118127
function MOI.get(
119128
model::JuMP.Model,
120129
attr::ReverseConstraintSet,
@@ -134,6 +143,9 @@ function MOI.set(
134143
return MOI.set(JuMP.backend(model), attr, JuMP.index(con_ref), set)
135144
end
136145

146+
# there is no set_forward_constraint_set because there is set_forward_parameter
147+
148+
# DEPRECATE
137149
function MOI.set(
138150
model::JuMP.Model,
139151
attr::ForwardConstraintSet,
@@ -255,6 +267,14 @@ function JuMP.coefficient(func::IndexMappedFunction, vi::MOI.VariableIndex)
255267
return JuMP.coefficient(func.func, func.index_map[vi])
256268
end
257269

270+
function JuMP.coefficient(
271+
func::IndexMappedFunction,
272+
vi::MOI.VariableIndex,
273+
output_index::Int,
274+
)
275+
return JuMP.coefficient(func.func, func.index_map[vi], output_index)
276+
end
277+
258278
function quad_sym_half(
259279
func::IndexMappedFunction,
260280
vi1::MOI.VariableIndex,

0 commit comments

Comments
 (0)