14
14
similar_type (:: Type{<:MOI.VectorAffineFunction} , T:: Type ) = MOI. VectorAffineFunction{T}
15
15
16
16
struct SplitZeroBridge{T, F<: MOI.Utilities.TypedLike{T} , G<: MOI.Utilities.TypedLike{Complex{T}} } <: MOI.Bridges.Constraint.AbstractBridge
17
- real:: MOI.ConstraintIndex{F, MOI.Zeros}
18
- imag:: MOI.ConstraintIndex{F, MOI.Zeros}
17
+ dimension:: Int
18
+ constraint:: MOI.ConstraintIndex{F, MOI.Zeros}
19
+ real_indices:: Vector{Int}
20
+ imag_indices:: Vector{Int}
21
+ end
22
+ function _nonzero_indices (func:: MOI.AbstractVectorFunction )
23
+ return [i for (i, scalar_func) in enumerate (MOIU. scalarize (func)) if ! iszero (scalar_func)]
19
24
end
20
25
function MOI. Bridges. Constraint. bridge_constraint (
21
26
:: Type{SplitZeroBridge{T, F, G}} , model:: MOI.ModelLike ,
22
27
f:: G ,
23
28
set:: MOI.Zeros
24
29
) where {T, F, G}
25
- real_con = MOI. add_constraint (model, operate_coefficients (real, T, f), set)
26
- imag_con = MOI. add_constraint (model, operate_coefficients (imag, T, f), set)
27
- return SplitZeroBridge {T, F, G} (real_con, imag_con)
30
+ real_part = operate_coefficients (real, T, f)
31
+ imag_part = operate_coefficients (imag, T, f)
32
+ real_indices = _nonzero_indices (real_part)
33
+ imag_indices = _nonzero_indices (imag_part)
34
+ func = MOIU. operate (
35
+ vcat, T,
36
+ MOIU. eachscalar (real_part)[real_indices],
37
+ MOIU. eachscalar (imag_part)[imag_indices]
38
+ )
39
+ constraint = MOI. add_constraint (model, func, MOI. Zeros (length (real_indices) + length (imag_indices)))
40
+ return SplitZeroBridge {T, F, G} (MOI. dimension (set), constraint, real_indices, imag_indices)
28
41
end
29
42
30
43
function MOI. supports_constraint (
45
58
# Attributes, Bridge acting as a model
46
59
function MOI. get (:: SplitZeroBridge{T, F} ,
47
60
:: MOI.NumberOfConstraints{F, MOI.Zeros} ) where {T, F}
48
- return 2
61
+ return 1
49
62
end
50
63
function MOI. get (bridge:: SplitZeroBridge{T, F} ,
51
64
:: MOI.ListOfConstraintIndices{F, MOI.Zeros} ) where {T, F}
52
- return [bridge. real, bridge . imag ]
65
+ return [bridge. constraint ]
53
66
end
54
67
55
68
# Indices
56
69
function MOI. delete (model:: MOI.ModelLike , bridge:: SplitZeroBridge )
57
- MOI. delete (model, bridge. imag)
58
- MOI. delete (model, bridge. real)
70
+ MOI. delete (model, bridge. constraint)
59
71
end
60
72
61
73
# Attributes, Bridge acting as a constraint
@@ -68,10 +80,24 @@ function MOI.supports(
68
80
end
69
81
function MOI. get (model:: MOI.ModelLike , attr:: Union{MOI.ConstraintPrimal, MOI.ConstraintPrimalStart, MOI.ConstraintDual, MOI.ConstraintDualStart} ,
70
82
bridge:: SplitZeroBridge )
71
- return MOI. get (model, attr, bridge. real) + im * MOI. get (model, attr, bridge. imag)
83
+ values = MOI. get (model, attr, bridge. constraint)
84
+ output = zeros (Complex{eltype (values)}, bridge. dimension)
85
+ for (i, idx) in enumerate (bridge. real_indices)
86
+ output[idx] = values[i]
87
+ end
88
+ for (i, idx) in enumerate (bridge. imag_indices)
89
+ output[idx] = values[length (bridge. real_indices) + i] * im
90
+ end
91
+ return output
72
92
end
73
93
function MOI. set (model:: MOI.ModelLike , attr:: Union{MOI.ConstraintPrimalStart, MOI.ConstraintDualStart} ,
74
- bridge:: SplitZeroBridge , value)
75
- MOI. set (model, attr, bridge. real, map (real, value))
76
- MOI. set (model, attr, bridge. imag, map (imag, value))
94
+ bridge:: SplitZeroBridge{T} , value) where T
95
+ input = Vector {T} (undef, length (bridge. real_indices) + length (bridge. imag_indices))
96
+ for (i, idx) in enumerate (bridge. real_indices)
97
+ input[i] = real (value[idx])
98
+ end
99
+ for (i, idx) in enumerate (bridge. imag_indices)
100
+ input[length (bridge. real_indices) + i] = imag (value[idx])
101
+ end
102
+ MOI. set (model, attr, bridge. constraint, input)
77
103
end
0 commit comments