Skip to content

Commit de4bff2

Browse files
ericphansonodow
andauthored
[breaking] scalar row indexing produces column vector (#624)
* fix row vector bug * format * Fix docs * Update * Update * Update --------- Co-authored-by: odow <[email protected]>
1 parent eff138b commit de4bff2

File tree

3 files changed

+37
-13
lines changed

3 files changed

+37
-13
lines changed

docs/src/examples/optimization_with_complex_variables/power_flow_optimization.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ W = ComplexVariable(n, n);
1818
objective = real(sum(diag(W)));
1919
c1 = Constraint[];
2020
for i in 2:n
21-
push!(c1, sum(W[i, :] .* (Y[i, :]')) == inj[i])
21+
push!(c1, dot(Y[i, :], W[i, :]) == inj[i])
2222
end
2323
c2 = isposdef(W)
2424
c3 = real(W[1, 1]) == 1.06^2;

src/atoms/IndexAtom.jl

Lines changed: 16 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -9,18 +9,14 @@ mutable struct IndexAtom <: AbstractExpr
99
rows::Union{AbstractArray,Nothing}
1010
cols::Union{AbstractArray,Nothing}
1111
inds::Union{AbstractArray,Nothing}
12+
end
1213

13-
function IndexAtom(
14-
x::AbstractExpr,
15-
rows::AbstractArray,
16-
cols::AbstractArray,
17-
)
18-
return new((x,), (length(rows), length(cols)), rows, cols, nothing)
19-
end
14+
function IndexAtom(x::AbstractExpr, rows::AbstractArray, cols::AbstractArray)
15+
return IndexAtom((x,), (length(rows), length(cols)), rows, cols, nothing)
16+
end
2017

21-
function IndexAtom(x::AbstractExpr, inds::AbstractArray)
22-
return new((x,), (length(inds), 1), nothing, nothing, inds)
23-
end
18+
function IndexAtom(x::AbstractExpr, inds::AbstractArray)
19+
return IndexAtom((x,), (length(inds), 1), nothing, nothing, inds)
2420
end
2521

2622
head(io::IO, ::IndexAtom) = print(io, "index")
@@ -33,7 +29,11 @@ curvature(::IndexAtom) = ConstVexity()
3329

3430
function evaluate(x::IndexAtom)
3531
result = if x.inds === nothing
36-
getindex(evaluate(x.children[1]), x.rows, x.cols)
32+
# reshape to ensure we are respecting that a scalar row index
33+
# creates a column vector. We can't just check `length(x.rows)`
34+
# since that doesn't distinguish between `i` and `i:i`. But
35+
# we had that info when we set the size, so we will use it now.
36+
reshape(getindex(evaluate(x.children[1]), x.rows, x.cols), x.size)
3737
else
3838
getindex(evaluate(x.children[1]), x.inds)
3939
end
@@ -98,7 +98,11 @@ function Base.getindex(x::AbstractExpr, row::Real, col::Real)
9898
end
9999

100100
function Base.getindex(x::AbstractExpr, row::Real, cols::AbstractVector{<:Real})
101-
return getindex(x, row:row, cols)
101+
# In this case, we must construct a column vector
102+
# https://github.com/jump-dev/Convex.jl/issues/509
103+
# Here we construct `getindex(x, row:row, cols)`
104+
# except with the size set to be that of a column vector
105+
return IndexAtom((x,), (length(cols), 1), row:row, cols, nothing)
102106
end
103107

104108
function Base.getindex(x::AbstractExpr, rows::AbstractVector{<:Real}, col::Real)

test/test_atoms.jl

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -523,6 +523,26 @@ function test_IndexAtom()
523523
return
524524
end
525525

526+
function test_IndexAtom_issue_509()
527+
# *Scalar* indexing creates a column vector
528+
# https://github.com/jump-dev/Convex.jl/issues/509
529+
x = rand(2, 3)
530+
ϕ = Variable(2, 3)
531+
Convex.set_value!(ϕ, rand(2, 3))
532+
i = j = 1
533+
# "column-vector" in Convex.jl is a 1 column matrix
534+
@test size(ϕ[i, :]) == (3, 1)
535+
@test size(ϕ[i, 1:2]) == (2, 1)
536+
@test size(ϕ[i, [2, 1]]) == (2, 1)
537+
@test size(ϕ[i:i, :]) == (1, 3)
538+
@test size(evaluate(ϕ[i, :])) == (3,)
539+
@test size(evaluate(ϕ[i:i, :])) == (1, 3)
540+
# "Column vector", not 3x3 matrix!
541+
atom = broadcast(*, ϕ[i, :] - ϕ[j, :], x[i, :] - x[j, :])
542+
@test size(evaluate(atom)) == (3, 1)
543+
return
544+
end
545+
526546
### affine/MultiplyAtom
527547

528548
function test_MultiplyAtom()

0 commit comments

Comments
 (0)