Skip to content

Commit 89a23b9

Browse files
committed
use better conic tests for spectral and nuclear cones
1 parent 83f4e87 commit 89a23b9

File tree

2 files changed

+45
-32
lines changed

2 files changed

+45
-32
lines changed

src/Test/contconic.jl

Lines changed: 27 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1901,9 +1901,9 @@ function normspec1test(model::MOI.ModelLike, config::TestConfig)
19011901
rtol = config.rtol
19021902
# Problem NormSpec1
19031903
# min t
1904-
# st t >= sigma_1([1 1 1; 1 1 1]) (i.e (t, ones(2, 3)) is in NormSpectralCone(2, 3))
1905-
# Singular values of ones(2, 3) are [sqrt(6), 0], so optimal solution is:
1906-
# t = sqrt(6)
1904+
# st t >= sigma_1([1 1 0; 1 -1 1]) (i.e (t, 1, 1, 1, -1, 0, 1]) is in NormSpectralCone(2, 3))
1905+
# Singular values are [sqrt(3), sqrt(2)], so optimal solution is:
1906+
# t = sqrt(3)
19071907

19081908
@test MOIU.supports_default_copy_to(model, #=copy_names=# false)
19091909
@test MOI.supports(model, MOI.ObjectiveFunction{MOI.SingleVariable}())
@@ -1916,7 +1916,8 @@ function normspec1test(model::MOI.ModelLike, config::TestConfig)
19161916
t = MOI.add_variable(model)
19171917
@test MOI.get(model, MOI.NumberOfVariables()) == 1
19181918

1919-
spec = MOI.add_constraint(model, MOI.VectorAffineFunction([MOI.VectorAffineTerm(1, MOI.ScalarAffineTerm(1.0, t))], vcat(0.0, ones(6))), MOI.NormSpectralCone(2, 3))
1919+
data = Float64[1, 1, 1, -1, 0, 1]
1920+
spec = MOI.add_constraint(model, MOI.VectorAffineFunction([MOI.VectorAffineTerm(1, MOI.ScalarAffineTerm(1.0, t))], vcat(0.0, data)), MOI.NormSpectralCone(2, 3))
19201921

19211922
MOI.set(model, MOI.ObjectiveFunction{MOI.SingleVariable}(), MOI.SingleVariable(t))
19221923
MOI.set(model, MOI.ObjectiveSense(), MOI.MIN_SENSE)
@@ -1933,17 +1934,18 @@ function normspec1test(model::MOI.ModelLike, config::TestConfig)
19331934
@test MOI.get(model, MOI.DualStatus()) == MOI.FEASIBLE_POINT
19341935
end
19351936

1936-
rt6 = sqrt(6)
1937-
@test MOI.get(model, MOI.ObjectiveValue()) rt6 atol=atol rtol=rtol
1937+
rt3 = sqrt(3)
1938+
@test MOI.get(model, MOI.ObjectiveValue()) rt3 atol=atol rtol=rtol
19381939
if config.dual_objective_value
1939-
@test MOI.get(model, MOI.DualObjectiveValue()) rt6 atol=atol rtol=rtol
1940+
@test MOI.get(model, MOI.DualObjectiveValue()) rt3 atol=atol rtol=rtol
19401941
end
19411942

1942-
@test MOI.get(model, MOI.VariablePrimal(), t) rt6 atol=atol rtol=rtol
1943-
@test MOI.get(model, MOI.ConstraintPrimal(), spec) vcat(rt6, ones(6)) atol=atol rtol=rtol
1943+
@test MOI.get(model, MOI.VariablePrimal(), t) rt3 atol=atol rtol=rtol
1944+
@test MOI.get(model, MOI.ConstraintPrimal(), spec) vcat(rt3, data) atol=atol rtol=rtol
19441945

19451946
if config.duals
1946-
@test MOI.get(model, MOI.ConstraintDual(), spec) vcat(1, fill(-inv(rt6), 6)) atol=atol rtol=rtol
1947+
invrt3 = inv(rt3)
1948+
@test MOI.get(model, MOI.ConstraintDual(), spec) Float64[1, 0, -invrt3, 0, invrt3, 0, -invrt3] atol=atol rtol=rtol
19471949
end
19481950
end
19491951
end
@@ -1958,9 +1960,9 @@ function normnuc1test(model::MOI.ModelLike, config::TestConfig)
19581960
rtol = config.rtol
19591961
# Problem NormNuc1
19601962
# min t
1961-
# st t >= sum_i sigma_i([1 1 1; 1 1 1]) (i.e (t, ones(2, 3)) is in NormNuclearCone(2, 3))
1962-
# Singular values of ones(2, 3) are [sqrt(6), 0], so optimal solution is:
1963-
# t = sqrt(6)
1963+
# st t >= sum_i sigma_i([1 1 0; 1 -1 1]) (i.e (t, 1, 1, 1, -1, 0, 1]) is in NormNuclearCone(2, 3))
1964+
# Singular values are [sqrt(3), sqrt(2)], so optimal solution is:
1965+
# t = sqrt(3) + sqrt(2)
19641966

19651967
@test MOIU.supports_default_copy_to(model, #=copy_names=# false)
19661968
@test MOI.supports(model, MOI.ObjectiveFunction{MOI.SingleVariable}())
@@ -1973,7 +1975,8 @@ function normnuc1test(model::MOI.ModelLike, config::TestConfig)
19731975
t = MOI.add_variable(model)
19741976
@test MOI.get(model, MOI.NumberOfVariables()) == 1
19751977

1976-
nuc = MOI.add_constraint(model, MOI.VectorAffineFunction([MOI.VectorAffineTerm(1, MOI.ScalarAffineTerm(1.0, t))], vcat(0.0, ones(6))), MOI.NormNuclearCone(2, 3))
1978+
data = Float64[1, 1, 1, -1, 0, 1]
1979+
nuc = MOI.add_constraint(model, MOI.VectorAffineFunction([MOI.VectorAffineTerm(1, MOI.ScalarAffineTerm(1.0, t))], vcat(0.0, data)), MOI.NormNuclearCone(2, 3))
19771980

19781981
MOI.set(model, MOI.ObjectiveFunction{MOI.SingleVariable}(), MOI.SingleVariable(t))
19791982
MOI.set(model, MOI.ObjectiveSense(), MOI.MIN_SENSE)
@@ -1990,17 +1993,21 @@ function normnuc1test(model::MOI.ModelLike, config::TestConfig)
19901993
@test MOI.get(model, MOI.DualStatus()) == MOI.FEASIBLE_POINT
19911994
end
19921995

1993-
rt6 = sqrt(6.0)
1994-
@test MOI.get(model, MOI.ObjectiveValue()) rt6 atol=atol rtol=rtol
1996+
rt3 = sqrt(3)
1997+
rt2 = sqrt(2)
1998+
@test MOI.get(model, MOI.ObjectiveValue()) rt3 + rt2 atol=atol rtol=rtol
19951999
if config.dual_objective_value
1996-
@test MOI.get(model, MOI.DualObjectiveValue()) rt6 atol=atol rtol=rtol
2000+
@test MOI.get(model, MOI.DualObjectiveValue()) rt3 + rt2 atol=atol rtol=rtol
19972001
end
19982002

1999-
@test MOI.get(model, MOI.VariablePrimal(), t) rt6 atol=atol rtol=rtol
2000-
@test MOI.get(model, MOI.ConstraintPrimal(), nuc) vcat(rt6, ones(6)) atol=atol rtol=rtol
2003+
@test MOI.get(model, MOI.VariablePrimal(), t) rt3 + rt2 atol=atol rtol=rtol
2004+
@test MOI.get(model, MOI.ConstraintPrimal(), nuc) Float64[rt2 + rt3, 1, 1, 1, -1, 0, 1] atol=atol rtol=rtol
20012005

20022006
if config.duals
2003-
@test MOI.get(model, MOI.ConstraintDual(), nuc) vcat(1, fill(-inv(rt6), 6)) atol=atol rtol=rtol
2007+
invrt2 = inv(rt2)
2008+
invrt3 = inv(rt3)
2009+
@test MOI.get(model, MOI.ConstraintDual(), nuc) Float64[1, -invrt2, -invrt3, -invrt2, invrt3, 0, -invrt3] atol=atol rtol=rtol
2010+
20042011
end
20052012
end
20062013
end

test/Bridges/Constraint/norm_spec_nuc_to_psd.jl

Lines changed: 18 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -19,11 +19,11 @@ config = MOIT.TestConfig()
1919
MOI.VectorOfVariables, MOI.VectorAffineFunction{Float64}, MOI.VectorQuadraticFunction{Float64}
2020
]])
2121

22-
d1 = 1 / 6
23-
d2 = 0.25
24-
x = -inv(2 * sqrt(6))
25-
psd_dual = [d1, 0, d1, 0, 0, d1, x, x, x, d2, x, x, x, 0, d2]
26-
mock.optimize! = (mock::MOIU.MockOptimizer) -> MOIU.mock_optimize!(mock, [sqrt(6)],
22+
inv6 = inv(6)
23+
rt3 = sqrt(3)
24+
invrt12 = inv(2 * rt3)
25+
psd_dual = [inv6, -invrt12, inv6, invrt12, -invrt12, inv6, 0, 0, 0, 0, -invrt12, invrt12, -invrt12, 0, 0.5]
26+
mock.optimize! = (mock::MOIU.MockOptimizer) -> MOIU.mock_optimize!(mock, [rt3],
2727
(MOI.VectorAffineFunction{Float64}, MOI.PositiveSemidefiniteConeTriangle) => [psd_dual])
2828

2929
MOIT.normspec1test(bridged_mock, config)
@@ -37,7 +37,7 @@ config = MOIT.TestConfig()
3737

3838
s = """
3939
variables: t
40-
psd: [t, 0.0, t, 0.0, 0.0, t, 1.0, 1.0, 1.0, t, 1.0, 1.0, 1.0, 0.0, t] in MathOptInterface.PositiveSemidefiniteConeTriangle(5)
40+
psd: [t, 0.0, t, 0.0, 0.0, t, 1.0, 1.0, 0.0, t, 1.0, -1.0, 1.0, 0.0, t] in MathOptInterface.PositiveSemidefiniteConeTriangle(5)
4141
minobjective: t
4242
"""
4343
model = MOIU.Model{Float64}()
@@ -54,7 +54,7 @@ config = MOIT.TestConfig()
5454

5555
s = """
5656
variables: t
57-
spec: [t, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0] in MathOptInterface.NormSpectralCone(2, 3)
57+
spec: [t, 1.0, 1.0, 1.0, -1.0, 0.0, 1.0] in MathOptInterface.NormSpectralCone(2, 3)
5858
minobjective: t
5959
"""
6060
model = MOIU.Model{Float64}()
@@ -74,9 +74,15 @@ end
7474
MOI.VectorOfVariables, MOI.VectorAffineFunction{Float64}, MOI.VectorQuadraticFunction{Float64}
7575
]])
7676

77-
x = -inv(2 * sqrt(6))
78-
psd_dual = [0.5, 0, 0.5, 0, 0, 0.5, x, x, x, 0.5, x, x, x, 0, 0.5]
79-
mock.optimize! = (mock::MOIU.MockOptimizer) -> MOIU.mock_optimize!(mock, vcat(sqrt(6), ones(6), ones(3)),
77+
rt2 = sqrt(2)
78+
rt3 = sqrt(3)
79+
invrt2 = inv(rt2)
80+
invrt3 = inv(rt3)
81+
var_primal = [rt2 + rt3, invrt2 + invrt3, invrt2 - invrt3, invrt2 + invrt3, invrt3, -invrt3, invrt3, rt2, 0, rt3]
82+
invrt8 = inv(sqrt(8))
83+
invrt12 = inv(sqrt(12))
84+
psd_dual = [0.5, 0, 0.5, 0, 0, 0.5, -invrt8, -invrt8, 0, invrt8, -invrt12, invrt12, -invrt12, 0, 0.5]
85+
mock.optimize! = (mock::MOIU.MockOptimizer) -> MOIU.mock_optimize!(mock, var_primal,
8086
(MOI.ScalarAffineFunction{Float64}, MOI.GreaterThan{Float64}) => [[1.0]],
8187
(MOI.VectorAffineFunction{Float64}, MOI.PositiveSemidefiniteConeTriangle) => [psd_dual])
8288

@@ -95,7 +101,7 @@ end
95101
s = """
96102
variables: t, U11, U12, U22, U31, U32, U33, V11, V12, V22
97103
greater: t + -0.5U11 + -0.5U22 + -0.5U33 + -0.5V11 + -0.5V22 >= 0.0
98-
psd: [U11, U12, U22, U31, U32, U33, 1.0, 1.0, 1.0, V11, 1.0, 1.0, 1.0, V12, V22] in MathOptInterface.PositiveSemidefiniteConeTriangle(5)
104+
psd: [U11, U12, U22, U31, U32, U33, 1.0, 1.0, 0.0, V11, 1.0, -1.0, 1.0, V12, V22] in MathOptInterface.PositiveSemidefiniteConeTriangle(5)
99105
minobjective: t
100106
"""
101107
model = MOIU.Model{Float64}()
@@ -112,7 +118,7 @@ end
112118

113119
s = """
114120
variables: t
115-
nuc: [t, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0] in MathOptInterface.NormNuclearCone(2, 3)
121+
nuc: [t, 1.0, 1.0, 1.0, -1.0, 0.0, 1.0] in MathOptInterface.NormNuclearCone(2, 3)
116122
minobjective: t
117123
"""
118124
model = MOIU.Model{Float64}()

0 commit comments

Comments
 (0)