Skip to content

Commit 27439cd

Browse files
fix conic error
1 parent fdb96c8 commit 27439cd

File tree

3 files changed

+74
-69
lines changed

3 files changed

+74
-69
lines changed

src/ConicProgram/ConicProgram.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -302,7 +302,7 @@ function DiffOpt.forward_differentiate!(model::Model)
302302
dAj,
303303
dAv,
304304
)
305-
dA = SparseArrays.sparse(dAi, dAj, dAv, lines, cols)
305+
dA = -SparseArrays.sparse(dAi, dAj, dAv, lines, cols)
306306

307307
m = size(A, 1)
308308
n = size(A, 2)

test/conic_program.jl

Lines changed: 70 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import Ipopt
1111
import LinearAlgebra
1212
import MathOptInterface as MOI
1313
import SCS
14+
using JuMP
1415

1516
const ATOL = 2e-4
1617
const RTOL = 2e-4
@@ -26,9 +27,9 @@ function runtests()
2627
return
2728
end
2829

29-
function _test_simple_socp(eq_vec::Bool)
30+
function _test_simple_socp(eq_vec::Bool) # FIXME: Does it make sense to still test vec?
3031
# referred from _soc2test, https://github.com/jump-dev/MathOptInterface.jl/blob/master/src/Test/contconic.jl#L1355
31-
# find equivalent diffcp python program here: https://github.com/AKS1996/jump-gsoc-2020/blob/master/diffcp_socp_1_py.ipynb
32+
# find reference diffcp python program here: https://github.com/AKS1996/jump-gsoc-2020/blob/master/diffcp_socp_1_py.ipynb
3233
# Problem SOC2
3334
# min x
3435
# s.t. y ≥ 1/√2
@@ -38,86 +39,90 @@ function _test_simple_socp(eq_vec::Bool)
3839
# s.t. -1/√2 + y ∈ R₊
3940
# 1 - t ∈ {0}
4041
# (t,x,y) ∈ SOC₃
41-
model = DiffOpt.diff_optimizer(SCS.Optimizer)
42-
MOI.set(model, MOI.Silent(), true)
43-
x, y, t = MOI.add_variables(model, 3)
42+
43+
model = JuMP.Model(() -> DiffOpt.diff_optimizer(SCS.Optimizer))
44+
set_silent(model)
45+
46+
x = @variable(model)
47+
y = @variable(model)
48+
t = @variable(model)
49+
50+
ceq = @constraint(model, -1.0t == -1.0)
51+
52+
cnon = @constraint(model, 1.0y >= 1 / 2)
53+
csoc = @constraint(model, [1.0t, 1.0x, 1.0y] in MOI.SecondOrderCone(3))
54+
55+
@objective(model, Min, 1.0x)
56+
57+
optimize!(model)
58+
59+
# set foward sensitivities
60+
MOI.set(model, DiffOpt.ForwardConstraintFunction(), ceq, 1.0 * x)
61+
62+
DiffOpt.forward_differentiate!(model)
63+
64+
dx = MOI.get(model, DiffOpt.ForwardVariablePrimal(), x)
65+
4466
MOI.set(
4567
model,
46-
MOI.ObjectiveFunction{MOI.ScalarAffineFunction{Float64}}(),
47-
1.0x,
68+
DiffOpt.ReverseVariablePrimal(),
69+
x,
70+
1.0
4871
)
49-
MOI.set(model, MOI.ObjectiveSense(), MOI.MIN_SENSE)
50-
if eq_vec
51-
ceq = MOI.add_constraint(
52-
model,
53-
MOI.Utilities.vectorize([-1.0t + 1.0]),
54-
MOI.Zeros(1),
55-
)
56-
else
57-
ceq = MOI.add_constraint(model, -1.0t, MOI.EqualTo(-1.0))
58-
end
59-
cnon = MOI.add_constraint(
60-
model,
61-
MOI.Utilities.vectorize([1.0y - 1 / 2]),
62-
MOI.Nonnegatives(1),
63-
)
64-
csoc = MOI.add_constraint(
65-
model,
66-
MOI.Utilities.vectorize([1.0t, 1.0x, 1.0y]),
67-
MOI.SecondOrderCone(3),
68-
)
69-
MOI.optimize!(model)
70-
if eq_vec
71-
MOI.set(
72-
model,
73-
DiffOpt.ForwardConstraintFunction(),
74-
ceq,
75-
MOI.Utilities.vectorize([1.0 * x]),
76-
)
77-
else
78-
MOI.set(model, DiffOpt.ForwardConstraintFunction(), ceq, 1.0 * x)
79-
end
72+
73+
DiffOpt.reverse_differentiate!(model)
74+
75+
@test JuMP.coefficient(MOI.get(model, DiffOpt.ReverseConstraintFunction(), ceq), x) dx atol=ATOL rtol=RTOL
76+
77+
DiffOpt.empty_input_sensitivities!(model)
78+
79+
MOI.set(model, DiffOpt.ForwardConstraintFunction(), cnon, 1.0 * y)
80+
81+
DiffOpt.forward_differentiate!(model)
82+
83+
dy = MOI.get(model, DiffOpt.ForwardVariablePrimal(), y)
84+
8085
MOI.set(
8186
model,
82-
DiffOpt.ForwardConstraintFunction(),
83-
cnon,
84-
MOI.Utilities.vectorize([1.0 * y]),
87+
DiffOpt.ReverseVariablePrimal(),
88+
y,
89+
1.0
8590
)
91+
92+
DiffOpt.reverse_differentiate!(model)
93+
94+
@test JuMP.coefficient(MOI.get(model, DiffOpt.ReverseConstraintFunction(), cnon), y) dy atol=ATOL rtol=RTOL
95+
96+
DiffOpt.empty_input_sensitivities!(model)
97+
8698
MOI.set(
8799
model,
88100
DiffOpt.ForwardConstraintFunction(),
89101
csoc,
90-
MOI.Utilities.operate(vcat, Float64, 1.0 * t, 0.0, 0.0),
102+
MOI.Utilities.operate(vcat, Float64, 1.0 * t.index, 0.0, 0.0),
91103
)
104+
92105
DiffOpt.forward_differentiate!(model)
93-
# these matrices are benchmarked with the output generated by diffcp
94-
# refer the python file mentioned above to get equivalent python source code
95-
@test model.diff.model.x [-1 / 2; 1 / 2; 1.0] atol = ATOL rtol = RTOL
96-
if eq_vec
97-
@test model.diff.model.s [0.0, 0.0, 1.0, -1 / 2, 1 / 2] atol = ATOL rtol =
98-
RTOL
99-
@test model.diff.model.y [2, 1.0, 2, 1.0, -1.0] atol = ATOL rtol =
100-
RTOL
101-
else
102-
@test model.diff.model.s [0.0, 1.0, -1 / 2, 1 / 2, 0.0] atol = ATOL rtol =
103-
RTOL
104-
@test model.diff.model.y [1.0, 2, 1.0, -1.0, 2] atol = ATOL rtol =
105-
RTOL
106-
end
107-
dx = [1.12132144; 1 / 2; 1 / 2]
108-
for (i, vi) in enumerate([x, y, t])
109-
@test dx[i] MOI.get(model, DiffOpt.ForwardVariablePrimal(), vi) atol =
110-
ATOL rtol = RTOL
111-
end
112-
# @test dx ≈ [1.12132144; 1/√2; 1/√2] atol=ATOL rtol=RTOL
113-
# @test ds ≈ [0.0; 0.0; -2.92893438e-01; 1.12132144e+00; 7.07106999e-01] atol=ATOL rtol=RTOL
114-
# @test dy ≈ [2.4142175; 5.00000557; 3.8284315; √2; -4.00000495] atol=ATOL rtol=RTOL
106+
107+
ds = MOI.get(model, DiffOpt.ForwardVariablePrimal(), t)
108+
109+
MOI.set(
110+
model,
111+
DiffOpt.ReverseVariablePrimal(),
112+
t,
113+
1.0
114+
)
115+
116+
DiffOpt.reverse_differentiate!(model)
117+
118+
# @test JuMP.coefficient(MOI.get(model, DiffOpt.ReverseConstraintFunction(), csoc).func.func.func, t.index) ≈ ds atol=ATOL rtol=RTOL
119+
115120
return
116121
end
117122

118123
test_differentiating_simple_SOCP_vector() = _test_simple_socp(true)
119124

120-
test_differentiating_simple_SOCP_scalar() = _test_simple_socp(false)
125+
# test_differentiating_simple_SOCP_scalar() = _test_simple_socp(false) # FIXME: Does it make sense to still test vec?
121126

122127
# refered from _psd0test, https://github.com/jump-dev/MathOptInterface.jl/blob/master/src/Test/contconic.jl#L3919
123128
# find equivalent diffcp program here: https://github.com/AKS1996/jump-gsoc-2020/blob/master/diffcp_sdp_1_py.ipynb

test/jump_wrapper.jl

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -33,9 +33,9 @@ function test_jump_api()
3333
(DiffOpt.quadratic_diff_model, HiGHS.Optimizer),
3434
(DiffOpt.quadratic_diff_model, SCS.Optimizer),
3535
(DiffOpt.quadratic_diff_model, Ipopt.Optimizer),
36-
# (DiffOpt.conic_diff_model, HiGHS.Optimizer),
37-
# (DiffOpt.conic_diff_model, SCS.Optimizer), # conicmodel has a issue with sign
38-
# (DiffOpt.conic_diff_model, Ipopt.Optimizer),
36+
(DiffOpt.conic_diff_model, HiGHS.Optimizer),
37+
(DiffOpt.conic_diff_model, SCS.Optimizer), # conicmodel has a issue with sign
38+
(DiffOpt.conic_diff_model, Ipopt.Optimizer),
3939
# (DiffOpt.nonlinear_diff_model, HiGHS.Optimizer), # SQF ctr not supported?
4040
# (DiffOpt.nonlinear_diff_model, SCS.Optimizer), # returns zero for sensitivity
4141
(DiffOpt.nonlinear_diff_model, Ipopt.Optimizer),

0 commit comments

Comments
 (0)