-
Notifications
You must be signed in to change notification settings - Fork 25
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Constrain type in to_vec(::AbstractArray/Vector)
#156
Conversation
to_vec(::AbstractArray/Vector)
to_vec(::AbstractArray/Vector)
I think the answer is just that no one has taken the time to fix it -- I had personally imagined that it would be annoying to have to modify a bunch of existing code in ChainRules, but if that's not the case, then great. Regarding bad things happening -- there might be a couple of surprised users, and perhaps the occassional issue asking why an |
src/to_vec.jl
Outdated
@@ -53,7 +53,7 @@ function to_vec(x::StridedVector) | |||
return x_vec, Vector_from_vec | |||
end | |||
|
|||
function to_vec(x::Union{SubArray, StridedArray}) | |||
function to_vec(x::Union{SubArray, Base.ReshapedArray, StridedArray}) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe the parent array of SubArray
should be restricted to e.g. StridedArray
or something?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We want e.g. a
julia> sa = @view randn(T, 10)[1:4]
julia> typeof(sa)
SubArray{Float64, 1, Vector{Float64}, Tuple{UnitRange{Int64}}, true}
to dispatch on the current SubArray
implementation. Unfortunately StridedArray
is a Union
of several more specific SubArrays
(not just in the parent argument)
So we have two options:
- Narrow the dispatch of the current
SubArray
(very verbose*) - Loosen the dispatch for
StridedArray
toUnion{StridedArray, SubArray}
so that the currentSubArray
becomes more specific.
And similarly for the ReshapedArray
.
I don't particularly like either option but it's probably better than the status quo.
*Number 1) looks like this, I want to nope out of that 😂
StridedSubArray = Union{
SubArray{T, N, A, I, true} where {T, N, A<:DenseArray, I<:Union{Tuple{Vararg{Real, N} where N}, Tuple{AbstractUnitRange, Vararg{Any, N} where N}}}, DenseArray}, MI<:Tuple{Vararg{Base.MultiplicativeInverses.SignedMultiplicativeInverse{Int64}, N} where N}},
SubArray{T, 1, A, I, L} where {A<:Union{Base.ReinterpretArray{T, N, S, A, IsReshaped} where {T, N, A<:Union{SubArray{T, N, A, I, true} where {T, N, A<:DenseArray, I<:Union{Tuple{Vararg{Real, N} where N}, Tuple{AbstractUnitRange, Vararg{Any, N} where N}}}, DenseArray}, IsReshaped, S},
SubArray{T, N, A, I, true} where {T, N, A<:DenseArray, I<:Union{Tuple{Vararg{Real, N} where N}, Tuple{AbstractUnitRange, Vararg{Any, N} where N}}}, DenseArray}, MI<:Tuple{Vararg{Base.MultiplicativeInverses.SignedMultiplicativeInverse{Int64}, N} where N}}, DenseArray}, I<:Tuple{Vararg{Union{Int64, AbstractRange{Int64}, Base.AbstractCartesianIndex, Base.ReshapedArray{T, N, A, Tuple{}} where {T, N, A<:AbstractUnitRange}}, N} where N}, L}} where T)
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@willtebbutt how do you feel about that?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The thing I'm concerned about is if someone attempts to to_vec
something like
view(Diagonal(randn(5)), 1:5, 1:3)
*Number 1) looks like this, I want to nope out of that 😂
Lol yeah, that's really not fun.
Is there a reason that we can't go with something like
Union{StridedArray, SubArray{T, D, <:StridedArray} where {T, D}}
and just recurse into ReshapedArray
s?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The dispatch for the Diagonal
example is the same (the dedicated SubArray
method) whether we constrain the parent of the SubArray
to be strided or not.
The example breaks, but because SparseArray.SparseMatrixCSC
does not have a to_vec
defined.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The status is:
- All tests pass with the current PR
- Removing the
to_vec(Base.SubArray)
breaks some tests test_to_vec(view(Diagonal(randn(5)), 1:5, 1:3); check_inferred=false)
, (the thing you suggested should be checked) breaks on master (StackOverflowError
), on the current PR (SparseMatrixCSC
error), and on the current PR withSubArray
removed from the Union (SparseMatrixCSC
error).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ahh I see.
I've run it further locally, and found that the following seems to resolve everything for me:
- restrict the array methods to
DenseVector
andDenseArray
, fromUnion{StridedArray...}
- add a specific method for
SubArray
:
function to_vec(x::SubArray)
x_vec, from_vec = to_vec(x.parent)
SubArray_from_vec(x_vec) = view(from_vec(x_vec), x.indices...)
return x_vec, SubArray_from_vec
end
if you don't have this, it thinks that the integer fields should also be to_vec
ed.
3. comment out the SubArray
-specific method
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh yeah that's much better. Are we happy with that?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actually with this one ChainRules test fails, and the reason is that the current implementation returns the whole parent vector
julia> a = rand(7);
julia> b = @view a[2:5];
julia> v, back = to_vec(b);
julia> v
7-element Vector{Float64}:
0.9586867155061674
0.8025760289977295
0.9784238101274141
0.16440182965461236
0.17784328126321847
0.01704930118685577
0.8408143603848348
Keeping the old version below works just fine. No issues now StridedArray
has been replaced by DenseArray
(where we used to have AbstractArray
)
to_vec(x::SubArray) = to_vec(copy(x))
to_vec(::AbstractArray/Vector)
to_vec(::AbstractArray/Vector)
This is looking pretty good now I think. Do we need to bump the minor version, or would a patch bump suffice? |
I've made sure ChainRules tests are fine but technically it is still a breaking change, no? |
Im not sure which bit is really breaking. Could you elaborate? |
julia> subtypes(AbstractArray)
31-element Vector{Any}:
AbstractRange
Base.LogicalIndex
Base.ReinterpretArray
Base.ReshapedArray
Base.SCartesianIndices2
BitArray
CartesianIndices
Core.Compiler.AbstractRange
Core.Compiler.BitArray
Core.Compiler.LinearIndices
DenseArray
LinearAlgebra.AbstractQ
LinearAlgebra.AbstractTriangular
LinearAlgebra.Adjoint
LinearAlgebra.Bidiagonal
LinearAlgebra.Diagonal
LinearAlgebra.Hermitian
LinearAlgebra.LQPackedQ
LinearAlgebra.SymTridiagonal
LinearAlgebra.Symmetric
LinearAlgebra.Transpose
LinearAlgebra.Tridiagonal
LinearAlgebra.UpperHessenberg
LinearIndices
PermutedDimsArray
SparseArrays.AbstractSparseArray
StaticArrays.StaticArray
StaticArrays.TrivialView
SubArray
SuiteSparse.CHOLMOD.FactorComponent
Test.GenericArray I guess unless a special |
This is my view -- if anyone opens an issue indicating that we broke their code, I'm more than happy to add a A third opinion would be great though. |
test/to_vec.jl
Outdated
test_to_vec(SVector{2, T}(1.0, 2.0); check_inferred = false) | ||
test_to_vec(SMatrix{2, 2, T}(1.0, 2.0, 3.0, 4.0); check_inferred = false) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
test_to_vec(SVector{2, T}(1.0, 2.0); check_inferred = false) | |
test_to_vec(SMatrix{2, 2, T}(1.0, 2.0, 3.0, 4.0); check_inferred = false) | |
test_to_vec(SVector{2, T}(1.0, 2.0); check_inferred=false) | |
test_to_vec(SMatrix{2, 2, T}(1.0, 2.0, 3.0, 4.0); check_inferred=false) |
Bluetyle spacing in kwargs
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
changed in other places as well now
I think we need a test for a custom wrapper array, something like is like NamedDimsArray.
and make sure that still acts in a way we are happy with. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we can say this is a patch
I've looked into whether we can simply constrain the
to_vec
genericAbstractVector/Array
toStrided
, and it almost works.It's just these
ChainRules
tests which need theSubArray
in theUnion
(I didn't investigate why theSubArray
s inside theStrided
Union
do not contain this case):https://github.com/JuliaDiff/ChainRules.jl/blob/38caf4bfdb8af616fcbe7626d10699608af21904/test/rulesets/Base/arraymath.jl#L36-L42
@willtebbutt this seems to solve a lot of issues that we were seeing (#149, #141).
Is there a reason we haven't changed this before? I guess partly because it is breaking, but are there any bad things that can happen if we go ahead with this? It seems like using the struct fallback is a better choice for most things that subtype
AbstractArray
s?