Should Implicit Expansion be Applied to Additional Functions?

I know that some don't like implicit expansion. Given that it's likely here to stay, should it be made applicable to some additional functions? Just the other day I ran into a case like this, where one of X or Y is n x 3 and the other 1 x 3.
Z = X + Y;
Z = X - Y;
Z = dot(X,Y,2); % doesn't work
Is there some fundamental reason why dot can't support implicit expansion? If not, should it? Are there other functions, like cross, that should support implicit expansion?
Intresting to me is that the doc says: "Most binary (two-input) operators and functions in MATLAB® support numeric arrays that have compatible sizes. Two inputs have compatible sizes if, for every dimension, the dimension sizes of the inputs are either the same or one of them is 1." So most binary functions, but not all, support it. It would be nice if the doc had a single list of functions that support implicit expansion, or, if shorter, a list of binary functions that do not.

13 Kommentare

Well, your example with dot not working is rather poorly chosen, don't you agree?
Why is dot a poorly chosen example?
To the best of my understanding you get the extension of the dot-product in that case with a normal matrix-vector-product:
r_nby3 = randn(12,3);
r_1by3 = randn(1,3);
l_nby1 = r_nby3*r_1by3';
Or are you thinking about something completely different?
Actually, that approach doesn't work because, referring to my orginal case, either X or Y or both can have 1 or n rows. That matrix-vector-product won't work if X and Y both have m rows. So the replacment for the dot(X,Y,2) command is:
sum(conj(X).*Y,2)
which uses the implicit expansion on X or Y as the case may be. So dot can be easily replaced, but is there a reason why it can't or shouldn't allow for implicit expansion?
I suspect one reason is that it might be difficult to distinguish between the case of wrong input and input that should be expanded.
Note that you can still use bsxfun (although I'm not sure how to write the call in this case, it is too complex to write on mobile).
I suppose one ambiguous case would be:
X=rand(1,3);Y=rand(3,1);
dot(X,Y)
However, dot already handles this as a special case and could continue to do so. I think that implicit expansion would already work in (the compuational part of) dot as written when the dim argument is specified.
Regardless of whether dot is a good example or not, the broader question is if there are any binary operators or functions that don't support implicit expansion but perhaps should.
I still think it is a dubious case for implicit expansion. If you have r1 [n x 3] and r2 [m x 3] one implicit expansion of the dot might be the outer product r1*r2' givin us all n-by-m dot-products, but that will clash with (at least my) "natural" idea of a dot-product of 2 m-by-3 arrays (which dot already handles if I transpose the arrays) giving us a result that's m-by-1.
Bruno Luong
Bruno Luong am 10 Okt. 2020
Bearbeitet: Bruno Luong am 10 Okt. 2020
I write my own DOT and CROSS (pretty easy, actually I don't do DOT just sum on .* directly is ) that can deal with auto-expansion. That's pretty often encounted when you do geometric calcuation on a bunch of points.
I guess TMW is prudent and don't want to break backward compatibility, which I can understand when I see a few peoples still complain.
To me auto-expansion is one of the most important progress step they made in recent years. It pretty cool, one can make code faster, shorter and more readable.
Bjorn,
According to the rules of implicit expansion, if n > 1 and m > 1 then implicit expansion can't apply.
Bruno,
That's basically what I ended up doing for the exact reason you state. I needed to the take the dot product of a single vector with a bunch of other vectors. What backward compatibility would break?
Maybe this case would be an issue if implicit expansion is applied for dot:
dot(rand(3,1),rand(1,3),2)
Should the arguments both be expanded to 3 x 3 and then dot works along the second dimension? I doubt that's what any user would intend. Of course, these inputs could still be flagged as incompatible, as they are today (at least in 2019a).
So then your back to one array with size n x 3 and the other 1 x 3 (or some transpose-combination.) - then it is just to figure out which matrix-vector multiplication to do. If you have arrays with sizes n x 3 and n x 3, that's something dot already handles...
Exactly. The discussion here is about implicit expansion. So for this example where we want to dot across the second dimension, as in the original question, we must have a 1 x 3 and an n x 3. Currently dot, cross, and others(?) reject this pair of inputs. So the question in this comment thread is: should dot, cross, and others be upgraded to accept these inputs and apply implicit expansion? Yes, I can implement this myself, and I have, but that’s not really relevant to the discussion, unless your position is that because I can roll my own version there is no need for TMW to modify theirs.
Yes, "roll your own" is my opinion on this, whenever I've had these cases I've either handled it such that I know which sizes the input-arrays can have and used matrix-vector multiplication, or for cross-products explicit expressions for the cases. Since it is a couple of lines and with operations matlab is supposed to excell at I dont see the gain.
That argument could be used against any use case, in the sense that we all were able to work before implicit expansion came into being.
So, is that your opinion just for dot? Or do you think that implicit expansion is not needed for any functions for which it is not currently supported? Or maybe there are additional functions that don’t support it now, but you think they should? If the latter, what are those functions?

Melden Sie sich an, um zu kommentieren.

Antworten (2)

Yes, it should be extended to datetime() objects.
>> datetime() + hours(1:5).' + hours(1:3)
Data inputs must be the same size, or any of them can be a scalar.
>> hours(1:5).' + hours(1:3) + datetime()
ans =
5×3 datetime array
09-Oct-2020 19:05:40 09-Oct-2020 20:05:40 09-Oct-2020 21:05:40
09-Oct-2020 20:05:40 09-Oct-2020 21:05:40 09-Oct-2020 22:05:40
09-Oct-2020 21:05:40 09-Oct-2020 22:05:40 09-Oct-2020 23:05:40
09-Oct-2020 22:05:40 09-Oct-2020 23:05:40 10-Oct-2020 00:05:40
09-Oct-2020 23:05:40 10-Oct-2020 00:05:40 10-Oct-2020 01:05:40
>> bsxfun(@plus,(datetime() + hours(1:5)).', hours(1:3))
Error using bsxfun
Operands must be numeric arrays.

6 Kommentare

Ah, I just ran in R2020b and it looks like this has been done.
datetime() + hours(1:5).' + hours(1:3)
ans = 5×3 datetime array
10-Oct-2020 00:09:43 10-Oct-2020 01:09:43 10-Oct-2020 02:09:43 10-Oct-2020 01:09:43 10-Oct-2020 02:09:43 10-Oct-2020 03:09:43 10-Oct-2020 02:09:43 10-Oct-2020 03:09:43 10-Oct-2020 04:09:43 10-Oct-2020 03:09:43 10-Oct-2020 04:09:43 10-Oct-2020 05:09:43 10-Oct-2020 04:09:43 10-Oct-2020 05:09:43 10-Oct-2020 06:09:43
hours(1:5).' + hours(1:3) + datetime()
ans = 5×3 datetime array
10-Oct-2020 00:09:44 10-Oct-2020 01:09:44 10-Oct-2020 02:09:44 10-Oct-2020 01:09:44 10-Oct-2020 02:09:44 10-Oct-2020 03:09:44 10-Oct-2020 02:09:44 10-Oct-2020 03:09:44 10-Oct-2020 04:09:44 10-Oct-2020 03:09:44 10-Oct-2020 04:09:44 10-Oct-2020 05:09:44 10-Oct-2020 04:09:44 10-Oct-2020 05:09:44 10-Oct-2020 06:09:44
bsxfun(@plus,(datetime() + hours(1:5)).', hours(1:3))
Error using bsxfun
Operands must be numeric arrays.
So this is an example where implicit expansion works, but bsxfun does not? That seems like a very strange choice to me.
I agree, it is odd!
Yes, implicit expansion behavior was added to several operators and functions on datetime, duration, and/or calendarDuration in release R2020b.
Does the doc have a list of binary operators/functions that support implicit expansion, with notes on exeptions? By exceptions I mean as in Walter's original exmaple, i.e., the plus operator supports implicit expansion except when the operands are a datetime and a duration. If it does, I couldn't find it.

Melden Sie sich an, um zu kommentieren.

I wouldn't mind seeing it extended to the colon operator, instead of having to do things like this,
a=2;
b=[5,7,9];
c=arrayfun(@(q)a:q, b,'uni',0); %I'd rather just do a:b
c{:}
ans = 1×4
2 3 4 5
ans = 1×6
2 3 4 5 6 7
ans = 1×8
2 3 4 5 6 7 8 9

8 Kommentare

Paul's comment moved here:
This feature would be a bit more than implicit expansion because the color operator is currently not defined, per the doc, for the case:
[2,2,2]:[5,7,9] % see comment below
So first Matlab would have to define what the colon operator means for two non scalar inputs and then implicit expansion could be applied, at least for the two operand case.
Comment: Though the doc says that the operands to the colon operator are scalars, non-scalar inputs don't throw an error (much to my surprise)
>> [2,2,2]:[5,7,9]
ans =
2 3 4 5
So even if implicit expansion was applied and implemented for your example, the output would be different than what Matlab produces today, undocumented as it may be.
That behavior is documented, though not as prominently as it could be. On the documentation page for colon in the second syntax in the Description section: "If you specify nonscalar arrays, then MATLAB interprets j:i:k as j(1):i(1):k(1)."
But it doesn't say that for the first syntax in the Description section, which is the syntax under question here. And the Input Arguments section says that each input is a scalar. So if this usage is really supposed to be supported, that doc page needs to updated.
Do you know why the colon operator works thay way for non-scalar arrays? Or put another way, what use case takes advantage of that functionality of the colon operator, other than the case where the user actually wants to j(1):i(1):k(1) for nonsclar i, j, and/or k and just doesn't want to type that out?
I suspect this syntax does not have any interesting use case other than thet fact TMW programmers does not want to bother - or waste time for checking - for non-scalar arguments. This have been discovered and discussed when I prepare this FEX
In some cases, MATLAB gives warnings for non-scalar arguments to colon.
It is unfortunately not uncommon to see people write something like
for i=1:size(x)
... and when they do, more often than not, it is really the number of columns they want rather than the number of rows...
I don't think I have ever seen a good reason to permit non-scalars in the colon operator.
Matt J
Matt J am 11 Okt. 2020
Bearbeitet: Matt J am 11 Okt. 2020
I don't think I have ever seen a good reason to permit non-scalars in the colon operator.
I suppose I was really thinking that it might be good if combined with automatic comma separated list expansion. So, for example, instead of extracting a sub-array given its lower and upper limit vectors a and b,
M(a(1):2:b(1),a(2):2:b(2),a(3):2:b(3))
I could instead just do,
M(a:2:b)
I'm not completely certain, but I suspect Bruno Luong's answer is close to the mark. The colon operator dates back to a very early version of MATLAB, probably even Cleve's original Fortran MATLAB. I suspect Cleve didn't consider that people would use : with non-scalar values and so didn't check for that.
We've learned since then. Were we to redesign : today, we likely wouldn't allow non-scalar inputs without a good use case.
Matt J
Matt J am 11 Okt. 2020
Bearbeitet: Matt J am 11 Okt. 2020
We've learned since then. Were we to redesign : today, we likely wouldn't allow non-scalar inputs without a good use case.
In addition to the one I raised above, I think that a good case would in the use of griddedInterpolant. Instead of upsampling an array V by doing,
F=griddedInterpolant(V);
[m,n,p]=size(V);
Vq=F({1:0.5:m,1:0.5:n,1:0.5:p})
it would be much more sleek to do,
Vq=F({1:0.5:size(V)})

Melden Sie sich an, um zu kommentieren.

Kategorien

Produkte

Version

R2019a

Gefragt:

am 9 Okt. 2020

Kommentiert:

am 11 Okt. 2020

Community Treasure Hunt

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

Start Hunting!

Translated by