Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Octave and Matlab "wat" matrix/vector inconsistencies

I've noticed various cases in Matlab and octave where functions accept both matrices and vectors, but doesn't do the same thing with vectors as it does with matrices.

This can be frustrating because when you input a matrix with a variable number of rows/columns, it could be interpreted as a vector and do something you don't expect when the height/width is 1 making for difficult debugging and weird conditional edge cases.

I'll list a few I've found, but I'm curious what others people have run into

(Note: I'm only looking for cases where code accepts matrices as valid input. Anything that raises an exception when a non-vector matrix is given as an argument doesn't count)

1) "diag" can be used to mean diagonal of a matrix or turn a vector into a diagonal matrix

Since the former is generally only used for square matrices this isn't so egregious in matlab, but in Octave it can be particularly painful when Octave interperets a vector beginning with a nonzero element and everything else zeros as a "diagonal matrix" ie

t=eye(3);
size(diag(t(:,3))) == [3,3]
size(diag(t(:,2))) == [3,3]
size(diag(t(:,1))) == [1,1]

2) Indexing into a row-vector with logicals returns a row-vector

Indexing into anything else with logicals returns a column vector

a = 1:3;
b = true(1,3);
size(a(b)) == [1, 3]
a = [a; a];
b = [b; b];
size(a(b)) == [6, 1]

3) Indexing into a vector v with an index vector i returns a vector of the same (row/col) type as v. But if either v or i is a matrix, the return value has the same size as i.

a = 1:3;
b = a';
size(a(b)) == [1, 3]
b = [b,b];
size(a(b)) == [3, 2]

4) max, min, sum etc. operate on the columns of a matrix M individiually unless M is 1xn in which case they operate on M as a single row-vector

a = 1:3
size(max(a)) == [1, 1]
a = [a;a]
size(max(a)) == [1, 3]

max is particularly bad since it can't even take a dimension as an argument (unlike sum)

What other such cases should I watch out for when writing octave/matlab code?

like image 332
dspyz Avatar asked Apr 19 '13 20:04

dspyz


1 Answers

Each language has its own concepts. An important point of this language is to very often think of matrices as an array of vectors, each column an entry. Things will start to make sense then. If you don't want that behavior, use matrix(:) as the argument to those functions which will pass a single vector, rather than a matrix. For example:

octave> a = magic (5);
octave> max (a)
ans =

   23   24   25   21   22

octave> max (a(:))
ans =  25

1) This is not true with at least Octave 3.6.4. I'm not 100% sure but may be related related to this bug which has already been fixed.

2) If you index with boolean values, it will considered to be a mask and treated as such. If you index with non-boolean values, then it's treated as the indexes for the values. This makes perfect sense to me.

3) This is not true. The returned has always the same size of the index, independent if it's a matrix or vector. The only exception is that if the index is a vector, the output will be a single row. The idea is that indexing with a single vector/matrix returns something of the same size:

octave> a = 4:7
a =

   4   5   6   7

octave> a([1 1])
ans =

   4   4

octave> a([1 3])
ans =

   4   6

octave> a([1 3; 3 1])
ans =

   4   6
   6   4

4) max does take dimension as argument at least in Octave. From the 3.6.4 help text of max:

For a vector argument, return the maximum value. For a matrix argument, return the maximum value from each column, as a row vector, or over the dimension DIM if defined, in which case Y should be set to the empty matrix (it's ignored otherwise).

The rest applies like I said on the intro. If you supply a matrix, it will think of each column as a dataset.

like image 103
carandraug Avatar answered Oct 12 '22 19:10

carandraug