Skip to content
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

Should "matrixes" work for all sizes including "degenerate" 1x1? Is it handled differently by design? #9208

Closed
PallHaraldsson opened this issue Dec 1, 2014 · 10 comments

Comments

@PallHaraldsson
Copy link
Contributor

in 0.3.3:

julia> [2.0]^2
ERROR: * has no method matching *(::Array{Float64,1}, ::Array{Float64,1})
in power_by_squaring at intfuncs.jl:56
in ^ at intfuncs.jl:86

1x1 matrix, a degenerate one, is maybe not too useful.. but it's not the same as a scalar (while not much of a difference - here).

I'm just not sure if this is a "bug" (as it is not too useful?). Is this intentional to prevent something common coding error "by design" (couldn't then an exception with a helpful message be used?). Do programs have to take arbitrary sizes matrixes in general? I'm not sure if down to 1x1 would happen in practice.. But for newbies trying out stuff errors like these are confusing.

julia> [2.0]_[2.0]
ERROR: _ has no method matching *(::Array{Float64,1}, ::Array{Float64,1})

I checked similar in Octave ("MATLAB") and there things work.

I just wander if this could be a symptom of some deeper problem.

By slicing ok:

julia> ([1.0 2.0; 3.0 4.0][1:1, 1:1])^2
1x1 Array{Float64,2}:
1.0

julia> ([1.0 2.0; 3.0 4.0][2:2, 2:2])^2
1x1 Array{Float64,2}:
16.0

@toivoh
Copy link
Contributor

toivoh commented Dec 1, 2014

The issue and the inconsistency here is that there is no simple canonical way to create 1x1 matrices. [2.0] is a vector. In Matlab/Octave, there is no difference between vectors and column matrices, so your example works (but that choice gives other problems, especially for arrays with more than two dimensions). 1x1 are definitely a legitimate corner case and should work like other square matrices.

Right now you can get a square 1x1 matrix as e.g. [2.0]'', since transpose currently makes vectors into matrices, but that might change at some point (see JuliaLang/LinearAlgebra.jl#42). So you can do e.g.

[2.0]''^2
1x1 Array{Float64,2}:
 4.0

which shows that you can take the square of a 1x1 matrix.

Still, I think we should have a better way of entering 1x1 matrices. I think [2.0;] has considered before, not sure why it wasn't implemented. Maybe it was just that nobody was bothered enough by this yet.

@vchuravy
Copy link
Member

vchuravy commented Dec 1, 2014

Your second example is matrix *matrix multiplication and the first one is a vector * vector multiplication.

# Matrix Array(T, 2)
julia> ones(1,1)
1x1 Array{Float64,2}:
 1.0

julia> [1.0]
1-element Array{Float64,1}:
 1.0

The multiplication of matrices is well defined, but vector multiplication is not uniquely defined [1]

As far as I know there are at least three different vector products in Julia

  • .* for element-wise multiplication
  • or dot(a,b) for the dot product
  • × or cross(a, b) for the cross product (The cross product is defined for vectors of length 3)

[1] http://mathworld.wolfram.com/VectorMultiplication.html

@PallHaraldsson
Copy link
Contributor Author

"In Matlab/Octave, there is no difference between vectors and column matrices"

My math may be getting rusty but isn't a vector just a thin matrix ("column matrix") - mathematically that is. In other words all Matrix functions should also take Vectors even considering:

Actually Matrix and Vector in Julia are both aliases of Array I though. By "alias" I guess still makes them different types.

"Still, I think we should have a better way of entering 1x1 matrices. I think [2.0;] has considered before, not sure why it wasn't implemented. Maybe it was just that nobody was bothered enough by this yet."

I wouldn't say I'm bothered, I knew that 1x1 Array is not the same as 1-element Array, understand the compsci difference, just not sure 1-element couldn't be processed as 1x1 mathematically.

[2.0;] wouldn't help I think, then you would have to explain that and newbies would stil do [2.0] and scratch their head :)

"but vector multiplication is not uniquely defined" if I understand correctly, can it be defined as a matrix? If not when "typed" in then used as such when the operator runs? Or will that lead to other more serious errors? If yes, what about a helpful error message, be defining the operation, but not really, using an "exception". Maybe there arror as is is considered discriptive..? :) Not to newbies at least.. And I get slightly different errors by changing things slightly.

In general, when you get an error as in this case, it is of course bad at runtime, but if it were fixed as I think might be possible it should not slow down any code that works/ed (non-degenerate matrixes) before (that is they would all generate the same code, only possibly compile-time would get tiny bit slower?), right?

Is there such a thing as a 0x0 matrix we might need to worry about (off topic: PostgreSQL has zero field tables by design..).

"1x1 are definitely a legitimate corner case" yes, as I thought, but is "1-element" really a legitimate one? Meaning would that happen in practice except by typing in exactly that case? I mean 1-element or even 0x0 matrix would not happen in any actual matrix algorithm?

julia> [2.0]*[2.0] # not sure why * is missing in my first "comment" on display (and not here).

@vchuravy
Copy link
Member

vchuravy commented Dec 1, 2014

This issue was discussed at length in multiple different places:

#6592 especially #6592 (comment)
JuliaLang/LinearAlgebra.jl#8
#2472
JuliaLang/LinearAlgebra.jl#42

currently the consent seems to be to treat Vectors and Matrices as different mathematical objects and let the user specify explicitly the kind of vector, vector product

@johnmyleswhite
Copy link
Member

We clearly need a different way to input arrays since the current system doesn't extend to tensors of higher order than 2. I think it's better to leave the 1x1 matrix case alone until we solve the broader problem.

@jwmerrill
Copy link

Another way to get a 1x1 matrix, which is less arcane than double transpose, is reshape.

e.g.

julia> m = reshape([2], 1, 1)
1x1 Array{Int64,2}:
 2

julia> m^2
1x1 Array{Int64,2}:
 4

This is probably the best way to get higher rank tensors right now too, until some other notation is invented.

@JeffBezanson
Copy link
Member

Or fill(2, 1, 1).

@deltakam
Copy link

deltakam commented Aug 9, 2016

This is an old thread, but this is a good a very good discussion. One natural thing I was trying is

Matrix([1;1])

, which currently spits out an error. To me, this is more readable. Was there any reason why it wasn't implemented?

@PallHaraldsson
Copy link
Contributor Author

PallHaraldsson commented Aug 9, 2016

@deltakam That seems a separate issue, that I do not know about [a relevant issue number]. You however "necromanced" my first (I believe) issue [I also leaded that word from a Julia-user discussion..], so I looked again into it:

@toivoh "Right now you can get a square 1x1 matrix as e.g. [2.0]''
[..]

[2.0]''^2
1x1 Array{Float64,2}:
4.0

which shows that you can take the square of a 1x1 matrix."

Actually, [2.0]'^2 will do it in that case.. but not recommended in general.. as in @deltakam example where you have to do transpose twice with:

Matrix([1;1]'') # while Matrix([1;1]') # does something different :)

I see this issue is still open: "Taking vector transposes seriously" JuliaLang/LinearAlgebra.jl#42

so either they are not taking vectors seriously enough, or taking them very seriously..

[I've seen some other such "taking seriously" issues.. some of them are actually solved.. And some still open or their children, see "arrayapocalypse".]

@eschnett
Copy link
Contributor

eschnett commented Aug 9, 2016

The syntax for a one-element tuple is (1,). Similarly, the syntax for a one-element matrix should probably be [1;], with a trailing semicolon inside the square brackets. A 0x0-matrix (also valid!) could then be [;], since [] already has a different meaning.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

8 participants