Constructing matrices

333 views
Skip to first unread message

Bill Hart

unread,
Feb 23, 2015, 3:05:19 PM2/23/15
to julia...@googlegroups.com
I'm writing some code which takes 2-dimensional Julia arrays and converts them to an external matrix type.

For example Mat([1 2; 3 4; 5 6]) creates a 3x2 matrix.

But I cannot figure out the syntax for nx1 arrays in Julia.

Note that I need to be able to construct nx1 and 1xn matrices.

I assumed the syntax would be [1 2 3] for 1x3 and [1; 2; 3] for 3x1. But this doesn't seem to work, currently. It looks like the latter is a synonym for [1, 2, 3], which makes no sense at all to me.

Also, what's with 

julia> transpose(transpose([1; 2; 3])) == [1; 2; 3]
false

?


Pablo Zubieta

unread,
Feb 23, 2015, 3:16:27 PM2/23/15
to julia...@googlegroups.com
Yeah, I have never thought of that, but it seems kind of confusing.

You can do

julia> hvcat(1, 1, 2, 3)
3x1 Array{Int64,2}:
 
1
 
2
 
3

julia
> hvcat(1, 1, 2, 3)'' == hvcat(1, 1, 2, 3)
true

Greetings.

Bill Hart

unread,
Feb 24, 2015, 8:02:52 AM2/24/15
to julia...@googlegroups.com
Thanks. The hvcat is somewhat awkward as a matrix syntax.

But from your hint I also see that [[1]'; 2; 3] or [1 2 3]' works.

That's a bit ugly, but workable for now. I really wish the semicolon had been reserved for terminating the row of a matrix.

Clearly Julia wants to deliberately conflate row and column vectors, which is fine if you aren't working with an algorithm that depends on the individual dimensions of your matrices, and you aren't interfacing to an external library.

Jiahao Chen

unread,
Feb 24, 2015, 8:30:19 AM2/24/15
to julia...@googlegroups.com
Clearly Julia wants to deliberately conflate row and column vectors, which is fine if you aren't working with an algorithm that depends on the individual dimensions of your matrices, and you aren't interfacing to an external library.

Could you elaborate on what you mean here? As part of Issue #4474 I've been trying to collect specific examples. 

Bill Hart

unread,
Feb 24, 2015, 9:18:28 AM2/24/15
to julia...@googlegroups.com
The specific use case where I hit this as a problem is in wrapping external libraries like flint and pari, which unlike julia do not conflate 1xn matrices with flat arrays.

However, I have just realised that Julia only conflates column vectors with flat arrays, not row vectors.

Therefore I can overload my constructor for the external flint and pari types to interpret Julia flat arrays as column vectors. Fortunately, I only need to do that in one place. I can't imagine overloading every single function for every possible combination of flat array vs matrix for each parameter to the function.

The only reason I did things that way is because I initially thought Julia arrays had cartesian product semantics (pointwise operations) rather than matrix semantics.

So actually, I guess I can live with the way things are right now. 

David P. Sanders

unread,
Feb 24, 2015, 2:39:14 PM2/24/15
to julia...@googlegroups.com


El martes, 24 de febrero de 2015, 8:18:28 (UTC-6), Bill Hart escribió:
The specific use case where I hit this as a problem is in wrapping external libraries like flint and pari, which unlike julia do not conflate 1xn matrices with flat arrays.

However, I have just realised that Julia only conflates column vectors with flat arrays, not row vectors.

That is not my interpretation. Julia carefully distinguishes between the different options:

(i) a 1D object (which could be called a "vector"), i.e. with 1 index (what I understand you mean by "flat array"):

julia> v = [3, 4, 5, 6]
4-element Array{Int64,1}:
 3
 4
 5
 6

This is (unfortunately?) displayed in a column, but is just a one-dimensional list of things.

(ii) A matrix object of size  1 x n  (which could be called a "row vector", but is actually a matrix):

julia> w = [3 4 5 6]
1x4 Array{Int64,2}:
 3  4  5  6

(iii) A matrix of size  n x 1   (which could be called a "column vector", but is actually a matrix):
julia> z = reshape([3, 4, 5, 6], (4,1)) 
4x1 Array{Int64,2}:
 3
 4
 5
 6

(The output looks superficially the same as that for v, but the object is of a different type -- Array{Int64, 2} vs. Array{Int64, 1}. I.e. there are now *two* indices.)

I do not find the nomenclature "row vector" and "column vector" useful in this (or almost any other!) context.

David.

Bill Hart

unread,
Feb 24, 2015, 2:46:38 PM2/24/15
to julia...@googlegroups.com
Julia distinguishes between them at the level of types, yes. I was talking about the syntax for creating them. There they become conflated.

[1; 2; 3] is precisely the same thing as [1, 2, 3]

Sorry for not being clearer about that.

It's clear this is done intentionally, not accidentally. It's just extremely confusing and I'll bet it will bite somewhere down the track. It's especially bad for metaprogramming for example.

Bill.

Kevin Squire

unread,
Feb 24, 2015, 5:18:52 PM2/24/15
to julia...@googlegroups.com
I (think I) would be in favor of changing [1; 2; 3] to mean a 1-column matrix.  Arguments against?

Kevin

Bill Hart

unread,
Feb 24, 2015, 5:42:23 PM2/24/15
to julia...@googlegroups.com
This might not be a trivial change. Presumably its done this way so that functions like linear solving do not take a column matrix as one of its inputs (which maybe has a relatively inefficient representation?), but so that they can take a flat array as input, which does have an efficient representation.

So it might not just be a matter of changing the syntax. Users who are currently using [1; 2; 3] with such functions would have to switch to using [1, 2, 3]. Or, the functions that currently expect flat array inputs when they really mean column would have to be changed to accept the other.

I understand the logic of why this was done. I just don't prefer it on consistency grounds, especially given that it was nontrivial to work out how to generate an actual nx1 matrix.

I'm all in favour of changing it. I just don't think it was an accident. The documentation explicitly mentions that Julia uses a flat array instead.

Matt Bauman

unread,
Feb 24, 2015, 6:18:57 PM2/24/15
to julia...@googlegroups.com
I don't understand the distinction you're making between "flat arrays" and "column matrices."  Internally, the vectors and matrices are laid out identically, with the exception that there are two dimensions instead of one and that 2D arrays cannot grow.  This is how `vec` is able to convert matrices to 1D vectors without copying the data.  I would be very surprised if there was a performance difference between the two (when using logical indexing for both).  There is, however, a difference in how they behave.

There's already a major change slated for the [a,b] and [a;b] syntaxes — they will no longer be equivalent once the switch is flipped on https://github.com/JuliaLang/julia/pull/8599.  The former will always be a 1D vector of its arguments.  The latter will perform a vertical concatenation of its arguments.  The result shape will be dependent upon the shapes of its arguments — it could be 1D or more.  I agree that changing it to always be at least 2D has some merit.  Now would certainly be the time to do it!

Bill Hart

unread,
Feb 24, 2015, 7:10:48 PM2/24/15
to julia...@googlegroups.com
On 25 February 2015 at 00:18, Matt Bauman <mba...@gmail.com> wrote:
I don't understand the distinction you're making between "flat arrays" and "column matrices."  Internally, the vectors and matrices are laid out identically, with the exception that there are two dimensions instead of one and that 2D arrays cannot grow.  

Sure. I only mean that you have extra data and extra branches to deal with 2D instead of 1D arrays. I agree it's probably slight. But I can't believe someone did this accidentally without having a performance reason in mind. Perhaps I am just wrong.
 
This is how `vec` is able to convert matrices to 1D vectors without copying the data.  I would be very surprised if there was a performance difference between the two (when using logical indexing for both).  There is, however, a difference in how they behave.

There's already a major change slated for the [a,b] and [a;b] syntaxes — they will no longer be equivalent once the switch is flipped on https://github.com/JuliaLang/julia/pull/8599.  The former will always be a 1D vector of its arguments.  The latter will perform a vertical concatenation of its arguments.  The result shape will be dependent upon the shapes of its arguments — it could be 1D or more.  

How can a vertical concatenation yield a 1D array? 

julia> [1 1 1; 2 2 2; 3 3 3]
3x3 Array{Int64,2}:
 1  1  1
 2  2  2
 3  3  3

julia> [1 1; 2 2; 3 3]
3x2 Array{Int64,2}:
 1  1
 2  2
 3  3

Surely I expect

julia> [1; 2; 3]
3x1 Array{Int64, 2}:
 1
 2
 3
 
I agree that changing it to always be at least 2D has some merit.  Now would certainly be the time to do it!

Since I can't understand how you could end up with 1D, I obviously prefer 2D as the minimum result. I am quite happy for it to be higher of course, if the arguments have higher than 1D.

One of my (mathematical) colleagues today asked about 0D arrays. He claims to have met nasty corner cases in code because 0xn and nx0 arrays were not supported in the language he was using.

I don't know what that would look like. [ ; ; ; ; ] perhaps, for columns. And [[] [] [] []] for rows? Though to be fair, I can't imagine an actual user creating arrays this way. They probably only need to be supported at the type level, not at the literal level. 

It seems like these are supported at the type level. With some work I found that the following constructs a 3x0: [[]'; []'; []']

This came up because I showed him what [[1]; [2]; [3]] resulted in. Neither of us could have predicted the outcome.

We tried [[]; []; []] and couldn't predict the outcome there either.

By the way, we found a strange thing with array printing. The following prints a huge space before the array:

[1 2; BigInt(10)^1000 3]

We think it is deliberate, but weren't sure. We couldn't construct an example where this would be wanted behaviour, except perhaps in a kind of divide and conquer printing routine where you want rows to line up when printing multiple matrices next to each other, where the size of the maximum entry over all the matrices is known in advance, for example.

We then decided that printing of large objects would be a good thesis topic. :-)

Bill Hart

unread,
Feb 24, 2015, 7:58:06 PM2/24/15
to julia...@googlegroups.com
Sorry, I wrote 0D array, when I actually meant 0xn or nx0 arrays, (which my colleague and I agree should be 2D).

Luis Benet

unread,
Feb 26, 2015, 1:55:39 PM2/26/15
to julia...@googlegroups.com
Just a tiny little note on:


[1; 2; 3] is precisely the same thing as [1, 2, 3]

julia> [1; 2; 3] == [1,2,3]
true

julia> [1; 2; 3] === [1,2,3]
false
 
Luis

Bill Hart

unread,
Feb 26, 2015, 2:07:58 PM2/26/15
to julia...@googlegroups.com
Yeah, but that's nothing to do with the syntax. After all:

julia> [1, 2, 3] === [1, 2, 3]
false

julia> [1; 2; 3] === [1; 2; 3]
false

Reply all
Reply to author
Forward
0 new messages