Indexing via 3d array changed behaviour 2015a -> 2015b?

Hi all, just got 2015b, here's a strange one where indexing via a multidimensional array has a differently shaped output to previous versions:
Code:
a = 1:10;
b = reshape(4:6,1,1,[]);
a(b)
2015a and before:
ans(:,:,1) =
4
ans(:,:,2) =
5
ans(:,:,3) =
6
2015b:
ans =
4 5 6
I searched through the release notes and couldn't find anything that relates to this behaviour change. Did I miss something? Or is this a bug that I should report?

1 comentario

I really hope someone answers this! It's very worrying that something as fundamental as array indexing might have quietly changed between versions. Of course the underlying problem is the inconsistent way indexing is applied to A(B) if both A and B are vectors. Since in this case isvector(b) returns 0, I think that the pre-2015b results are "correct", so to me it looks like a bug.

Iniciar sesión para comentar.

 Respuesta aceptada

Scott French
Scott French el 20 de Oct. de 2015
This was an intentional change/bug fix. Prior to R2015b, there was an inconsistency in the MATLAB indexing behavior - if you try your experiment in R2015a, but with the value of "a" being stored in a field of a struct, or an element of a cell, you'd get a different answer:
>> s.a = 1:10
s =
a: [1 2 3 4 5 6 7 8 9 10]
>> b=reshape(4:6, 1, 1, []);
>> s.a(b)
ans =
4 5 6
It didn't seem reasonable that the same value could be indexed by the same index, but give different results depending on where the value came from. So we changed it to give the same result.
The rule that we apply is, for an expression R(I) where R and I both have only one non-singleton dimension, then the dimensions of the result have the length of I, and the orientation of R.
Scott

5 comentarios

This approach suffers from the same problems that affect, for example,
mean(A(I:J, 1:10))
which produces a vector of 10 results of means along the first axis if J >= I+1 or J<I, but produces a scalar result if I==J. That is, you can end up computing possibilities that are normally not scalar along a dimension but on occasion might be scalar, and when they are scalar you suddenly get back a very different answer.
At least with mean() and sum() you can specify the dimension to work along to force the shape of result you expect, but you cannot do that with indexing.
Consistency between access forms is needed, but in any case where the shape or size of the output is determined by which dimension happens to be the first or only non-singular dimension, you need to provide a mechanism to select the dimension.
I know that something along the lines of
A(:,scalar K) = column vector
is very common in code, enough so that a lot of people never need to pay attention to whether they are using row or column vectors. "Get it working for beginners" is sometimes a pretty good argument. But automatic choice of dimensions also leads to bugs so in each case where dimensions are automatically chosen there needs to be an override mechanism.
Sven
Sven el 21 de Oct. de 2015
Editada: Sven el 21 de Oct. de 2015
Well, I agree with Walter that there is (and has always been) an inconsistency with indexing where
A = R(I)
  1. An answer (R) will have the same shape as its index (I) as long as that index isn't a vector.
  2. If both R and I are vectors, the answer (A) will actually have the shape of R.
Personally I think that just having #1 as the rule would be the most consistent. However this would be a change to the fundamental way results like below work so that's probably out of the question:
A = (1:5)';
R = A(1:3) % gives a 3-by-1 vector
I didn't realise that the rules above didn't apply if I happened to be a field of a structure - that's a bug and I'm glad it was addressed.
I'm still not convinced that that fixing this bug needed the introduction of a new inconsistency (between versions), but I'd be willing to be convinced that it's better.
At the moment though, I'd go with my 2-point rule above, where using isvector() on both R and I determines how the result gets shaped, rather than the rule "where R and I both have only one non-singleton dimension" (or perhaps isvector() should return true for this type of array too?).
Thank you both, Walter and Sven, for the feedback. I will make sure the rest of the indexing developers see it.
Sven, we actually did consider dropping rule 2 altogether, and when we prototyped it, enough current MATLAB code broke in our own products that we decided it would be unacceptable to customers. Balancing inconsistencies within a version of MATLAB versus inconsistencies across versions is a tricky task, but one that we take seriously.
Perhaps some kind of "strict vector orientation" setting could be added. Make it easy to use. Maybe put some detection into the code analyzer as a "best practice". Especially if you can add a convenient notation for "reshape this expression as a row vector" -- something easier than INDEXABLEEXPRESSION(:).' and something cleaner than reshape(NONINDEXABLEEXPRESSION,1,[]) . Maybe a ." operator?
Anyhow, do you have the facility for scoped pragmas? So someone could code
for K = 1 : 50 %#svo
... this code is under Strict Vector Orientation pragma
end
... the scope of %#svo ended
function myfunction %#svo
... entire function or subfunction is under %#svo
for K = 1 : 50 %#nosvo
... except this section
end
... we are back to %#svo
function mysubfunction
... subfunctions are scoped and so inherit %#svo or not
end
end
What would %#svo do, exactly? I'm not sure at the moment, but at the very least it would mean that assigning a vector of the wrong orientation to a vector slot would be detected as a shape error. Perhaps it should also mean that using the built-in routines that do automatic first-nonsingular dimension choice should be an error unless the dimension is explicitly provided. Maybe it should also mean Sven's Rule #2 should not be in effect.
One thing that needs to be distinguished is single index versus multiple index. R(I,J) should probably not depend upon the shape of I or J.
Hmmm... there is going to be a lot of code where a column vector is indexed by a row vector . Using R((I).') isn't so bad, but it would be nice if there was a column-vector form of P:Q without having to code (P:Q).'
Ramble.
Ramble cheerfully accepted.

Iniciar sesión para comentar.

Más respuestas (0)

Categorías

Productos

Etiquetas

Preguntada:

el 15 de Oct. de 2015

Comentada:

el 21 de Oct. de 2015

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!

Translated by