Skip to content

Commit 3b336ac

Browse files
authored
Merge branch 'master' into bl/hessian_forward
2 parents db7de82 + 355a039 commit 3b336ac

30 files changed

+352
-113
lines changed

.github/workflows/format_check.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ jobs:
1818
shell: julia --color=yes {0}
1919
run: |
2020
using Pkg
21-
Pkg.add(PackageSpec(name="JuliaFormatter", version="1"))
21+
Pkg.add(PackageSpec(name="JuliaFormatter", version="2"))
2222
using JuliaFormatter
2323
format(".", verbose=true)
2424
out = String(read(Cmd(`git diff`)))

src/Bridges/Constraint/Constraint.jl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ function add_all_bridges(model, ::Type{T}) where {T}
5656
end
5757
MOI.Bridges.add_bridge(model, GreaterToLessBridge{T})
5858
MOI.Bridges.add_bridge(model, HermitianToSymmetricPSDBridge{T})
59+
MOI.Bridges.add_bridge(model, HermitianToComplexSymmetricBridge{T})
5960
MOI.Bridges.add_bridge(model, IndicatorActiveOnFalseBridge{T})
6061
MOI.Bridges.add_bridge(model, IndicatorGreaterToLessThanBridge{T})
6162
MOI.Bridges.add_bridge(model, IndicatorLessToGreaterThanBridge{T})

src/Bridges/Constraint/bridges/BinPackingToMILPBridge.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -227,7 +227,7 @@ function MOI.Bridges.final_touch(
227227
end
228228
unit_f = MOI.ScalarAffineFunction(MOI.ScalarAffineTerm{T}[], zero(T))
229229
convex_f = MOI.ScalarAffineFunction(MOI.ScalarAffineTerm{T}[], zero(T))
230-
for xi in ret[1]::T:ret[2]::T
230+
for xi in (ret[1]::T):(ret[2]::T)
231231
new_var, _ = MOI.add_constrained_variable(model, MOI.ZeroOne())
232232
push!(bridge.variables, new_var)
233233
if !haskey(S, xi)

src/Bridges/Constraint/bridges/CircuitToMILPBridge.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ function bridge_constraint(
5656
s::MOI.Circuit,
5757
) where {T,F<:Union{MOI.VectorOfVariables,MOI.VectorAffineFunction{T}}}
5858
n = MOI.dimension(s)
59-
z = [MOI.add_constrained_variable(model, MOI.ZeroOne())[1] for _ in 1:n^2]
59+
z = [MOI.add_constrained_variable(model, MOI.ZeroOne())[1] for _ in 1:(n^2)]
6060
Z = reshape(z, n, n)
6161
equal_to = MOI.ConstraintIndex{MOI.ScalarAffineFunction{T},MOI.EqualTo{T}}[]
6262
for (i, x) in enumerate(MOI.Utilities.eachscalar(f))

src/Bridges/Constraint/bridges/CountDistinctToMILPBridge.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -375,7 +375,7 @@ function _final_touch_general_case(
375375
end
376376
unit_f = MOI.ScalarAffineFunction(MOI.ScalarAffineTerm{T}[], zero(T))
377377
convex_f = MOI.ScalarAffineFunction(MOI.ScalarAffineTerm{T}[], zero(T))
378-
for xi in ret[1]::T:ret[2]::T
378+
for xi in (ret[1]::T):(ret[2]::T)
379379
new_var, _ = MOI.add_constrained_variable(model, MOI.ZeroOne())
380380
push!(bridge.variables, new_var)
381381
if !haskey(S, xi)

src/Bridges/Constraint/bridges/CountGreaterThanToMILPBridge.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -214,7 +214,7 @@ function _add_unit_expansion(
214214
end
215215
unit_f = MOI.ScalarAffineFunction(MOI.ScalarAffineTerm{T}[], zero(T))
216216
convex_f = MOI.ScalarAffineFunction(MOI.ScalarAffineTerm{T}[], zero(T))
217-
for xi in ret[1]::T:ret[2]::T
217+
for xi in (ret[1]::T):(ret[2]::T)
218218
new_var, _ = MOI.add_constrained_variable(model, MOI.ZeroOne())
219219
push!(bridge.variables, new_var)
220220
if !haskey(S, xi)
Lines changed: 165 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,165 @@
1+
# Copyright (c) 2017: Miles Lubin and contributors
2+
# Copyright (c) 2017: Google Inc.
3+
#
4+
# Use of this source code is governed by an MIT-style license that can be found
5+
# in the LICENSE.md file or at https://opensource.org/licenses/MIT.
6+
7+
"""
8+
HermitianToComplexSymmetricBridge{T,F,G} <: Bridges.Constraint.AbstractBridge
9+
10+
`HermitianToSymmetricBridge` implements the following reformulation:
11+
12+
* Hermitian positive semidefinite `n x n` represented as a vector of real
13+
entries with real and imaginary parts on different entries to a vector
14+
of complex entries.
15+
16+
See also [`MOI.Bridges.Constraint.HermitianToSymmetricPSDBridge`](@ref).
17+
18+
## Source node
19+
20+
`HermitianToComplexSymmetricBridge` supports:
21+
22+
* `G` in [`MOI.HermitianPositiveSemidefiniteConeTriangle`](@ref)
23+
24+
## Target node
25+
26+
`HermitianToComplexSymmetricBridge` creates:
27+
28+
* `F` in [`MOI.PositiveSemidefiniteConeTriangle`](@ref)
29+
30+
Note that if `G` is `MOI.VectorAffineFunction{T}` then `F` will be
31+
`MOI.VectorAffineFunction{Complex{T}}`
32+
"""
33+
struct HermitianToComplexSymmetricBridge{T,F,G} <: SetMapBridge{
34+
T,
35+
MOI.PositiveSemidefiniteConeTriangle,
36+
MOI.HermitianPositiveSemidefiniteConeTriangle,
37+
F,
38+
G,
39+
}
40+
constraint::MOI.ConstraintIndex{F,MOI.PositiveSemidefiniteConeTriangle}
41+
end
42+
43+
const HermitianToComplexSymmetric{T,OT<:MOI.ModelLike} =
44+
SingleBridgeOptimizer{HermitianToComplexSymmetricBridge{T},OT}
45+
46+
# Should be favored over `HermitianToSymmetricPSDBridge`
47+
MOI.Bridges.bridging_cost(::Type{<:HermitianToComplexSymmetricBridge}) = 0.5
48+
49+
function _promote_complex_vcat(::Type{T}, ::Type{G}) where {T<:Real,G}
50+
S = MOI.Utilities.scalar_type(G)
51+
if S === T
52+
M = Complex{T}
53+
elseif S <: MOI.Utilities.TypedLike{T}
54+
M = MOI.Utilities.similar_type(S, Complex{T})
55+
else
56+
M = MOI.Utilities.promote_operation(*, Complex{T}, Complex{T}, S)
57+
end
58+
return MOI.Utilities.promote_operation(vcat, Complex{T}, M)
59+
end
60+
61+
function concrete_bridge_type(
62+
::Type{<:HermitianToComplexSymmetricBridge{T}},
63+
G::Type{<:MOI.AbstractVectorFunction},
64+
::Type{MOI.HermitianPositiveSemidefiniteConeTriangle},
65+
) where {T}
66+
F = _promote_complex_vcat(T, G)
67+
return HermitianToComplexSymmetricBridge{T,F,G}
68+
end
69+
70+
function MOI.Bridges.map_set(
71+
::Type{<:HermitianToComplexSymmetricBridge},
72+
set::MOI.HermitianPositiveSemidefiniteConeTriangle,
73+
)
74+
return MOI.PositiveSemidefiniteConeTriangle(set.side_dimension)
75+
end
76+
77+
function MOI.Bridges.inverse_map_set(
78+
::Type{<:HermitianToComplexSymmetricBridge},
79+
set::MOI.PositiveSemidefiniteConeTriangle,
80+
)
81+
return MOI.HermitianPositiveSemidefiniteConeTriangle(set.side_dimension)
82+
end
83+
84+
function MOI.Bridges.map_function(
85+
::Type{<:HermitianToComplexSymmetricBridge{T}},
86+
func,
87+
) where {T}
88+
complex_scalars = MOI.Utilities.eachscalar(func)
89+
S = MOI.Utilities.scalar_type(_promote_complex_vcat(T, typeof(func)))
90+
complex_dim = length(complex_scalars)
91+
complex_set = MOI.Utilities.set_with_dimension(
92+
MOI.HermitianPositiveSemidefiniteConeTriangle,
93+
complex_dim,
94+
)
95+
n = complex_set.side_dimension
96+
real_set = MOI.PositiveSemidefiniteConeTriangle(n)
97+
real_dim = MOI.dimension(real_set)
98+
real_scalars = Vector{S}(undef, real_dim)
99+
real_index = 0
100+
imag_index = real_dim
101+
for j in 1:n
102+
for i in 1:j
103+
real_index += 1
104+
if i == j
105+
real_scalars[real_index] = complex_scalars[real_index]
106+
else
107+
imag_index += 1
108+
real_scalars[real_index] =
109+
one(Complex{T}) * complex_scalars[real_index] +
110+
(one(T) * im) * complex_scalars[imag_index]
111+
end
112+
end
113+
end
114+
@assert length(real_scalars) == real_index
115+
@assert length(complex_scalars) == imag_index
116+
return MOI.Utilities.vectorize(real_scalars)
117+
end
118+
119+
function MOI.Bridges.inverse_adjoint_map_function(
120+
BT::Type{<:HermitianToComplexSymmetricBridge},
121+
func,
122+
)
123+
return MOI.Bridges.map_function(BT, func)
124+
end
125+
126+
function MOI.Bridges.inverse_map_function(
127+
::Type{<:HermitianToComplexSymmetricBridge},
128+
func,
129+
)
130+
real_scalars = MOI.Utilities.eachscalar(func)
131+
real_set = MOI.Utilities.set_with_dimension(
132+
MOI.PositiveSemidefiniteConeTriangle,
133+
length(real_scalars),
134+
)
135+
n = real_set.side_dimension
136+
complex_set = MOI.HermitianPositiveSemidefiniteConeTriangle(n)
137+
complex_scalars = Vector{
138+
MA.promote_operation(real, MOI.Utilities.scalar_type(typeof(func))),
139+
}(
140+
undef,
141+
MOI.dimension(complex_set),
142+
)
143+
real_index = 0
144+
imag_index = MOI.dimension(real_set)
145+
for j in 1:n
146+
for i in 1:j
147+
real_index += 1
148+
complex_scalars[real_index] = real(real_scalars[real_index])
149+
if i != j
150+
imag_index += 1
151+
complex_scalars[imag_index] = imag(real_scalars[real_index])
152+
end
153+
end
154+
end
155+
@assert length(real_scalars) == real_index
156+
@assert length(complex_scalars) == imag_index
157+
return MOI.Utilities.vectorize(complex_scalars)
158+
end
159+
160+
function MOI.Bridges.adjoint_map_function(
161+
BT::Type{<:HermitianToComplexSymmetricBridge},
162+
func,
163+
)
164+
return MOI.Bridges.inverse_map_function(BT, func)
165+
end

src/Bridges/Constraint/bridges/HermitianToSymmetricPSDBridge.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -153,7 +153,7 @@ function MOI.Bridges.map_function(
153153
end
154154

155155
function MOI.Bridges.inverse_map_function(
156-
BT::Type{<:HermitianToSymmetricPSDBridge},
156+
::Type{<:HermitianToSymmetricPSDBridge},
157157
func,
158158
)
159159
real_scalars = MOI.Utilities.eachscalar(func)

src/Bridges/Constraint/bridges/LogDetBridge.jl

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -31,15 +31,15 @@ function _extract_eigenvalues(
3131
f_scalars = MOI.Utilities.eachscalar(f)
3232
tu = [f_scalars[i] for i in 1:offset]
3333
n = MOI.Utilities.trimap(d, d)
34-
X = f_scalars[offset.+(1:n)]
34+
X = f_scalars[offset .+ (1:n)]
3535
N = MOI.Utilities.trimap(2d, 2d)
3636
Δ = MOI.add_variables(model, n)
3737
Z = [zero(MOI.ScalarAffineFunction{T}) for i in 1:(N-n)]
3838
for j in 1:d
3939
for i in j:d
40-
Z[MOI.Utilities.trimap(i, d + j)-n] = Δ[MOI.Utilities.trimap(i, j)]
40+
Z[MOI.Utilities.trimap(i, d+j)-n] = Δ[MOI.Utilities.trimap(i, j)]
4141
end
42-
Z[MOI.Utilities.trimap(d + j, d + j)-n] = Δ[MOI.Utilities.trimap(j, j)]
42+
Z[MOI.Utilities.trimap(d+j, d+j)-n] = Δ[MOI.Utilities.trimap(j, j)]
4343
end
4444
Y = MOI.Utilities.operate(vcat, T, X, MOI.Utilities.vectorize(Z))
4545
set = MOI.PositiveSemidefiniteConeTriangle(2d)

src/Bridges/Constraint/bridges/ReifiedCountDistinctToMILPBridge.jl

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -212,7 +212,7 @@ function MOI.get(
212212
)
213213
return MOI.ConstraintIndex{MOI.VariableIndex,MOI.ZeroOne}[
214214
MOI.ConstraintIndex{MOI.VariableIndex,MOI.ZeroOne}(x.value) for
215-
x in bridge.variables[1:end-2]
215+
x in bridge.variables[1:(end-2)]
216216
]
217217
end
218218

@@ -279,7 +279,7 @@ function MOI.Bridges.final_touch(
279279
end
280280
unit_f = MOI.ScalarAffineFunction(MOI.ScalarAffineTerm{T}[], zero(T))
281281
convex_f = MOI.ScalarAffineFunction(MOI.ScalarAffineTerm{T}[], zero(T))
282-
for xi in ret[1]::T:ret[2]::T
282+
for xi in (ret[1]::T):(ret[2]::T)
283283
new_var, _ = MOI.add_constrained_variable(model, MOI.ZeroOne())
284284
push!(bridge.variables, new_var)
285285
if !haskey(S, xi)

src/Bridges/Constraint/bridges/SetDotScalingBridge.jl

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -194,10 +194,10 @@ end
194194
# for `SetMapBridge` does not work
195195
function MOI.supports_constraint(
196196
::Type{<:SetDotScalingBridge},
197-
::Type{<:MOI.AbstractVectorFunction},
197+
F::Type{<:MOI.AbstractVectorFunction},
198198
S::Type{<:MOI.AbstractVectorSet},
199199
)
200-
return MOI.is_set_dot_scaled(S)
200+
return !MOI.Utilities.is_complex(F) && MOI.is_set_dot_scaled(S)
201201
end
202202

203203
function MOI.supports_constraint(

src/Bridges/Constraint/map.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -239,7 +239,7 @@ function vector_of_variables_constraints(map::Map)
239239
Base.Iterators.Filter(
240240
i ->
241241
map.bridges[i] !== nothing &&
242-
map.constraint_types[i][1] == MOI.VectorOfVariables,
242+
map.constraint_types[i][1] == MOI.VectorOfVariables,
243243
eachindex(map.bridges),
244244
),
245245
)

src/Bridges/Variable/bridges/FreeBridge.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,7 @@ function MOI.get(
105105
) where {T}
106106
n = div(length(bridge.variables), 2)
107107
primal = MOI.get(model, attr, bridge.constraint)
108-
return primal[1:n] - primal[n.+(1:n)]
108+
return primal[1:n] - primal[n .+ (1:n)]
109109
end
110110

111111
# The transformation is x_free = [I -I] * x

src/Bridges/Variable/map.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -553,7 +553,7 @@ variables corresponding to `ci`.
553553
function function_for(map::Map, ci::MOI.ConstraintIndex{MOI.VectorOfVariables})
554554
index = map.vector_of_variables_map[-ci.value]
555555
variables = MOI.VariableIndex[]
556-
for i in index:-1:-length(map.bridges)
556+
for i in index:-1:(-length(map.bridges))
557557
vi = MOI.VariableIndex(i)
558558
if map.index_in_vector[-vi.value] == -1
559559
continue

src/Bridges/bridge_optimizer.jl

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -735,7 +735,7 @@ function _get_all_including_bridged(
735735
# function, so we may need to report multiple variables.
736736
push!(user_only_variables, user_variable)
737737
n = Variable.length_of_vector_of_variables(map, user_variable)
738-
for i in 1:n-1
738+
for i in 1:(n-1)
739739
push!(
740740
user_only_variables,
741741
MOI.VariableIndex(user_variable.value - i),
@@ -780,7 +780,7 @@ function _get_all_including_bridged(
780780
# `outer_variable` might represent the start of a VectorOfVariables
781781
# if multiple user-variables were bridged. Add them all.
782782
n = Variable.length_of_vector_of_variables(map, outer_variable)
783-
for i in 1:n-1
783+
for i in 1:(n-1)
784784
push!(ret, MOI.VariableIndex(outer_variable.value - i))
785785
end
786786
end

src/FileFormats/CBF/read.jl

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -360,15 +360,15 @@ function Base.read!(io::IO, model::Model)
360360
MOI.VectorAffineTerm{Float64}(4 - l, t) for
361361
l in 1:cone_dim for t in data.row_terms[row_idx+l]
362362
],
363-
data.row_constants[row_idx.+(3:-1:1)],
363+
data.row_constants[row_idx .+ (3:-1:1)],
364364
)
365365
else
366366
MOI.VectorAffineFunction(
367367
[
368368
MOI.VectorAffineTerm{Float64}(l, t) for l in 1:cone_dim
369369
for t in data.row_terms[row_idx+l]
370370
],
371-
data.row_constants[row_idx.+(1:cone_dim)],
371+
data.row_constants[row_idx .+ (1:cone_dim)],
372372
)
373373
end
374374
con_set = _cbf_to_moi_cone(data, cone_str, cone_dim)
@@ -386,7 +386,7 @@ function Base.read!(io::IO, model::Model)
386386
MOI.VectorAffineTerm{Float64}(l, t) for l in 1:cone_dim for
387387
t in data.psd_row_terms[row_start+l]
388388
],
389-
data.psd_row_constants[row_start.+(1:cone_dim)],
389+
data.psd_row_constants[row_start .+ (1:cone_dim)],
390390
)
391391
MOI.add_constraint(
392392
model,

src/FileFormats/MPS/MPS.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -221,7 +221,7 @@ function Base.write(io::IO, model::Model)
221221
FileFormats.create_unique_names(
222222
model;
223223
warn = options.warn,
224-
replacements = Function[s->replace(s, ' ' => '_')],
224+
replacements = Function[s->replace(s, ' '=>'_')],
225225
)
226226
end
227227
variables = MOI.get(model, MOI.ListOfVariableIndices())

src/FileFormats/NL/NL.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -749,7 +749,7 @@ function Base.write(io::IO, model::Model)
749749
if n_con > 0
750750
println(io, "k", length(model.x) - 1)
751751
total = 0
752-
for i in 1:length(model.order)-1
752+
for i in 1:(length(model.order)-1)
753753
total += model.x[model.order[i]].jacobian_count
754754
println(io, total)
755755
end

src/Nonlinear/ReverseAD/graph_tools.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -258,7 +258,7 @@ function _compute_hessian_sparsity(
258258
if !all(
259259
i ->
260260
input_linearity[children_arr[i]] == CONSTANT ||
261-
children_arr[i] == k,
261+
children_arr[i] == k,
262262
sibling_idx,
263263
)
264264
# at least one sibling isn't constant

0 commit comments

Comments
 (0)