Skip to content

Commit 0ffdf67

Browse files
authored
Merge branch 'master' into dcp-warnings
2 parents efd3d1b + 15f05fb commit 0ffdf67

File tree

11 files changed

+104
-90
lines changed

11 files changed

+104
-90
lines changed

docs/src/operations.md

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -34,16 +34,15 @@ LP solver.
3434
| `x-y` or `x.-y` | subtraction | affine | increasing in $x$ decreasing in $y$ | none none |
3535
| `x*y` | multiplication | affine | increasing if constant term $\ge 0$ decreasing if constant term $\le 0$ not monotonic otherwise | PR: one argument is constant |
3636
| `x/y` | division | affine | increasing | PR: $y$ is scalar constant |
37-
| `dot(*)(x, y)` | elementwise multiplication | affine | increasing | PR: one argument is constant |
38-
| `dot(/)(x, y)` | elementwise division | affine | increasing | PR: one argument is constant |
37+
| `x .* y` | elementwise multiplication | affine | increasing | PR: one argument is constant |
38+
| `x ./ y` | elementwise division | affine | increasing | PR: one argument is constant |
3939
| `x[1:4, 2:3]` | indexing and slicing | affine | increasing | none |
4040
| `diag(x, k)` | $k$-th diagonal of a matrix | affine | increasing | none |
4141
| `diagm(x)` | construct diagonal matrix | affine | increasing | PR: $x$ is a vector |
4242
| `x'` | transpose | affine | increasing | none |
4343
| `vec(x)` | vector representation | affine | increasing | none |
4444
| `dot(x,y)` | $\sum_i x_i y_i$ | affine | increasing | PR: one argument is constant |
4545
| `kron(x,y)` | Kronecker product | affine | increasing | PR: one argument is constant |
46-
| `vecdot(x,y)` | `dot(vec(x),vec(y))` | affine | increasing | PR: one argument is constant |
4746
| `sum(x)` | $\sum_{ij} x_{ij}$ | affine | increasing | none |
4847
| `sum(x, k)` | sum elements across dimension $k$ | affine | increasing | none |
4948
| `sumlargest(x, k)` | sum of $k$ largest elements of $x$ | convex | increasing | none |
@@ -82,7 +81,7 @@ any solver that can solve both LPs and SOCPs can solve the problem.
8281
| `sumsquares(x)` | $\sum x_i^2$ | convex | increasing on $x \ge 0$ decreasing on $x \le 0$ | none |
8382
| `sqrt(x)` | $\sqrt{x}$ | concave | decreasing | IC: $x>0$ |
8483
| `square(x), x^2` | $x^2$ | convex | increasing on $x \ge 0$ decreasing on $x \le 0$ | PR : $x$ is scalar |
85-
| `dot(^)(x,2)` | $x.^2$ | convex | increasing on $x \ge 0$ decreasing on $x \le 0$ | elementwise |
84+
| `x .^ 2` | $x.^2$ | convex | increasing on $x \ge 0$ decreasing on $x \le 0$ | elementwise |
8685
| `geomean(x, y)` | $\sqrt{xy}$ | concave | increasing | IC: $x\ge0$, $y\ge0$ |
8786
| `huber(x, M=1)` | $\begin{cases} x^2 &\|x\| \leq M \\ 2M\|x\| - M^2 &\|x\| > M \end{cases}$ | convex | increasing on $x \ge 0$ decreasing on $x \le 0$ | PR: $M>=1$ |
8887

@@ -94,13 +93,14 @@ Exponential Cone Representable Functions
9493
An optimization problem using these functions can be solved by any
9594
exponential cone solver (SCS).
9695

97-
| operation | description | vexity | slope | notes |
98-
|-------------------|-----------------------------------|---------|---------------|-----------|
99-
| `logsumexp(x)` | $\log(\sum_i \exp(x_i))$ | convex | increasing | none |
100-
| `exp(x)` | $\exp(x)$ | convex | increasing | none |
101-
| `log(x)` | $\log(x)$ | concave | increasing | IC: $x>0$ |
102-
| `entropy(x)` | $\sum_{ij} -x_{ij} \log (x_{ij})$ | concave | not monotonic | IC: $x>0$ |
103-
| `logisticloss(x)` | $\log(1 + \exp(x_i))$ | convex | increasing | none |
96+
| operation | description | vexity | slope | notes |
97+
|-----------------------|-----------------------------------|---------|---------------|----------------|
98+
| `logsumexp(x)` | $\log(\sum_i \exp(x_i))$ | convex | increasing | none |
99+
| `exp(x)` | $\exp(x)$ | convex | increasing | none |
100+
| `log(x)` | $\log(x)$ | concave | increasing | IC: $x>0$ |
101+
| `entropy(x)` | $\sum_{ij} -x_{ij} \log(x_{ij})$ | concave | not monotonic | IC: $x>0$ |
102+
| `logisticloss(x)` | $\log(1 + \exp(x_i))$ | convex | increasing | none |
103+
| `relative_entropy(x, y)` | $\sum_i x_i \log(x_i / y_i)$ | convex | not monotonic | IC: $x>0, y>0$ |
104104

105105
Semidefinite Program Representable Functions
106106
--------------------------------------------

docs/src/release_notes.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ Breaking changes:
77
* `x + A` will error if `x` is a scalar variable and `A` is an array. Instead, use `x * ones(size(A)) + A`.
88
* The `RelativeEntropyAtom` now returns a scalar value instead of elementwise values. This does not affect the result of `relative_entropy`.
99
* The function `constant` should be used instead of the type `Constant` (which now refers to exclusively real constants).
10+
* The syntaxes `dot(*)`, `dot(/)` and `dot(^)` have been removed in favor of explicit broadcasting (`x .* y`, `x ./ y`, and `x .^ y`). These were (mild) type piracy.
11+
* `vecdot(x,y)` has been removed. Call `dot(vec(x), vec(y))` instead.
1012
* DCP violations now throw a `DCPViolationError` exception by default, rather than a warning. Relatedly, `Convex.emit_dcp_warnings` has been removed, and [`Convex.allow_dcp_violations`](@ref) added.
1113

1214
Other changes:
@@ -15,6 +17,7 @@ Other changes:
1517
* `geomean` supports more than 2 arguments
1618
* [Type piracy](https://docs.julialang.org/en/v1/manual/style-guide/#Avoid-type-piracy) of `imag` and `real` has been removed. This should not affect use of Convex. Unfortunately, piracy of `hcat`, `vcat`, and `hvcat` still remains.
1719
* `sumlargesteigs` now enforces that it's argument is hermitian.
20+
* Bugfix: `dot` now correctly complex-conjugates its first argument
1821

1922
## v0.15.4 (October 24, 2023)
2023

src/Convex.jl

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -271,7 +271,6 @@ include("utilities/tree_print.jl")
271271
include("utilities/tree_interface.jl")
272272
include("utilities/show.jl")
273273
include("utilities/iteration.jl")
274-
include("utilities/broadcast.jl")
275274
include("problem_depot/problem_depot.jl")
276275

277276
end

src/atoms/affine/dot.jl

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -10,15 +10,8 @@ ismatrix(::Any) = false
1010
# as extending singleton dimensions. We need to ensure that the inputs have the same
1111
# length, which broadcast will check for us if both inputs are vectors.
1212
asvec(x) = convert(AbstractExpr, ismatrix(x) ? vec(x) : x)
13-
_vecdot(x, y) = sum(broadcast(*, asvec(x), asvec(y)))
13+
_vecdot(x, y) = sum(broadcast(*, conj(asvec(x)), asvec(y)))
1414

1515
dot(x::AbstractExpr, y::AbstractExpr) = _vecdot(x, y)
1616
dot(x::Value, y::AbstractExpr) = _vecdot(x, y)
1717
dot(x::AbstractExpr, y::Value) = _vecdot(x, y)
18-
19-
if isdefined(LinearAlgebra, :vecdot) # defined but deprecated
20-
import LinearAlgebra: vecdot
21-
end
22-
Base.@deprecate vecdot(x::AbstractExpr, y::AbstractExpr) dot(x, y)
23-
Base.@deprecate vecdot(x::Value, y::AbstractExpr) dot(x, y)
24-
Base.@deprecate vecdot(x::AbstractExpr, y::Value) dot(x, y)

src/atoms/affine/multiply_divide.jl

Lines changed: 6 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -195,6 +195,10 @@ end
195195
# end
196196

197197
function dotmultiply(x, y)
198+
if size(x) == (1, 1) || size(y) == (1, 1)
199+
return x * y
200+
end
201+
198202
if vexity(x) != ConstVexity()
199203
if vexity(y) != ConstVexity()
200204
error(
@@ -223,39 +227,12 @@ function dotmultiply(x, y)
223227
return reshape(const_multiplier * vec(var), size(var)...)
224228
end
225229

226-
function broadcasted(
227-
::typeof(*),
228-
x::Union{Constant,ComplexConstant},
229-
y::AbstractExpr,
230-
)
231-
if x.size == (1, 1) || y.size == (1, 1)
232-
return x * y
233-
elseif size(y, 1) < size(x, 1) && size(y, 1) == 1
234-
return dotmultiply(x, ones(size(x, 1)) * y)
235-
elseif size(y, 2) < size(x, 2) && size(y, 2) == 1
236-
return dotmultiply(x, y * ones(1, size(x, 1)))
237-
else
238-
return dotmultiply(x, y)
239-
end
240-
end
241-
function broadcasted(
242-
::typeof(*),
243-
y::AbstractExpr,
244-
x::Union{Constant,ComplexConstant},
245-
)
246-
return dotmultiply(x, y)
247-
end
248-
249230
# if neither is a constant it's not DCP, but might be nice to support anyway for eg MultiConvex
250231
function broadcasted(::typeof(*), x::AbstractExpr, y::AbstractExpr)
251-
if x.size == (1, 1) || y.size == (1, 1)
252-
return x * y
253-
elseif vexity(x) == ConstVexity()
254-
return dotmultiply(x, y)
255-
elseif isequal(x, y)
232+
if isequal(x, y)
256233
return square(x)
257234
else
258-
return dotmultiply(y, x)
235+
return dotmultiply(x, y)
259236
end
260237
end
261238
function broadcasted(::typeof(*), x::Value, y::AbstractExpr)

src/atoms/second_order_cone/qol_elementwise.jl

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,16 @@ function broadcasted(::typeof(^), x::AbstractExpr, k::Int)
5656
error("raising variables to powers other than 2 is not implemented")
5757
end
5858

59+
# handle literal case
60+
function broadcasted(
61+
::typeof(Base.literal_pow),
62+
::typeof(^),
63+
x::AbstractExpr,
64+
::Val{k},
65+
) where {k}
66+
return broadcasted(^, x, k)
67+
end
68+
5969
invpos(x::AbstractExpr) = QolElemAtom(constant(ones(x.size[1], x.size[2])), x)
6070
function broadcasted(::typeof(/), x::Value, y::AbstractExpr)
6171
return dotmultiply(constant(x), invpos(y))

src/problem_depot/problems/affine.jl

Lines changed: 9 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -405,31 +405,31 @@ end
405405
::Type{T},
406406
) where {T,test}
407407
x = Variable(3)
408-
p = maximize(sum(dot(*)(x, [1, 2, 3])), x <= 1; numeric_type = T)
408+
p = maximize(sum(x .* [1, 2, 3]), x <= 1; numeric_type = T)
409409

410410
if test
411411
@test problem_vexity(p) == AffineVexity()
412412
end
413413
handle_problem!(p)
414414
if test
415415
@test p.optval 6 atol = atol rtol = rtol
416-
@test evaluate(sum((dot(*))(x, [1, 2, 3]))) 6 atol = atol rtol = rtol
416+
@test evaluate(sum(x .* [1, 2, 3])) 6 atol = atol rtol = rtol
417417
end
418418

419419
x = Variable(3, 3)
420-
p = maximize(sum(dot(*)(x, eye(3))), x <= 1; numeric_type = T)
420+
p = maximize(sum(x .* eye(3)), x <= 1; numeric_type = T)
421421

422422
if test
423423
@test problem_vexity(p) == AffineVexity()
424424
end
425425
handle_problem!(p)
426426
if test
427427
@test p.optval 3 atol = atol rtol = rtol
428-
@test evaluate(sum((dot(*))(x, eye(3)))) 3 atol = atol rtol = rtol
428+
@test evaluate(sum(x .* eye(3))) 3 atol = atol rtol = rtol
429429
end
430430

431431
x = Variable(5, 5)
432-
p = minimize(x[1, 1], dot(*)(3, x) >= 3; numeric_type = T)
432+
p = minimize(x[1, 1], 3 .* x >= 3; numeric_type = T)
433433

434434
if test
435435
@test problem_vexity(p) == AffineVexity()
@@ -441,7 +441,7 @@ end
441441
end
442442

443443
x = Variable(3, 1)
444-
p = minimize(sum(dot(*)(ones(3, 3), x)), x >= 1; numeric_type = T)
444+
p = minimize(sum(ones(3, 3) .* x), x >= 1; numeric_type = T)
445445

446446
if test
447447
@test problem_vexity(p) == AffineVexity()
@@ -453,7 +453,7 @@ end
453453
end
454454

455455
x = Variable(1, 3)
456-
p = minimize(sum(dot(*)(ones(3, 3), x)), x >= 1; numeric_type = T)
456+
p = minimize(sum(ones(3, 3) .* x), x >= 1; numeric_type = T)
457457

458458
if test
459459
@test problem_vexity(p) == AffineVexity()
@@ -465,16 +465,15 @@ end
465465
end
466466

467467
x = Variable(1, 3, Positive())
468-
p = maximize(sum(dot(/)(x, [1 2 3])), x <= 1; numeric_type = T)
468+
p = maximize(sum(x ./ [1 2 3]), x <= 1; numeric_type = T)
469469

470470
if test
471471
@test problem_vexity(p) == AffineVexity()
472472
end
473473
handle_problem!(p)
474474
if test
475475
@test p.optval 11 / 6 atol = atol rtol = rtol
476-
@test evaluate(sum((dot(/))(x, [1 2 3]))) 11 / 6 atol = atol rtol =
477-
rtol
476+
@test evaluate(sum(x ./ [1 2 3])) 11 / 6 atol = atol rtol = rtol
478477
end
479478

480479
# Broadcast fusion works

src/problem_depot/problems/sdp.jl

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2253,3 +2253,43 @@ end
22532253
] atol = atol rtol = rtol
22542254
end
22552255
end
2256+
2257+
# Using the formulation from:
2258+
# https://discourse.julialang.org/t/minimisation-of-operator-norm-solution-does-not-match-evaluated-value-convex-jl/102319/2
2259+
@add_problem sdp function sdp_issue_510(
2260+
handle_problem!,
2261+
::Val{test},
2262+
atol,
2263+
rtol,
2264+
::Type{T},
2265+
) where {T,test}
2266+
d₁ = 2
2267+
d₂ = 2
2268+
H = rand(ComplexF64, d₁ * d₂, d₁ * d₂)
2269+
U = exp(im * π * (H + H'))
2270+
K = rand(ComplexF64, d₁ * d₂, d₁ * d₂)
2271+
K *= d₁ / LinearAlgebra.tr(K' * K)
2272+
ρ = Semidefinite(d₂)
2273+
J = sum(
2274+
kron(
2275+
((1:d₁) .== j) * ((1:d₁) .== k)',
2276+
partialtrace(
2277+
U' *
2278+
(
2279+
K * kron(((1:d₁) .== j) * ((1:d₁) .== k)', I(d₂)) * K' -
2280+
kron(((1:d₁) .== j) * ((1:d₁) .== k)', ρ)
2281+
) *
2282+
U,
2283+
2,
2284+
[d₁, d₂],
2285+
),
2286+
) for j in 1:d₁, k in 1:d₁
2287+
)
2288+
constraints = [tr(ρ) == 1]
2289+
p = minimize(opnorm(J, Inf), constraints; numeric_type = T)
2290+
handle_problem!(p)
2291+
if test
2292+
@test p.optval opnorm(evaluate(J), Inf) atol = atol rtol = rtol
2293+
@test tr(evaluate(ρ)) 1 atol = atol rtol = rtol
2294+
end
2295+
end

0 commit comments

Comments
 (0)