Skip to content

Commit 5b968d1

Browse files
ericphansonodow
andauthored
deprecate + on constraints (#659)
* deprecate `+` on constraints * add test, fix matrix case * fix example * Update test/test_utilities.jl Co-authored-by: Oscar Dowson <[email protected]> * add test * Apply suggestions from code review Co-authored-by: Oscar Dowson <[email protected]> * Update docs/src/examples/optimization_with_complex_variables/povm_simulation.jl --------- Co-authored-by: Oscar Dowson <[email protected]>
1 parent dbb7306 commit 5b968d1

File tree

9 files changed

+108
-51
lines changed

9 files changed

+108
-51
lines changed

docs/src/examples/general_examples/basic_usage.jl

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,9 +22,8 @@ x = Variable(4)
2222
c = [1; 2; 3; 4]
2323
A = I(4)
2424
b = [10; 10; 10; 10]
25-
p = minimize(dot(c, x)) # or c' * x
26-
p.constraints += A * x <= b
27-
p.constraints += [x >= 1; x <= 10; x[2] <= 5; x[1] + x[4] - x[2] <= 10]
25+
constraints = [A * x <= b, x >= 1, x <= 10, x[2] <= 5, x[1] + x[4] - x[2] <= 10]
26+
p = minimize(dot(c, x), constraints) # or c' * x
2827
solve!(p, SCS.Optimizer; silent_solver = true)
2928

3029
println(round(p.optval, digits = 2))

docs/src/examples/general_examples/chebyshev_center.jl

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -22,11 +22,13 @@ b = ones(4, 1);
2222
# Create and solve the model
2323
r = Variable(1)
2424
x_c = Variable(2)
25-
p = maximize(r)
26-
p.constraints += a1' * x_c + r * norm(a1, 2) <= b[1];
27-
p.constraints += a2' * x_c + r * norm(a2, 2) <= b[2];
28-
p.constraints += a3' * x_c + r * norm(a3, 2) <= b[3];
29-
p.constraints += a4' * x_c + r * norm(a4, 2) <= b[4];
25+
constraints = [
26+
a1' * x_c + r * norm(a1, 2) <= b[1],
27+
a2' * x_c + r * norm(a2, 2) <= b[2],
28+
a3' * x_c + r * norm(a3, 2) <= b[3],
29+
a4' * x_c + r * norm(a4, 2) <= b[4],
30+
]
31+
p = maximize(r, constraints)
3032
solve!(p, SCS.Optimizer; silent_solver = true)
3133
p.optval
3234

docs/src/examples/mixed_integer/n_queens.jl

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,12 +10,12 @@ x = Variable((n, n), BinVar)
1010

1111
# Now we impose the constraints: at most one queen on any anti-diagonal, at most one queen on any diagonal, and we must have exactly one queen per row and per column.
1212
## At most one queen on any anti-diagonal
13-
constr = Constraint[sum(antidiag(x, k)) <= 1 for k in -n+2:n-2]
13+
constraints = Constraint[sum(antidiag(x, k)) <= 1 for k in -n+2:n-2]
1414
## At most one queen on any diagonal
15-
constr += Constraint[sum(diag(x, k)) <= 1 for k in -n+2:n-2]
15+
append!(constraints, [sum(diag(x, k)) <= 1 for k in -n+2:n-2])
1616
## Exactly one queen per row and one queen per column
17-
constr += Constraint[sum(x, dims = 1)==1, sum(x, dims = 2)==1]
18-
p = satisfy(constr)
17+
append!(constraints, [sum(x, dims = 1) == 1, sum(x, dims = 2) == 1])
18+
p = satisfy(constraints)
1919
solve!(p, GLPK.Optimizer)
2020

2121
# Let us test the results:

docs/src/examples/optimization_with_complex_variables/povm_simulation.jl

Lines changed: 20 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -42,14 +42,26 @@ function get_visibility(K)
4242
P = [[ComplexVariable(2, 2) for i in 1:2] for j in 1:6]
4343
q = Variable(6, Positive())
4444
t = Variable(1, Positive())
45-
constraints = [isposdef(P[i][j]) for i in 1:6 for j in 1:2]
46-
constraints += sum(q) == 1
47-
constraints += t <= 1
48-
constraints += [P[i][1] + P[i][2] == q[i] * I(2) for i in 1:6]
49-
constraints += t * K[1] + (1 - t) * noise[1] == P[1][1] + P[2][1] + P[3][1]
50-
constraints += t * K[2] + (1 - t) * noise[2] == P[1][2] + P[4][1] + P[5][1]
51-
constraints += t * K[3] + (1 - t) * noise[3] == P[2][2] + P[4][2] + P[6][1]
52-
constraints += t * K[4] + (1 - t) * noise[4] == P[3][2] + P[5][2] + P[6][2]
45+
constraints = Constraint[isposdef(P[i][j]) for i in 1:6 for j in 1:2]
46+
push!(constraints, sum(q) == 1)
47+
push!(constraints, t <= 1)
48+
append!(constraints, [P[i][1] + P[i][2] == q[i] * I(2) for i in 1:6])
49+
push!(
50+
constraints,
51+
t * K[1] + (1 - t) * noise[1] == P[1][1] + P[2][1] + P[3][1],
52+
)
53+
push!(
54+
constraints,
55+
t * K[2] + (1 - t) * noise[2] == P[1][2] + P[4][1] + P[5][1],
56+
)
57+
push!(
58+
constraints,
59+
t * K[3] + (1 - t) * noise[3] == P[2][2] + P[4][2] + P[6][1],
60+
)
61+
push!(
62+
constraints,
63+
t * K[4] + (1 - t) * noise[4] == P[3][2] + P[5][2] + P[6][2],
64+
)
5365
p = maximize(t, constraints)
5466
solve!(p, SCS.Optimizer; silent_solver = true)
5567
return p.optval

src/deprecations.jl

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,3 +123,35 @@ end
123123
function ComplexVariable(set::Symbol, sets::Symbol...)
124124
return ComplexVariable((1, 1), set, sets...)
125125
end
126+
127+
# `+` on constraints
128+
function warn_deprecated_constraint_concatenation()
129+
@warn(
130+
"Concatenating collections of constraints together with `+` or `+=` to produce a new list of constraints is deprecated. Instead, use `vcat` to concatenate collections of constraints.",
131+
maxlog = 1
132+
)
133+
return
134+
end
135+
136+
function Base.:+(x::Array{<:Constraint}, y::Array{<:Constraint})
137+
warn_deprecated_constraint_concatenation()
138+
return vcat(x, y)
139+
end
140+
141+
function Base.:+(x::Constraint, y::Constraint)
142+
@warn(
143+
"Adding constraints together (with `+` or `+=`) to produce a list of constraints is deprecated. Instead, construct a list of constraints via `[constraint1, constraint2]`",
144+
maxlog = 1
145+
)
146+
return [x, y]
147+
end
148+
149+
function Base.:+(x::Constraint, y::Array{<:Constraint})
150+
warn_deprecated_constraint_concatenation()
151+
return vcat(x, y)
152+
end
153+
154+
function Base.:+(x::Array{<:Constraint}, y::Constraint)
155+
warn_deprecated_constraint_concatenation()
156+
return vcat(x, y)
157+
end

src/problem_depot/problems/affine.jl

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -754,11 +754,7 @@ end
754754
@test p.status == MOI.OPTIMAL
755755
end
756756

757-
constr = x >= 0
758-
constr += x >= 1
759-
constr += x <= 10
760-
constr2 = x >= 0
761-
constr2 += [x >= 2, x <= 3] + constr
757+
constr = [x >= 0, x >= 1, x <= 10]
762758
p = satisfy(constr; numeric_type = T)
763759

764760
handle_problem!(p)

src/problem_depot/problems/socp.jl

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -476,9 +476,8 @@ end
476476
x = Variable(5)
477477
q = 1.379 # q norm constraint that generates many inequalities
478478
qs = q / (q - 1) # Conjugate to q
479-
p = minimize(x' * v; numeric_type = T)
479+
p = minimize(x' * v, norm(x, q) <= 1; numeric_type = T)
480480

481-
p.constraints += (norm(x, q) <= 1)
482481
if test
483482
@test problem_vexity(p) == ConvexVexity()
484483
end

src/problems.jl

Lines changed: 17 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -6,21 +6,21 @@
66
mutable struct Problem{T<:Real} <: AbstractExpr
77
head::Symbol
88
objective::Union{AbstractExpr,Nothing}
9-
constraints::Array{Constraint}
9+
constraints::Vector{Constraint}
1010
status::MOI.TerminationStatusCode
1111
model::Union{MOI.ModelLike,Nothing}
1212
function Problem{T}(
1313
head::Symbol,
1414
objective::Union{AbstractExpr,Nothing},
15-
constraints::Array = Constraint[],
15+
constraints = Constraint[],
1616
) where {T<:Real}
1717
if objective !== nothing && sign(objective) == Convex.ComplexSign()
1818
error("Objective cannot be a complex expression")
1919
end
2020
return new(
2121
head,
2222
objective,
23-
constraints,
23+
vec(constraints),
2424
MOI.OPTIMIZE_NOT_CALLED,
2525
nothing,
2626
)
@@ -197,7 +197,7 @@ function Problem{T}(
197197
constraint::Constraint,
198198
constraints::Constraint...,
199199
) where {T<:Real}
200-
return Problem{T}(head, objective, [constraint, constraints...])
200+
return Problem{T}(head, objective, Constraint[constraint, constraints...])
201201
end
202202

203203
# Allow users to simply type minimize
@@ -206,12 +206,16 @@ function minimize(
206206
constraints::Constraint...;
207207
numeric_type = Float64,
208208
)
209-
return Problem{numeric_type}(:minimize, objective, collect(constraints))
209+
return Problem{numeric_type}(
210+
:minimize,
211+
objective,
212+
collect(Constraint, constraints),
213+
)
210214
end
211215

212216
function minimize(
213217
objective::AbstractExpr,
214-
constraints::Array{<:Constraint} = Constraint[];
218+
constraints = Constraint[];
215219
numeric_type = Float64,
216220
)
217221
return Problem{numeric_type}(:minimize, objective, constraints)
@@ -227,7 +231,7 @@ end
227231

228232
function minimize(
229233
objective::Value,
230-
constraints::Array{<:Constraint} = Constraint[];
234+
constraints = Constraint[];
231235
numeric_type = Float64,
232236
)
233237
return minimize(constant(objective), constraints; numeric_type)
@@ -244,7 +248,7 @@ end
244248

245249
function maximize(
246250
objective::AbstractExpr,
247-
constraints::Array{<:Constraint} = Constraint[];
251+
constraints = Constraint[];
248252
numeric_type = Float64,
249253
)
250254
return Problem{numeric_type}(:maximize, objective, constraints)
@@ -260,52 +264,41 @@ end
260264

261265
function maximize(
262266
objective::Value,
263-
constraints::Array{<:Constraint} = Constraint[];
267+
constraints = Constraint[];
264268
numeric_type = Float64,
265269
)
266270
return maximize(constant(objective), constraints; numeric_type)
267271
end
268272

269273
# Allow users to simply type satisfy (if there is no objective)
270274
function satisfy(constraints::Constraint...; numeric_type = Float64)
271-
return Problem{numeric_type}(:satisfy, nothing, [constraints...])
275+
return Problem{numeric_type}(:satisfy, nothing, Constraint[constraints...])
272276
end
273277

274-
function satisfy(
275-
constraints::Array{<:Constraint} = Constraint[];
276-
numeric_type = Float64,
277-
)
278+
function satisfy(constraints = Constraint[]; numeric_type = Float64)
278279
return Problem{numeric_type}(:satisfy, nothing, constraints)
279280
end
280281

281282
function satisfy(constraint::Constraint; numeric_type = Float64)
282283
return satisfy([constraint]; numeric_type = numeric_type)
283284
end
284285

285-
function add_constraints!(p::Problem, constraints::Array{<:Constraint})
286+
function add_constraints!(p::Problem, constraints)
286287
return append!(p.constraints, constraints)
287288
end
288289

289290
function add_constraints!(p::Problem, constraint::Constraint)
290291
return add_constraints!(p, [constraint])
291292
end
292293

293-
function add_constraint!(p::Problem, constraints::Array{<:Constraint})
294+
function add_constraint!(p::Problem, constraints)
294295
return add_constraints!(p, constraints)
295296
end
296297

297298
function add_constraint!(p::Problem, constraint::Constraint)
298299
return add_constraints!(p, constraint)
299300
end
300301

301-
Base.:+(x::Array{<:Constraint}, y::Array{<:Constraint}) = vcat(x, y)
302-
303-
Base.:+(x::Constraint, y::Constraint) = [x, y]
304-
305-
Base.:+(x::Constraint, y::Array{<:Constraint}) = vcat(x, y)
306-
307-
Base.:+(x::Array{<:Constraint}, y::Constraint) = vcat(x, y)
308-
309302
iscomplex(c::Constraint) = iscomplex(c.lhs) || iscomplex(c.rhs)
310303

311304
function add_constraint!(context::Context, c::Constraint)

test/test_utilities.jl

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1008,6 +1008,16 @@ function test_deprecation_in_symbol()
10081008
return
10091009
end
10101010

1011+
function test_deprecation_adding_constraints()
1012+
x = Variable()
1013+
c = x == x
1014+
@test_logs (:warn, r"^Adding") c + c
1015+
@test_logs (:warn, r"^Concatenating") [c] + c
1016+
@test_logs (:warn, r"^Concatenating") c + [c]
1017+
@test_logs (:warn, r"^Concatenating") [c] + [c]
1018+
return
1019+
end
1020+
10111021
function test_dcp_rules()
10121022
vexities = (
10131023
Convex.ConcaveVexity(),
@@ -1118,6 +1128,20 @@ function test_dcp_rules()
11181128
return
11191129
end
11201130

1131+
function test_problem_untyped_constraints()
1132+
x = Variable(1, Positive())
1133+
# Test untyped constraints
1134+
p = maximize(x, Any[x<=1])
1135+
@test p isa Problem
1136+
p = maximize(x, Any[x <= 1;; x <= 1])
1137+
@test p isa Problem
1138+
p = minimize(x, Any[x<=1])
1139+
@test p isa Problem
1140+
p = minimize(x, Any[x <= 1;; x <= 1])
1141+
@test p isa Problem
1142+
return
1143+
end
1144+
11211145
function test_problem_maximize()
11221146
x = Variable(1, Positive())
11231147
p = maximize(exp(x), x <= 1)

0 commit comments

Comments
 (0)