Skip to content

Commit 1da3d2a

Browse files
committed
add possible fix to scalarize bridge error
1 parent 4448a46 commit 1da3d2a

File tree

3 files changed

+62
-0
lines changed

3 files changed

+62
-0
lines changed

src/bridges.jl

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,27 @@ function MOI.get(
4343
MOI.get(model, attr, bridge.vector_constraint),
4444
)[1]
4545
end
46+
47+
function MOI.set(
48+
model::MOI.ModelLike,
49+
attr::ForwardConstraintFunction,
50+
bridge::MOI.Bridges.Constraint.ScalarizeBridge{T},
51+
value,
52+
) where {T}
53+
MOI.set.(model, attr, bridge.scalar_constraints, value)
54+
return
55+
end
56+
57+
function MOI.get(
58+
model::MOI.ModelLike,
59+
attr::ReverseConstraintFunction,
60+
bridge::MOI.Bridges.Constraint.ScalarizeBridge,
61+
)
62+
return _vectorize(
63+
MOI.get.(model, attr, bridge.scalar_constraints),
64+
)
65+
end
66+
4667
function MOI.get(
4768
model::MOI.ModelLike,
4869
attr::DiffOpt.ReverseConstraintFunction,

src/utils.jl

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33
# Use of this source code is governed by an MIT-style license that can be found
44
# in the LICENSE.md file or at https://opensource.org/licenses/MIT.
55

6+
# Helpers for objective function
7+
68
# Representation of MOI functions using SparseArrays
79
# Might be able to replace in the future by a function in MOI, see
810
# https://github.com/jump-dev/MathOptInterface.jl/pull/1238
@@ -152,6 +154,8 @@ function sparse_array_representation(
152154
)
153155
end
154156

157+
# Helpers for scalar constraints
158+
155159
# In the future, we could replace by https://github.com/jump-dev/MathOptInterface.jl/pull/1238
156160
"""
157161
VectorScalarAffineFunction{T, VT} <: MOI.AbstractScalarFunction
@@ -228,6 +232,8 @@ function JuMP.coefficient(
228232
return JuMP.coefficient(func.affine, vi)
229233
end
230234

235+
# Helpers for Vector constraints
236+
231237
"""
232238
MatrixVectorAffineFunction{T, VT} <: MOI.AbstractVectorFunction
233239
@@ -260,6 +266,17 @@ function standard_form(func::MatrixVectorAffineFunction{T}) where {T}
260266
return convert(MOI.VectorAffineFunction{T}, func)
261267
end
262268

269+
_get_terms(f::VectorScalarAffineFunction) = f.terms
270+
_get_constant(f::VectorScalarAffineFunction) = f.constant
271+
function _vectorize(vec::Vector{T}) where {T<:VectorScalarAffineFunction}
272+
terms = LazyArrays.@~ LazyArrays.ApplyArray(hcat, _get_terms.(vec)...)'
273+
constants = LazyArrays.ApplyArray(vcat, _get_constant.(vec)...)
274+
AT = typeof(terms)
275+
VT = typeof(constants)
276+
ret = MatrixVectorAffineFunction{AT,VT}(terms, constants)
277+
return ret
278+
end
279+
263280
# Only used for testing at the moment so performance is not critical so
264281
# converting to standard form is ok
265282
function MOIU.isapprox_zero(

test/parameters.jl

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -646,6 +646,30 @@ function test_diff_errors()
646646
return
647647
end
648648

649+
function test_scalarize_bridge()
650+
using JuMP, DiffOpt, HiGHS
651+
652+
b = [1.0, 2.0]
653+
654+
m = Model(
655+
() -> DiffOpt.diff_optimizer(
656+
HiGHS.Optimizer;
657+
with_parametric_opt_interface = true,
658+
),
659+
)
660+
@variable(m, x[1:2] >= 0)
661+
@variable(m, c[1:2] in MOI.Parameter.(b))
662+
@constraint(m, con, x <= c)
663+
@objective(m, Max, sum(x))
664+
optimize!(m)
665+
666+
MOI.set(m, DiffOpt.ReverseVariablePrimal(), m[:x][1], 1.0)
667+
DiffOpt.reverse_differentiate!(m)
668+
@test MOI.get.(m, DiffOpt.ReverseConstraintSet(), ParameterRef.(c)) == [1, 0]
669+
670+
return
671+
end
672+
649673
end # module
650674

651675
TestParameters.runtests()

0 commit comments

Comments
 (0)