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

array assignment a[1,:,:] = b fails even when b is the correct size #4048

Closed
ggggggggg opened this issue Aug 13, 2013 · 6 comments
Closed

array assignment a[1,:,:] = b fails even when b is the correct size #4048

ggggggggg opened this issue Aug 13, 2013 · 6 comments
Labels
breaking This change will break code needs decision A decision on this change is needed

Comments

@ggggggggg
Copy link
Contributor

Julia Studio 0.3.2

a = zeros((9,9,9))
b = ones((9,9))
println(size(a[1,:,:])) # (1,9,9)
a[1,:] = b
a[1,:,:] = b # argument dimensions must match

For comparison this works in both MATLAB and numpy.

python + numpy

In [10]: a = numpy.zeros((9,9,9))
In [11]: b = numpy.ones((9,9))
In [12]: a[1,:,:] = b
In [13]: a[1,:,:].shape
Out[13]: (9, 9)
In [14]: a[1,:] = b

Personally I feel it makes more sense to have the resulting array from a[1,:,:] have size (9,9) rather than (1,9,9). I also know that in MATLAB the leading singleton dimensions make plot fail where it would work with a 2d array, which is often annoying.

MATLAB

>> a = zeros(9,9,9);
>> b = ones(9,9);
>> a(1,:,:) = b;
>> size(a(1,:,:))
ans =
     1     9     9
>> a(1,:) = b;
Subscripted assignment dimension mismatch.

Here is a more extreme case, where I can't find any solution that works.

a = zeros((4,4,4,4))
b = ones((4,4))
a[1,1,:,:]=b # argument dimensions must match
a[1,1,:] = b # argument dimensions must match
a[1,:,1] = b # argument dimensions must match
a[1,:,:,1] = b # argument dimensions must match

All of the equivalent "extreme case" assignments do something in numpy. In MATLAB both of the unambiguous assignments (a[1,1,:,:]=b and a[1,:,:,1] = b) work, and the others do not.

I'm new to julia, so I'm not sure if you want the more ambiguous of these to work. For example its ambiguous in the "extreme case" what a[1,:,1] = b even means. But certainly the unambiguous subset of these assignments should work.

Also I don't know about the implementation, but from a user point of view this is similar to issue #4033

@timholy
Copy link
Member

timholy commented Aug 14, 2013

Personally I feel it makes more sense to have the resulting array from a[1,:,:] have size (9,9) rather than (1,9,9). I also know that in MATLAB the leading singleton dimensions make plot fail where it would work with a 2d array, which is often annoying.

Having array dimensions change on you simply because you index them with scalars rather than a range is a formula for lots of trouble.

What you're looking for is slice:

a = zeros((9,9,9))
s = slice(a, :, 3, :)
size(s) -> (9,9)

You can assign to your sliced array:

a = zeros((4,4,4,4))
b = ones((4,4))
s = slice(a, 1, 1, :, :)
copy!(s, b)
@assert squeeze(a[1,1,:,:], (1,2)) == b

@ggggggggg
Copy link
Contributor Author

I think there are already cases where case that array dimensions change based on whether you index them with a scalar or a range.

julia> a = zeros((4,4))
julia> a[1,1]
0.0
julia> a[1,1:1]
1x1 Float64 Array:
 0.0

Although maybe there is a good reason to see this differently since it is going down to a single element? But really I think input on what size arrays returned from thing should be is beyond me since I'm so new to julia.

Regardless, perhaps something like broadcasting could be used to allow assignment between arrays that differ only by singleton dimensions?

@Staross
Copy link

Staross commented Aug 19, 2013

Personally I feel like

a[1,:] = b

Shouldn't work, but

a[1,:,:] = b

should, because it's weird to put a 2D object into a 1D space (by doing an implicit reshape), it just doesn't fit in there.

The second one makes much more sense, because you have a stack of matrices and you simply put your matrix somewhere in the stack.

@BobPortmann
Copy link
Contributor

I agree with @Staross

@wenxgwen
Copy link

Let A has a size n x n x n, I feel that A[1,:,:] should have a size n x n, while A[1:1,:,:] should have a size 1 x n x n. This is much more consistent and uniform (since 1:1 is a range while 1 is not a range).

Currently, A[1,:,:] has a size 1 x n x n in Julia. This is not intuitive and is inconsistent (since A[1,1,1] is a scaler not a 1 x 1 x 1 Array).

@mschauer
Copy link
Contributor

Yes, assignment between arrays that differ only by singleton dimensions would make the design choice to keep those singleton dimensions in subscripted arrays friendlier.

This extension would be still conservative I think: a.) The assignment

A= rand(3,2,3,4)
A[3, :, :, 4] = zeros(2*3)

considers a 1-dimensional array as data without any shape already now and b.)

A[3, :, :, 4] = zeros(1,2,3)

is allowed as well.

Therefore = isn't very strict in the beginning because of a.) and this extension would not change the flavor of = a lot. It would make the treatment of singleton dimension more consitent, see b.) and one does not need to write assignments without any dimension check as in

b = zeros(2,3)
A[3, :, :, 4] = b[:]

JeffBezanson added a commit that referenced this issue Dec 28, 2013
…#4383

this rule ignores singleton dimensions, and allows the last dimension of
one side to match all trailing dimensions of the other.
JeffBezanson added a commit that referenced this issue Dec 28, 2013
…#4383

this rule ignores singleton dimensions, and allows the last dimension of
one side to match all trailing dimensions of the other.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
breaking This change will break code needs decision A decision on this change is needed
Projects
None yet
Development

Successfully merging a pull request may close this issue.

6 participants