Skip to content

Commit ac382bb

Browse files
authored
Add GenericConstraint{RelativeEntropyCone} support (#623)
1 parent 58f23cd commit ac382bb

File tree

4 files changed

+42
-11
lines changed

4 files changed

+42
-11
lines changed

src/atoms/RelativeEntropyAtom.jl

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -39,15 +39,15 @@ function evaluate(e::RelativeEntropyAtom)
3939
end
4040

4141
function new_conic_form!(context::Context{T}, e::RelativeEntropyAtom) where {T}
42-
# relative_entropy(x,y) = sum_i( x_i log (x_i/y_i) )
43-
w = conic_form!(context, e.children[1])
44-
v = conic_form!(context, e.children[2])
45-
u = conic_form!(context, Variable())
46-
f = operate(vcat, T, sign(e), u, v, w)
47-
d = MOI.output_dimension(w)
48-
@assert d == MOI.output_dimension(v)
49-
MOI_add_constraint(context.model, f, MOI.RelativeEntropyCone(2d + 1))
50-
return u
42+
u = Variable()
43+
x, y = e.children
44+
# Convex.jl has the connvention:
45+
# u >= relative_entropy(x,y) = sum_i( x_i log (x_i/y_i) )
46+
# But MOI has the reversed convention:
47+
# MOI.RelativeEntropyCone has the order (u, y, x)
48+
f = vcat(u, y, x)
49+
add_constraint!(context, GenericConstraint{MOI.RelativeEntropyCone}(f))
50+
return conic_form!(context, u)
5151
end
5252

5353
relative_entropy(x::AbstractExpr, y::AbstractExpr) = RelativeEntropyAtom(x, y)

src/constraints/GenericConstraint.jl

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -283,3 +283,16 @@ function vexity(vex, ::MOI.RotatedSecondOrderCone)
283283
end
284284
return ConvexVexity()
285285
end
286+
287+
# ==============================================================================
288+
# RelativeEntropyCone
289+
# ==============================================================================
290+
291+
head(io::IO, ::MOI.RelativeEntropyCone) = print(io, "RelativeEntropyCone")
292+
293+
function vexity(vex, ::MOI.RelativeEntropyCone)
294+
if !(vex == ConstVexity() || vex == AffineVexity())
295+
return NotDcp()
296+
end
297+
return ConvexVexity()
298+
end

test/test_atoms.jl

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -952,7 +952,7 @@ end
952952

953953
function test_RelativeEntropyAtom()
954954
target = """
955-
variables: w1, w2, v1, v2, u
955+
variables: u, v1, v2, w1, w2
956956
minobjective: 1.0 * u + 0.0
957957
[1.0*u, 1.0*v1, 1.0*v2, 1.0*w1, 1.0*w2] in RelativeEntropyCone(5)
958958
"""
@@ -962,7 +962,7 @@ function test_RelativeEntropyAtom()
962962
return relative_entropy(x, y)
963963
end
964964
target = """
965-
variables: w1, w2, v1, v2, u
965+
variables: u, v1, v2, w1, w2
966966
minobjective: -1.0 * u + 1.0
967967
[1.0*u, 1.0*v1, 1.0*v2, 1.0*w1, 1.0*w2] in RelativeEntropyCone(5)
968968
"""

test/test_constraints.jl

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -279,6 +279,24 @@ function test_GenericConstraint_ExponentialConeConstraint()
279279
return
280280
end
281281

282+
### constraints/GenericConstraint_RelativeEntropyCone
283+
284+
function test_GenericConstraint_RelativeEntropyConeConstraint()
285+
# u >= sum_i( w_i log (w_i/v_i) )
286+
u = Variable()
287+
v = [1, 2]
288+
w = Variable(2)
289+
c = Convex.GenericConstraint{MOI.RelativeEntropyCone}(vcat(u, v, w))
290+
p = minimize(u, [c, w >= 2])
291+
solve!(p, SCS.Optimizer; silent_solver = true)
292+
@test isapprox(u.value, 2 * log(2 / 1) + 2 * log(2 / 2); atol = 1e-4)
293+
@test isapprox(c.dual, [1, 2, 1, -log(2) - 1, -1]; atol = 1e-3)
294+
c = Convex.GenericConstraint{MOI.RelativeEntropyCone}(vcat(square(u), 1, u))
295+
@test vexity(c) === Convex.NotDcp()
296+
@test sprint(Convex.head, c) == "RelativeEntropyCone"
297+
return
298+
end
299+
282300
end # TestConstraints
283301

284302
TestConstraints.runtests()

0 commit comments

Comments
 (0)