Skip to content

Commit 7a90ad8

Browse files
authored
Merge pull request #1 from blegat/bl/split_zero
Add SplitZeroBridge
2 parents b34dd6a + 8dee01c commit 7a90ad8

File tree

4 files changed

+107
-2
lines changed

4 files changed

+107
-2
lines changed

.travis.yml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ codecov: true
44
os:
55
- linux
66
julia:
7-
- 1.0
87
- 1
98
notifications:
109
email: false

src/Bridges/Constraint/Constraint.jl

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,4 +8,6 @@ const MOIB = MOI.Bridges
88
import ComplexOptInterface
99
const COI = ComplexOptInterface
1010

11+
include("split_zero.jl")
12+
1113
end

src/Bridges/Constraint/split_zero.jl

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
function operate_coefficient(f, T::Type, term::MOI.ScalarAffineTerm)
2+
MOI.ScalarAffineTerm(f(term.coefficient), term.variable_index)
3+
end
4+
function operate_coefficient(f, T::Type, term::MOI.VectorAffineTerm)
5+
return MOI.VectorAffineTerm(term.output_index, operate_coefficient(f, T, term.scalar_term))
6+
end
7+
function operate_coefficients(f, T::Type, func::MOI.VectorAffineFunction)
8+
return MOI.VectorAffineFunction(
9+
[operate_coefficient(f, T, term) for term in func.terms],
10+
map(f, func.constants)
11+
)
12+
end
13+
14+
similar_type(::Type{<:MOI.VectorAffineFunction}, T::Type) = MOI.VectorAffineFunction{T}
15+
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}
19+
end
20+
function MOI.Bridges.Constraint.bridge_constraint(
21+
::Type{SplitZeroBridge{T, F, G}}, model::MOI.ModelLike,
22+
f::G,
23+
set::MOI.Zeros
24+
) 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)
28+
end
29+
30+
function MOI.supports_constraint(
31+
::Type{SplitZeroBridge{T}}, ::Type{<:MOI.Utilities.TypedLike{Complex{T}}},
32+
::Type{MOI.Zeros}) where T
33+
return true
34+
end
35+
MOIB.added_constrained_variable_types(::Type{<:SplitZeroBridge}) = Tuple{DataType}[]
36+
function MOIB.added_constraint_types(::Type{SplitZeroBridge{T, F, G}}) where {T, F, G}
37+
return Tuple{DataType, DataType}[(F, MOI.Zeros)]
38+
end
39+
function MOI.Bridges.Constraint.concrete_bridge_type(
40+
::Type{<:SplitZeroBridge{T}}, G::Type{<:MOI.Utilities.TypedLike},
41+
::Type{MOI.Zeros}) where T
42+
return SplitZeroBridge{T, similar_type(G, T), G}
43+
end
44+
45+
# Attributes, Bridge acting as a model
46+
function MOI.get(::SplitZeroBridge{T, F},
47+
::MOI.NumberOfConstraints{F, MOI.Zeros}) where {T, F}
48+
return 2
49+
end
50+
function MOI.get(bridge::SplitZeroBridge{T, F},
51+
::MOI.ListOfConstraintIndices{F, MOI.Zeros}) where {T, F}
52+
return [bridge.real, bridge.imag]
53+
end
54+
55+
# Indices
56+
function MOI.delete(model::MOI.ModelLike, bridge::SplitZeroBridge)
57+
MOI.delete(model, bridge.imag)
58+
MOI.delete(model, bridge.real)
59+
end
60+
61+
# Attributes, Bridge acting as a constraint
62+
function MOI.supports(
63+
::MOI.ModelLike,
64+
::Union{MOI.ConstraintPrimalStart, MOI.ConstraintDualStart},
65+
::Type{<:SplitZeroBridge})
66+
67+
return true
68+
end
69+
function MOI.get(model::MOI.ModelLike, attr::Union{MOI.ConstraintPrimal, MOI.ConstraintPrimalStart, MOI.ConstraintDual, MOI.ConstraintDualStart},
70+
bridge::SplitZeroBridge)
71+
return MOI.get(model, attr, bridge.real) + im * MOI.get(model, attr, bridge.imag)
72+
end
73+
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))
77+
end

test/runtests.jl

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,9 +49,36 @@ function projection_test(optimizer, config)
4949
@test MOI.get(optimizer, MOI.ConstraintDual(), cx) dual atol=atol rtol=rtol
5050
end
5151

52+
function zero_test(optimizer, config)
53+
atol = config.atol
54+
rtol = config.rtol
55+
56+
MOI.empty!(optimizer)
57+
x, cx = MOI.add_constrained_variables(optimizer, MOI.Nonnegatives(2))
58+
fx = MOI.SingleVariable.(x)
59+
func = (1.0 + 2.0im) * fx[1] + (1.0 - 1.0im) * fx[2] + (-1.0 + -1.0im)
60+
c = MOI.add_constraint(
61+
optimizer,
62+
MOI.Utilities.operate(vcat, Complex{Float64}, func),
63+
MOI.Zeros(1)
64+
)
65+
MOI.optimize!(optimizer)
66+
@test MOI.get(optimizer, MOI.TerminationStatus()) == MOI.OPTIMAL
67+
@test MOI.get(optimizer, MOI.VariablePrimal(), x) [2/3, 1/3] atol=atol rtol=rtol
68+
@test MOI.get(optimizer, MOI.ConstraintPrimal(), cx) [2/3, 1/3] atol=atol rtol=rtol
69+
@test MOI.get(optimizer, MOI.ConstraintDual(), cx) zeros(2) atol=atol rtol=rtol
70+
@test MOI.get(optimizer, MOI.ConstraintPrimal(), c) [0.0 + 0.0im] atol=atol rtol=rtol
71+
@test MOI.get(optimizer, MOI.ConstraintDual(), c) [0.0 + 0.0im] atol=atol rtol=rtol
72+
end
73+
5274
import CSDP
5375
@testset "CSDP" begin
76+
config = MOI.Test.TestConfig(atol=1e-4, rtol=1e-4)
5477
bridged = MOI.instantiate(CSDP.Optimizer, with_bridge_type=Float64)
5578
MOI.Bridges.add_bridge(bridged, COI.Bridges.Variable.HermitianToSymmetricPSDBridge{Float64})
56-
projection_test(bridged, MOI.Test.TestConfig(atol=1e-4, rtol=1e-4))
79+
projection_test(bridged, config)
80+
bridged = MOI.Bridges.LazyBridgeOptimizer(MOI.Utilities.CachingOptimizer(MOI.Utilities.Model{Float64}(), CSDP.Optimizer()))
81+
MOI.Bridges.add_bridge(bridged, MOI.Bridges.Constraint.ScalarizeBridge{Float64})
82+
MOI.Bridges.add_bridge(bridged, COI.Bridges.Constraint.SplitZeroBridge{Float64})
83+
zero_test(bridged, config)
5784
end

0 commit comments

Comments
 (0)