Skip to content

Commit 1b3a4bb

Browse files
authored
Add support for using Problem as an atom (#646)
1 parent 19ab3a9 commit 1b3a4bb

File tree

3 files changed

+75
-15
lines changed

3 files changed

+75
-15
lines changed

src/problems.jl

Lines changed: 12 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,9 @@ function Base.getproperty(p::Problem, s::Symbol)
3434
else
3535
return objective_value(p)
3636
end
37+
elseif s === :size
38+
# Used when Problem is interpreted as an atom
39+
return p.objective.size
3740
end
3841
return getfield(p, s)
3942
end
@@ -90,20 +93,15 @@ function objective_vexity(p::Problem)
9093
return obj_vex
9194
end
9295

93-
vexity(p::Problem) = objective_vexity(p)
94-
95-
# is this right?
96-
# function problem_vexity(sense, obj_vexity, constr_vexity)
97-
# if constr_vexity == ConstVexity()
98-
# return obj_vexity
99-
# end
100-
101-
# if constr_vexity == AffineVexity() && obj_vexity == AffineVexity()
102-
# return sense === :maximize ? ConcaveVexity() : ConvexVexity()
103-
# end
104-
105-
# return obj_vexity + constr_vexity
106-
# end
96+
function vexity(p::Problem)
97+
if p.head == :satisfy
98+
return ConstVexity()
99+
elseif p.head == :minimize
100+
return vexity(p.objective) + ConvexVexity()
101+
elseif p.head == :maximize
102+
return vexity(p.objective) + ConcaveVexity()
103+
end
104+
end
107105

108106
function monotonicity(p::Problem)
109107
if p.head === :satisfy

test/test_atoms.jl

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2265,6 +2265,68 @@ function test_transpose()
22652265
return
22662266
end
22672267

2268+
### src/problems.jl
2269+
2270+
function test_Problem_at_atom_lamba_min()
2271+
function lamb_min(A::Convex.AbstractExpr)
2272+
t = Variable()
2273+
n = size(A, 1)
2274+
@assert n == size(A, 2)
2275+
return maximize(t, [A - t * LinearAlgebra.I(n) 0])
2276+
end
2277+
A = Variable(2, 2)
2278+
p = maximize(lamb_min(A) + 1)
2279+
@test vexity(p) == Convex.ConcaveVexity()
2280+
context = Convex.Context(p, MOI.Utilities.Model{Float64})
2281+
F = MOI.VectorAffineFunction{Float64}
2282+
S = MOI.PositiveSemidefiniteConeSquare
2283+
@test (F, S) in MOI.get(context.model, MOI.ListOfConstraintTypesPresent())
2284+
@test MOI.get(context.model, MOI.NumberOfConstraints{F,S}()) == 1
2285+
# Check DCP error
2286+
p = minimize(lamb_min(A) + 1)
2287+
@test vexity(p) == Convex.NotDcp()
2288+
# Check satisfy
2289+
p = satisfy([lamb_min(A) >= 1])
2290+
@test vexity(p) == Convex.ConstVexity()
2291+
return
2292+
end
2293+
2294+
function test_Problem_caching()
2295+
function t_atom()
2296+
t = Variable()
2297+
return minimize(t, [t >= 0])
2298+
end
2299+
p = minimize(t_atom() + t_atom())
2300+
context = Convex.Context(p, MOI.Utilities.Model{Float64})
2301+
@test MOI.get(context.model, MOI.NumberOfVariables()) == 2
2302+
t = t_atom()
2303+
p = minimize(t + t)
2304+
context = Convex.Context(p, MOI.Utilities.Model{Float64})
2305+
@test MOI.get(context.model, MOI.NumberOfVariables()) == 1
2306+
return
2307+
end
2308+
2309+
function test_Problem_array()
2310+
function op_huber(c)
2311+
M = 1.0
2312+
s = Variable(size(c))
2313+
n = Variable(size(c))
2314+
return minimize(square(s) + 2 * M * abs(n), c == s + n)
2315+
end
2316+
x = Variable(2)
2317+
@test size(op_huber(x)) == (2, 1)
2318+
context_op_huber =
2319+
Convex.Context(minimize(sum(op_huber(x))), MOI.Utilities.Model{Float64})
2320+
context_builtin =
2321+
Convex.Context(minimize(sum(huber(x))), MOI.Utilities.Model{Float64})
2322+
# This test checks that the two printed models are identical. This relies on
2323+
# the conic_form! of HuberAtom being identical to the implementation in
2324+
# op_huber. Feel free to change this test if HuberAtom changes.
2325+
@test sprint(print, context_op_huber.model) ==
2326+
sprint(print, context_builtin.model)
2327+
return
2328+
end
2329+
22682330
end # TestAtoms
22692331

22702332
TestAtoms.runtests()

test/test_utilities.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -822,7 +822,7 @@ function test_DictVectors()
822822
x = DictVectors.DictVector{BigFloat}(1)
823823
y = DictVectors.DictVector{BigFloat}(1)
824824
p = minimize(x + y, [x >= 3, y >= 2])
825-
@test vexity(p) == Convex.AffineVexity()
825+
@test vexity(p) == Convex.ConvexVexity()
826826
solve!(p, MOI.OptimizerWithAttributes(SCS.Optimizer, "verbose" => 0))
827827
@test p.optval 5 atol = 1e-3
828828
@test evaluate(x + y) 5 atol = 1e-3

0 commit comments

Comments
 (0)