jump-dev / ComplexOptInterface.jl

@@ -1,54 +1,76 @@
Loading
1 -
struct SplitZeroBridge{T, F<:MOI.Utilities.TypedLike{T}, G<:MOI.Utilities.TypedLike{Complex{T}}} <: MOI.Bridges.Constraint.AbstractBridge
1 +
struct SplitZeroBridge{
2 +
    T,
3 +
    F<:MOI.Utilities.TypedLike{T},
4 +
    G<:MOI.Utilities.TypedLike{Complex{T}},
5 +
} <: MOI.Bridges.Constraint.AbstractBridge
2 6
    dimension::Int
3 -
    constraint::MOI.ConstraintIndex{F, MOI.Zeros}
7 +
    constraint::MOI.ConstraintIndex{F,MOI.Zeros}
4 8
    real_indices::Vector{Int}
5 9
    imag_indices::Vector{Int}
6 10
end
7 11
function _nonzero_indices(func::MOI.AbstractVectorFunction)
8 -
    return [i for (i, scalar_func) in enumerate(MOIU.scalarize(func)) if !iszero(scalar_func)]
12 +
    return [
13 +
        i for (i, scalar_func) in enumerate(MOIU.scalarize(func)) if !iszero(scalar_func)
14 +
    ]
9 15
end
10 16
function MOI.Bridges.Constraint.bridge_constraint(
11 -
    ::Type{SplitZeroBridge{T, F, G}}, model::MOI.ModelLike,
17 +
    ::Type{SplitZeroBridge{T,F,G}},
18 +
    model::MOI.ModelLike,
12 19
    f::G,
13 -
    set::MOI.Zeros
14 -
) where {T, F, G}
20 +
    set::MOI.Zeros,
21 +
) where {T,F,G}
15 22
    real_part = real(f)
16 23
    imag_part = MOI.Utilities.operate(imag, T, f)
17 24
    real_indices = _nonzero_indices(real_part)
18 25
    imag_indices = _nonzero_indices(imag_part)
19 26
    func = MOIU.operate(
20 -
        vcat, T,
27 +
        vcat,
28 +
        T,
21 29
        MOIU.eachscalar(real_part)[real_indices],
22 -
        MOIU.eachscalar(imag_part)[imag_indices]
30 +
        MOIU.eachscalar(imag_part)[imag_indices],
31 +
    )
32 +
    constraint = MOI.add_constraint(
33 +
        model,
34 +
        func,
35 +
        MOI.Zeros(length(real_indices) + length(imag_indices)),
36 +
    )
37 +
    return SplitZeroBridge{T,F,G}(
38 +
        MOI.dimension(set),
39 +
        constraint,
40 +
        real_indices,
41 +
        imag_indices,
23 42
    )
24 -
    constraint = MOI.add_constraint(model, func, MOI.Zeros(length(real_indices) + length(imag_indices)))
25 -
    return SplitZeroBridge{T, F, G}(MOI.dimension(set), constraint, real_indices, imag_indices)
26 43
end
27 44
28 45
# We don't support `MOI.VectorOfVariables` as it would be a self-loop in the bridge graph
29 46
function MOI.supports_constraint(
30 -
    ::Type{SplitZeroBridge{T}}, ::Type{<:MOI.Utilities.TypedLike{Complex{T}}},
31 -
    ::Type{MOI.Zeros}) where T
47 +
    ::Type{SplitZeroBridge{T}},
48 +
    ::Type{<:MOI.Utilities.TypedLike{Complex{T}}},
49 +
    ::Type{MOI.Zeros},
50 +
) where {T}
32 51
    return true
33 52
end
34 53
MOIB.added_constrained_variable_types(::Type{<:SplitZeroBridge}) = Tuple{DataType}[]
35 -
function MOIB.added_constraint_types(::Type{SplitZeroBridge{T, F, G}}) where {T, F, G}
36 -
    return Tuple{DataType, DataType}[(F, MOI.Zeros)]
54 +
function MOIB.added_constraint_types(::Type{SplitZeroBridge{T,F,G}}) where {T,F,G}
55 +
    return Tuple{DataType,DataType}[(F, MOI.Zeros)]
37 56
end
38 57
function MOI.Bridges.Constraint.concrete_bridge_type(
39 -
    ::Type{<:SplitZeroBridge{T}}, G::Type{<:MOI.Utilities.TypedLike},
40 -
    ::Type{MOI.Zeros}) where T
58 +
    ::Type{<:SplitZeroBridge{T}},
59 +
    G::Type{<:MOI.Utilities.TypedLike},
60 +
    ::Type{MOI.Zeros},
61 +
) where {T}
41 62
    F = MA.promote_operation(imag, G)
42 -
    return SplitZeroBridge{T, F, G}
63 +
    return SplitZeroBridge{T,F,G}
43 64
end
44 65
45 66
# Attributes, Bridge acting as a model
46 -
function MOI.get(::SplitZeroBridge{T, F},
47 -
                 ::MOI.NumberOfConstraints{F, MOI.Zeros}) where {T, F}
67 +
function MOI.get(::SplitZeroBridge{T,F}, ::MOI.NumberOfConstraints{F,MOI.Zeros}) where {T,F}
48 68
    return 1
49 69
end
50 -
function MOI.get(bridge::SplitZeroBridge{T, F},
51 -
                 ::MOI.ListOfConstraintIndices{F, MOI.Zeros}) where {T, F}
70 +
function MOI.get(
71 +
    bridge::SplitZeroBridge{T,F},
72 +
    ::MOI.ListOfConstraintIndices{F,MOI.Zeros},
73 +
) where {T,F}
52 74
    return [bridge.constraint]
53 75
end
54 76
@@ -60,31 +82,44 @@
Loading
60 82
# Attributes, Bridge acting as a constraint
61 83
function MOI.supports(
62 84
    ::MOI.ModelLike,
63 -
    ::Union{MOI.ConstraintPrimalStart, MOI.ConstraintDualStart},
64 -
    ::Type{<:SplitZeroBridge})
85 +
    ::Union{MOI.ConstraintPrimalStart,MOI.ConstraintDualStart},
86 +
    ::Type{<:SplitZeroBridge},
87 +
)
65 88
66 89
    return true
67 90
end
68 -
function MOI.get(model::MOI.ModelLike, attr::Union{MOI.ConstraintPrimal, MOI.ConstraintPrimalStart, MOI.ConstraintDual, MOI.ConstraintDualStart},
69 -
                 bridge::SplitZeroBridge)
91 +
function MOI.get(
92 +
    model::MOI.ModelLike,
93 +
    attr::Union{
94 +
        MOI.ConstraintPrimal,
95 +
        MOI.ConstraintPrimalStart,
96 +
        MOI.ConstraintDual,
97 +
        MOI.ConstraintDualStart,
98 +
    },
99 +
    bridge::SplitZeroBridge,
100 +
)
70 101
    values = MOI.get(model, attr, bridge.constraint)
71 102
    output = zeros(Complex{eltype(values)}, bridge.dimension)
72 103
    for (i, idx) in enumerate(bridge.real_indices)
73 104
        output[idx] = values[i]
74 105
    end
75 106
    for (i, idx) in enumerate(bridge.imag_indices)
76 -
        output[idx] = values[length(bridge.real_indices) + i] * im
107 +
        output[idx] = values[length(bridge.real_indices)+i] * im
77 108
    end
78 109
    return output
79 110
end
80 -
function MOI.set(model::MOI.ModelLike, attr::Union{MOI.ConstraintPrimalStart, MOI.ConstraintDualStart},
81 -
                 bridge::SplitZeroBridge{T}, value) where T
111 +
function MOI.set(
112 +
    model::MOI.ModelLike,
113 +
    attr::Union{MOI.ConstraintPrimalStart,MOI.ConstraintDualStart},
114 +
    bridge::SplitZeroBridge{T},
115 +
    value,
116 +
) where {T}
82 117
    input = Vector{T}(undef, length(bridge.real_indices) + length(bridge.imag_indices))
83 118
    for (i, idx) in enumerate(bridge.real_indices)
84 119
        input[i] = real(value[idx])
85 120
    end
86 121
    for (i, idx) in enumerate(bridge.imag_indices)
87 -
        input[length(bridge.real_indices) + i] = imag(value[idx])
122 +
        input[length(bridge.real_indices)+i] = imag(value[idx])
88 123
    end
89 124
    MOI.set(model, attr, bridge.constraint, input)
90 125
end

@@ -1,4 +1,4 @@
Loading
1 -
const EQ{T} = MOI.ConstraintIndex{MOI.ScalarAffineFunction{T}, MOI.EqualTo{T}}
1 +
const EQ{T} = MOI.ConstraintIndex{MOI.ScalarAffineFunction{T},MOI.EqualTo{T}}
2 2
3 3
"""
4 4
Let `H = HermitianToSymmetricPSDBridge(n)`, `S = PositiveSemidefiniteConeTriangle(2n)`
@@ -37,18 +37,24 @@
Loading
37 37
"""
38 38
struct HermitianToSymmetricPSDBridge{T} <: MOIB.Variable.AbstractBridge
39 39
    variables::Vector{MOI.VariableIndex}
40 -
    psd_constraint::MOI.ConstraintIndex{MOI.VectorOfVariables, MOI.PositiveSemidefiniteConeTriangle}
40 +
    psd_constraint::MOI.ConstraintIndex{
41 +
        MOI.VectorOfVariables,
42 +
        MOI.PositiveSemidefiniteConeTriangle,
43 +
    }
41 44
    con_11_22::Vector{EQ{T}}
42 45
    con12diag::Vector{EQ{T}}
43 46
    con_12_21::Vector{EQ{T}}
44 47
end
45 48
46 49
function MOIB.Variable.bridge_constrained_variable(
47 -
    ::Type{HermitianToSymmetricPSDBridge{T}}, model::MOI.ModelLike,
48 -
    set::COI.HermitianPositiveSemidefiniteConeTriangle) where T
50 +
    ::Type{HermitianToSymmetricPSDBridge{T}},
51 +
    model::MOI.ModelLike,
52 +
    set::COI.HermitianPositiveSemidefiniteConeTriangle,
53 +
) where {T}
49 54
50 55
    n = set.side_dimension
51 -
    variables, psd_constraint = MOI.add_constrained_variables(model, MOI.PositiveSemidefiniteConeTriangle(2n))
56 +
    variables, psd_constraint =
57 +
        MOI.add_constrained_variables(model, MOI.PositiveSemidefiniteConeTriangle(2n))
52 58
53 59
    k11 = 0
54 60
    k12 = MOI.dimension(MOI.PositiveSemidefiniteConeTriangle(n))
@@ -66,33 +72,62 @@
Loading
66 72
    con_11_22 = EQ{T}[]
67 73
    con12diag = EQ{T}[]
68 74
    con_12_21 = EQ{T}[]
69 -
    for j in 1:n
75 +
    for j = 1:n
70 76
        k22 += n
71 -
        for i in 1:j
77 +
        for i = 1:j
72 78
            k11 += 1
73 79
            k12 += 1
74 80
            k22 += 1
75 -
            push!(con_11_22, MOI.add_constraint(model, MOI.Utilities.operate(-, T, X11(), X22()), MOI.EqualTo(zero(T))))
81 +
            push!(
82 +
                con_11_22,
83 +
                MOI.add_constraint(
84 +
                    model,
85 +
                    MOI.Utilities.operate(-, T, X11(), X22()),
86 +
                    MOI.EqualTo(zero(T)),
87 +
                ),
88 +
            )
76 89
            if i == j
77 -
                push!(con12diag, MOI.add_constraint(model, convert(MOI.ScalarAffineFunction{T}, X12()), MOI.EqualTo(zero(T))))
90 +
                push!(
91 +
                    con12diag,
92 +
                    MOI.add_constraint(
93 +
                        model,
94 +
                        convert(MOI.ScalarAffineFunction{T}, X12()),
95 +
                        MOI.EqualTo(zero(T)),
96 +
                    ),
97 +
                )
78 98
            else
79 -
                push!(con_12_21, MOI.add_constraint(model, MOI.Utilities.operate(+, T, X21(i, j), X12()), MOI.EqualTo(zero(T))))
99 +
                push!(
100 +
                    con_12_21,
101 +
                    MOI.add_constraint(
102 +
                        model,
103 +
                        MOI.Utilities.operate(+, T, X21(i, j), X12()),
104 +
                        MOI.EqualTo(zero(T)),
105 +
                    ),
106 +
                )
80 107
            end
81 108
        end
82 109
        k12 += n
83 110
    end
84 111
85 -
    return HermitianToSymmetricPSDBridge(variables, psd_constraint, con_11_22, con12diag, con_12_21)
112 +
    return HermitianToSymmetricPSDBridge(
113 +
        variables,
114 +
        psd_constraint,
115 +
        con_11_22,
116 +
        con12diag,
117 +
        con_12_21,
118 +
    )
86 119
end
87 120
88 121
function MOIB.Variable.supports_constrained_variable(
89 -
    ::Type{<:HermitianToSymmetricPSDBridge}, ::Type{COI.HermitianPositiveSemidefiniteConeTriangle})
122 +
    ::Type{<:HermitianToSymmetricPSDBridge},
123 +
    ::Type{COI.HermitianPositiveSemidefiniteConeTriangle},
124 +
)
90 125
    return true
91 126
end
92 127
function MOIB.added_constrained_variable_types(::Type{<:HermitianToSymmetricPSDBridge})
93 128
    return [(MOI.PositiveSemidefiniteConeTriangle,)]
94 129
end
95 -
function MOIB.added_constraint_types(::Type{HermitianToSymmetricPSDBridge{T}}) where T
130 +
function MOIB.added_constraint_types(::Type{HermitianToSymmetricPSDBridge{T}}) where {T}
96 131
    return [(MOI.ScalarAffineFunction{T}, MOI.EqualTo{T})]
97 132
end
98 133
@@ -103,22 +138,31 @@
Loading
103 138
function MOI.get(bridge::HermitianToSymmetricPSDBridge, ::MOI.ListOfVariableIndices)
104 139
    return bridge.variables
105 140
end
106 -
function MOI.get(bridge::HermitianToSymmetricPSDBridge,
107 -
                 ::MOI.NumberOfConstraints{MOI.VectorOfVariables, MOI.PositiveSemidefiniteConeTriangle})
141 +
function MOI.get(
142 +
    bridge::HermitianToSymmetricPSDBridge,
143 +
    ::MOI.NumberOfConstraints{MOI.VectorOfVariables,MOI.PositiveSemidefiniteConeTriangle},
144 +
)
108 145
    return 1
109 146
end
110 -
function MOI.get(bridge::HermitianToSymmetricPSDBridge,
111 -
                 ::MOI.ListOfConstraintIndices{MOI.VectorOfVariables, MOI.PositiveSemidefiniteConeTriangle})
147 +
function MOI.get(
148 +
    bridge::HermitianToSymmetricPSDBridge,
149 +
    ::MOI.ListOfConstraintIndices{
150 +
        MOI.VectorOfVariables,
151 +
        MOI.PositiveSemidefiniteConeTriangle,
152 +
    },
153 +
)
112 154
    return [bridge.psd_constraint]
113 155
end
114 -
function MOI.get(bridge::HermitianToSymmetricPSDBridge{T},
115 -
                 ::MOI.NumberOfConstraints{MOI.ScalarAffineFunction{T},
116 -
                                           MOI.EqualTo{T}}) where T
156 +
function MOI.get(
157 +
    bridge::HermitianToSymmetricPSDBridge{T},
158 +
    ::MOI.NumberOfConstraints{MOI.ScalarAffineFunction{T},MOI.EqualTo{T}},
159 +
) where {T}
117 160
    return length(bridge.con_11_22) + length(bridge.con12diag) + length(bridge.con_12_21)
118 161
end
119 -
function MOI.get(bridge::HermitianToSymmetricPSDBridge{T},
120 -
                 ::MOI.ListOfConstraintIndices{MOI.ScalarAffineFunction{T},
121 -
                                               MOI.EqualTo{T}}) where T
162 +
function MOI.get(
163 +
    bridge::HermitianToSymmetricPSDBridge{T},
164 +
    ::MOI.ListOfConstraintIndices{MOI.ScalarAffineFunction{T},MOI.EqualTo{T}},
165 +
) where {T}
122 166
    return [bridge.con_11_22; bridge.con12diag; bridge.con_12_21]
123 167
end
124 168
@@ -138,8 +182,11 @@
Loading
138 182
139 183
# Attributes, Bridge acting as a constraint
140 184
141 -
function MOI.get(model::MOI.ModelLike, ::MOI.ConstraintSet,
142 -
                 bridge::HermitianToSymmetricPSDBridge)
185 +
function MOI.get(
186 +
    model::MOI.ModelLike,
187 +
    ::MOI.ConstraintSet,
188 +
    bridge::HermitianToSymmetricPSDBridge,
189 +
)
143 190
    return COI.HermitianPositiveSemidefiniteConeTriangle(length(bridge.con12diag))
144 191
end
145 192
@@ -172,18 +219,24 @@
Loading
172 219
    return bridge.variables[_variable_map(i, length(bridge.con12diag))]
173 220
end
174 221
175 -
function MOI.get(model::MOI.ModelLike, attr::MOI.ConstraintPrimal,
176 -
                 bridge::HermitianToSymmetricPSDBridge{T}) where T
222 +
function MOI.get(
223 +
    model::MOI.ModelLike,
224 +
    attr::MOI.ConstraintPrimal,
225 +
    bridge::HermitianToSymmetricPSDBridge{T},
226 +
) where {T}
177 227
    values = MOI.get(model, attr, bridge.psd_constraint)
178 228
    M = MOI.dimension(MOI.get(model, MOI.ConstraintSet(), bridge))
179 229
    n = length(bridge.con12diag)
180 -
    return [values[_variable_map(MOIB.IndexInVector(i), n)] for i in 1:M]
230 +
    return [values[_variable_map(MOIB.IndexInVector(i), n)] for i = 1:M]
181 231
end
182 232
183 233
# See docstring of bridge for why we ignore the dual of the constraints
184 234
# `con_11_22`, `con_12_21` and `con12diag`.
185 -
function MOI.get(model::MOI.ModelLike, attr::MOI.ConstraintDual,
186 -
                 bridge::HermitianToSymmetricPSDBridge{T}) where T
235 +
function MOI.get(
236 +
    model::MOI.ModelLike,
237 +
    attr::MOI.ConstraintDual,
238 +
    bridge::HermitianToSymmetricPSDBridge{T},
239 +
) where {T}
187 240
    dual = MOI.get(model, attr, bridge.psd_constraint)
188 241
    M = MOI.dimension(MOI.get(model, MOI.ConstraintSet(), bridge))
189 242
    mapped = zeros(T, M)
@@ -194,10 +247,10 @@
Loading
194 247
    k21 = MOI.dimension(MOI.PositiveSemidefiniteConeTriangle(2n)) + 1
195 248
    k22 = N
196 249
    k = 0
197 -
    for j in 1:n
250 +
    for j = 1:n
198 251
        k21 -= n + 1 - j
199 252
        k22 += n
200 -
        for i in 1:j
253 +
        for i = 1:j
201 254
            k11 += 1
202 255
            k12 += 1
203 256
            k21 -= 1
@@ -206,8 +259,8 @@
Loading
206 259
            mapped[k11] += dual[k22]
207 260
            if i != j
208 261
                k += 1
209 -
                mapped[N + k] += dual[k12]
210 -
                mapped[N + k] -= dual[k21]
262 +
                mapped[N+k] += dual[k12]
263 +
                mapped[N+k] -= dual[k21]
211 264
            end
212 265
        end
213 266
        k12 += n
@@ -216,17 +269,27 @@
Loading
216 269
    return mapped
217 270
end
218 271
219 -
function MOI.get(model::MOI.ModelLike, attr::MOI.VariablePrimal,
220 -
                 bridge::HermitianToSymmetricPSDBridge{T}, i::MOIB.IndexInVector) where T
272 +
function MOI.get(
273 +
    model::MOI.ModelLike,
274 +
    attr::MOI.VariablePrimal,
275 +
    bridge::HermitianToSymmetricPSDBridge{T},
276 +
    i::MOIB.IndexInVector,
277 +
) where {T}
221 278
    value = MOI.get(model, attr, _variable(bridge, i))
222 279
end
223 280
224 -
function MOIB.bridged_function(bridge::HermitianToSymmetricPSDBridge{T}, i::MOIB.IndexInVector) where T
281 +
function MOIB.bridged_function(
282 +
    bridge::HermitianToSymmetricPSDBridge{T},
283 +
    i::MOIB.IndexInVector,
284 +
) where {T}
225 285
    func = _variable(bridge, i)
226 286
    return convert(MOI.ScalarAffineFunction{T}, func)
227 287
end
228 -
function MOIB.Variable.unbridged_map(bridge::HermitianToSymmetricPSDBridge{T}, vi::MOI.VariableIndex,
229 -
                       i::MOIB.IndexInVector) where T
288 +
function MOIB.Variable.unbridged_map(
289 +
    bridge::HermitianToSymmetricPSDBridge{T},
290 +
    vi::MOI.VariableIndex,
291 +
    i::MOIB.IndexInVector,
292 +
) where {T}
230 293
    func = convert(MOI.ScalarAffineFunction{T}, vi)
231 294
    return (_variable(bridge, i) => func,)
232 295
end

@@ -11,14 +11,17 @@
Loading
11 11
end
12 12
function MOI.dimension(set::HermitianPositiveSemidefiniteConeTriangle)
13 13
    return MOI.dimension(MOI.PositiveSemidefiniteConeTriangle(set.side_dimension)) +
14 -
        MOI.dimension(MOI.PositiveSemidefiniteConeTriangle(set.side_dimension - 1))
14 +
           MOI.dimension(MOI.PositiveSemidefiniteConeTriangle(set.side_dimension - 1))
15 15
end
16 16
17 -
function MOI.Utilities.set_dot(x::AbstractVector, y::AbstractVector,
18 -
                               set::HermitianPositiveSemidefiniteConeTriangle)
17 +
function MOI.Utilities.set_dot(
18 +
    x::AbstractVector,
19 +
    y::AbstractVector,
20 +
    set::HermitianPositiveSemidefiniteConeTriangle,
21 +
)
19 22
    sym = MOI.PositiveSemidefiniteConeTriangle(set.side_dimension)
20 23
    result = MOI.Utilities.set_dot(x, y, sym)
21 -
    for k in (MOI.dimension(sym) + 1):MOI.dimension(set)
24 +
    for k = (MOI.dimension(sym)+1):MOI.dimension(set)
22 25
        result = MA.add_mul!!(result, 2, x[k], y[k])
23 26
    end
24 27
    return result
Files Coverage
src 79.04%
Project Totals (3 files) 79.04%
Sunburst
The inner-most circle is the entire project, moving away from the center are folders then, finally, a single file. The size and color of each slice is representing the number of statements and the coverage, respectively.
Icicle
The top section represents the entire project. Proceeding with folders and finally individual files. The size and color of each slice is representing the number of statements and the coverage, respectively.
Grid
Each block represents a single file in the project. The size and color of each block is represented by the number of statements and the coverage, respectively.
Loading