Closed adienes closed 1 year ago
The transpose
docs already point to permutedims
as a non-recursive generalization: https://docs.julialang.org/en/v1/stdlib/LinearAlgebra/#Base.transpose
Related previous discussion: #4774, #20978
I'm quite confused why https://github.com/JuliaLang/julia/issues/20978 was closed
it looks like near the end, people were mostly in agreement that
[recursive] transpose however is lacking even a single motivation or actual use case.
or to put it under a trait
probably makes sense even if we do something else as well), some kind of type-check or trait for whether an element should do recursive transpose
So I'm confused. There seemed to be pretty solid consensus that transpose should be made non-recursive - e.g. https://github.com/JuliaLang/julia/issues/20978#issuecomment-285865225, https://github.com/JuliaLang/julia/issues/20978#issuecomment-285942526, https://github.com/JuliaLang/julia/issues/20978#issuecomment-285993057, https://github.com/JuliaLang/julia/issues/20978#issuecomment-348464449, and https://github.com/JuliaLang/julia/pull/23424.
I'll cast a small vote in favor of non-recursive transpose and ctranspose for AbstractArrays, with both being recursive on AbstractArray{T} where T<:AbstractArray.
and yet the issue was closed leaving transpose
recursive? 😕
I understand that this is in some cases mathematically consistent with other functions. however a Matrix{String}
is not really a mathematical object, just something I'm using for data preprocessing. if a Matrix
must be only objects that should be interpreted as linear maps / tensors / yada yada, then I shouldn't be able to construct a Matrix{String}
in the first place. actually with that said, I don't think this issue should have the linear algebra
label
.
this is one of those situations where it feels that we have let some esoteric principle win out over a really annoying usability problem. like really, take a step back from the linalg textbook for a second, does it really make sense that transpose(::Matrix{T})
only works if T
itself is transposable? to me that's such a strange design choice
[recursive] transpose however is lacking even a single motivation or actual use case
No, the recursiveness seems to be necessary for a transpose, consider the following:
transpose_necessary_property1(t, a) = (t∘t)(a) == a
transpose_necessary_property2(t, u, v) = t(v*u) == t(u)*t(v)
for candidate ∈ (permutedims, transpose)
v = [rand(2, 2) for _ ∈ 0:1, _ ∈ 0:2]
u = [rand(2, 2) for _ ∈ 0:2, _ ∈ 0:2]
transpose_necessary_property1(candidate, u) ||
println(candidate, " fails the first necessary property, can't be transpose")
transpose_necessary_property2(candidate, u, v) ||
println(candidate, " fails the second necessary property, can't be transpose")
end
It outputs:
permutedims fails the second necessary property, can't be transpose
This PR and the associated discussion are also relevant: #7244.
transpose_necessary_property2(t, u, v) = t(v*u) == t(u)*t(v)
this is only necessary if you treat the elements as scalars and every Matrix
as a linear map and not just an arbitrary AbstractArray
. for transpose
as a data preprocessing tool it is absolutely not necesary
which is exactly what I am protesting: I find it very silly that permutedims
is considered a generic Array
method but transpose
is only for linear algebra use, when it seems clear to me that transpose
should be a special case of permutedims
I understand that this has been discussed at length before, but reading through some threads I really don't see any good justification or consensus that transpose
should be recursive. it seems it is only this way as a historical accident + momentum, with justifications bolted on after the fact.
the only compelling use case at all I see in those discussions is to transpose block matrices, which should have been done with a new type + dispatch
All of our basic linear algebra operations are recursive.
Like *
, dot
and a few others.
It's required that transpose also be recursive to maintain a' * b == dot(a, b)
.
There is a strong case to be made that we should indeed get rid of this behaviour in Julia 2.0 (if that ever happens). And leave the representations of interesting vector spaces represented nested arrays to a special type -- not to Array
But we would need to get rid of whole recursive thing. Not just transpose.
Anyways this is breaking so this appropriate labels. We won't be able to do this any time soon (if ever), if we do every decide we want to do that.
leave the representations of interesting vector spaces represented nested arrays to a special type -- not to
Array
This reminds of the mathematical programming language Fricas. Its type system and standard library distinguish between:
"two-dimensional array" types, which are basically 2D tables and their element type is completely arbitary
"matrix" types, which may share some of their implementation with some "two-dimensional array" types, but their allowed element type is somewhat restricted (it must be a multiplicative monoid) so that the usual mathematical operations could be defined on them safely
However, it seems to me that the trend in Julia is to use traits instead of abstract types? So I guess adienes' suggestion may materialize partially, but only in Julia 2?
It's required that
transpose
also be recursive to maintaina' * b == dot(a, b)
.
I don't see transpose
in this expression, only '
which is adjoint
.
Rethinking this issue, I'm finding it a bit absurd. It's not even a feature request, seeing as the single-argument permutedims
method already behaves exactly as requested. So this issue could basically be rephrased as "please make transpose
not behave like a transpose for Matrix
", which is clearly nonsensical.
Perhaps the underlying issue is the already discussed way Julia's Base
and LinearAlgebra
conflate the non-mathematical "multidimensional table" and mathematical "multidimensional array/cartesian tensor" type categories, however:
If that's an issue, it should be a separate issue on Github.
It seems to me that this conflation may be just a red herring here. This is because, even if we got a cleaner design in the future, one that doesn't conflate non-algebraic and algebraic usage, I'm imagining that transpose
wouldn't even be defined for the non-algebraic/"just table" types, as it's really a linear/tensor algebra concept.
I follow, but do not agree with the argument.
anyway, looks like this is unlikely to change. thank you for the thoughts
You could just leave it open, many other open issues exist with the https://github.com/JuliaLang/julia/labels/speculative or https://github.com/JuliaLang/julia/labels/breaking labels.
I understand the argument for
adjoint
, buttranspose
is really something different. I think it's somewhat silly that e.g.Matrix{String}
cannot betranspose
'd. if a type wants to opt-in to recursive transpose it can do so via dispatch