[Numpy-discussion] Syntax Improvement for Array Transpose

Sebastian Berg sebastian at sipsolutions.net
Tue Jun 25 14:30:19 EDT 2019


On Tue, 2019-06-25 at 14:18 -0400, Cameron Blocker wrote:
> It seems to me that the general consensus is that we shouldn't be
> changing .T to do what we've termed matrix transpose or conjugate
> transpose. As such, the discussion of whether .T should be changed to
> throw errors or warnings on 1D arrays seems a bit off topic (not that
> it shouldn't be discussed). 
> 

Yeah, it is a separate thing and is likely better to be discussed after
the other discussion has somewhat settled down.

> My suggestion that conjugate transpose and matrix transpose be a
> single operation .H was partially because I thought it would fill 90%
> of the use cases while limiting the added API. The are times that I
> am batch processing complex-valued images when what I want is .MT
> with no conjugation, but I just figured those use cases would be rare
> or not benefit from a short as much, and we could then add .MT later
> if the demand presented itself. I agree that the fact that the
> difference in MATLAB is implicit is bad, to me .H is explicit to
> people working with complex numbers, but I could be wrong.
> 

True, a lot of use cases may be happy to use .H just to get the matrix
transpose operation (although that relies on no-copy semantics
possibly). On the other hand, it might be a confusing change to have .T
and .H not be interchangable, which is a point for `.mT` and `mH` even
if I am even more hesitant on it right now.

> In regards to Marten's earlier post on names, my preference is .mT
> for matrix transpose. I prefer .H if what is implemented is
> equivalent to .conj().T, but if what is implemented is equivalent to
> .conj().mT, then I'd prefer .mH for symmetry. 
> 
> I also hope there is a way to implement .H/.mH without a copy as was
> briefly discussed above, otherwise .H()/.mH() might be better at
> making the copy explicit.
> 

To be honest, the copy/no-copy thing is a going to be a small issue in
any case. There is the idea of no-copy for complex values. Which is
great, however, that does have the issue that it does not work for
object arrays, which have to call `.conjugate()` on each element (and
thus have to copy).

Which is not to say we cannot do it. If we go there, but it is a
confusion (also that .H and .T behave quite differently is). We can
return read-only views, which at least fixes one direction of
unintentional change here. Making it `.H()` could be better in that
regard...

- Sebastian


> On Tue, Jun 25, 2019 at 1:17 PM Todd <toddrjen at gmail.com> wrote:
> > I was saying we shouldn't change the default transpose operation to
> > be conjugate transpose.  We don't currently have a conjugate
> > transpose so it isn't an issue.  I think having a conjugate
> > transpose is a great idea, I just don't think it should be the
> > default.
> > 
> > On Tue, Jun 25, 2019 at 12:12 PM Ilhan Polat <ilhanpolat at gmail.com>
> > wrote:
> > > I think we would have seen a lot of evidence in the last four
> > > decades if this was that problematic.
> > > 
> > > You are the second person to memtion these bugs. Care to show me
> > > some examples of these bugs? 
> > > 
> > > Maybe I am missing the point here. I haven't seen any bugs
> > > because somebody thought they are just transposing.
> > > 
> > > Using transpose to reshape an array is a different story. That we
> > > can discuss. 
> > > 
> > > On Tue, Jun 25, 2019, 16:10 Todd <toddrjen at gmail.com> wrote:
> > > > That is how it is in your field, but not mine.  For us we only
> > > > use the conventional transpose, even for complex numbers.  And
> > > > I routinely see bugs in MATLAB because of its choice of
> > > > defaults, and there are probably many more that don't get
> > > > caught because they happen silently.
> > > > 
> > > > I think the principle of least surprise should apply here.  For
> > > > people who need the conjugate transform the know to make sure
> > > > they use the right operation.  But a lot of people aren't even
> > > > aware that there conjugate transpose exists, they are just
> > > > going to copy what they see in the examples without realizing
> > > > it does the completely wrong thing in certain cases.  They
> > > > wouldn't bother to check because they don't even know there is
> > > > a second transpose operation they need to look out for.  So it
> > > > would hurt a lot of people without helping anyone.
> > > > 
> > > > On Tue, Jun 25, 2019, 07:03 Ilhan Polat <ilhanpolat at gmail.com>
> > > > wrote:
> > > > > I have to disagree, I hardly ever saw such bugs and moreover
> > > > > <Zbar, Z> is not compatible if you don't also transpose it
> > > > > but expected in almost all contexts of matrices, vectors and
> > > > > scalars. Elementwise conjugation is well inline with other
> > > > > elementwise operations starting with a dot in matlab hence
> > > > > still consistent. 
> > > > > 
> > > > > I would still expect an conjugation+transposition to be the
> > > > > default since just transposing a complex array is way more
> > > > > special and rare than its ubiquitous regular usage.
> > > > > 
> > > > > ilhan
> > > > > 
> > > > > 
> > > > > On Tue, Jun 25, 2019 at 10:57 AM Andras Deak <
> > > > > deak.andris at gmail.com> wrote:
> > > > > > On Tue, Jun 25, 2019 at 4:29 AM Cameron Blocker
> > > > > > <cameronjblocker at gmail.com> wrote:
> > > > > > >
> > > > > > > In my opinion, the matrix transpose operator and the
> > > > > > conjugate transpose operator should be one and the same.
> > > > > > Something nice about both Julia and MATLAB is that it takes
> > > > > > more keystrokes to do a regular transpose instead of a
> > > > > > conjugate transpose. Then people who work exclusively with
> > > > > > real numbers can just forget that it's a conjugate
> > > > > > transpose, and for relatively simple algorithms, their code
> > > > > > will just work with complex numbers with little
> > > > > > modification.
> > > > > > >
> > > > > > 
> > > > > > I'd argue that MATLAB's feature of `'` meaning adjoint
> > > > > > (conjugate
> > > > > > transpose etc.) and `.'` meaning regular transpose causes a
> > > > > > lot of
> > > > > > confusion and probably a lot of subtle bugs. Most people
> > > > > > are unaware
> > > > > > that `'` does a conjugate transpose and use it habitually,
> > > > > > and when
> > > > > > for once they have a complex array they don't understand
> > > > > > why the
> > > > > > values are off (assuming they even notice). Even the MATLAB
> > > > > > docs
> > > > > > conflate the two operations occasionally, which doesn't
> > > > > > help at all.
> > > > > > Transpose should _not_ incur conjugation automatically. I'm
> > > > > > already a
> > > > > > bit wary of special-casing matrix dynamics this much, when
> > > > > > ndarrays
> > > > > > are naturally multidimensional objects. Making transposes
> > > > > > be more than
> > > > > > transposes would be a huge mistake in my opinion, already
> > > > > > for matrices
> > > > > > (2d arrays) and especially for everything else.
> > > > > > 
> > > > > > András
> > > > > > 
> > > > > > 
> > > > > > 
> > > > > > > Ideally, I'd like to see a .H that was the defacto
> > > > > > Matrix/Linear Algebra/Conjugate transpose that for 2 or
> > > > > > more dimensions, conjugate transposes the last two
> > > > > > dimensions and for 1 dimension just conjugates (if
> > > > > > necessary). And then .T can stay the Array/Tensor transpose
> > > > > > for general axis manipulation. I'd be okay with .T raising
> > > > > > an error/warning on 1D arrays if .H did not. I commonly
> > > > > > write things like u.conj().T at v even if I know both u and v
> > > > > > are 1D just so it looks more like an inner product.
> > > > > > >
> > > > > > > -Cameron
> > > > > > >
> > > > > > > On Mon, Jun 24, 2019 at 6:43 PM Ilhan Polat <
> > > > > > ilhanpolat at gmail.com> wrote:
> > > > > > >>
> > > > > > >> I think enumerating the cases along the way makes it a
> > > > > > bit more tangible for the discussion
> > > > > > >>
> > > > > > >>
> > > > > > >> import numpy as np
> > > > > > >> z = 1+1j
> > > > > > >> z.conjugate()  # 1-1j
> > > > > > >>
> > > > > > >> zz = np.array(z)
> > > > > > >> zz  # array(1+1j)
> > > > > > >> zz.T  # array(1+1j)  # OK expected.
> > > > > > >> zz.conj()  # 1-1j ?? what happened; no arrays?
> > > > > > >> zz.conjugate()  # 1-1j ?? same
> > > > > > >>
> > > > > > >> zz1d = np.array([z]*3)
> > > > > > >> zz1d.T  # no change so this is not the regular 2D array
> > > > > > >> zz1d.conj()  # array([1.-1.j, 1.-1.j, 1.-1.j])
> > > > > > >> zz1d.conj().T  # array([1.-1.j, 1.-1.j, 1.-1.j])
> > > > > > >> zz1d.T.conj()  # array([1.-1.j, 1.-1.j, 1.-1.j])
> > > > > > >> zz1d[:, None].conj()  # 2D column vector - no surprises
> > > > > > if [:, None] is known
> > > > > > >>
> > > > > > >> zz2d = zz1d[:, None]  # 2D column vector - no surprises
> > > > > > if [:, None] is known
> > > > > > >> zz2d.conj()  # 2D col vec conjugated
> > > > > > >> zz2d.conj().T  # 2D col vec conjugated transposed
> > > > > > >>
> > > > > > >> zz3d = np.arange(24.).reshape(2,3,4).view(complex)
> > > > > > >> zz3d.conj()  # no surprises, conjugated
> > > > > > >> zz3d.conj().T  # ?? Why not the last two dims swapped
> > > > > > like other stacked ops
> > > > > > >>
> > > > > > >> # For scalar arrays conjugation strips the number
> > > > > > >> # For 1D arrays transpose is a no-op but conjugation
> > > > > > works
> > > > > > >> # For 2D arrays conjugate it is the matlab's elementwise
> > > > > > conjugation op .'
> > > > > > >> #     and transpose is acting like expected
> > > > > > >> # For 3D arrays conjugate it is the matlab's elementwise
> > > > > > conjugation op .'
> > > > > > >> #     but transpose is the reversing all dims just like
> > > > > > matlab's permute()
> > > > > > >> #     with static dimorder.
> > > > > > >>
> > > > > > >> and so on. Maybe we can try to identify all the use
> > > > > > cases and the quirks before we can make design the
> > > > > > solution. Because these are a bit more involved and I don't
> > > > > > even know if this is exhaustive.
> > > > > > >>
> > > > > > >>
> > > > > > >> On Mon, Jun 24, 2019 at 8:21 PM Marten van Kerkwijk <
> > > > > > m.h.vankerkwijk at gmail.com> wrote:
> > > > > > >>>
> > > > > > >>> Hi Stephan,
> > > > > > >>>
> > > > > > >>> Yes, the complex conjugate dtype would make things a
> > > > > > lot faster, but I don't quite see why we would wait for
> > > > > > that with introducing the `.H` property.
> > > > > > >>>
> > > > > > >>> I do agree that `.H` is the correct name, giving most
> > > > > > immediate clarity (i.e., people who know what conjugate
> > > > > > transpose is, will recognize it, while likely having to
> > > > > > look up `.CT`, while people who do not know will have to
> > > > > > look up regardless). But at the same time agree that the
> > > > > > docstring and other documentation should start with
> > > > > > "Conjugate tranpose" - good to try to avoid using names of
> > > > > > people where you have to be in the "in crowd" to know what
> > > > > > it means.
> > > > > > >>>
> > > > > > >>> The above said, if we were going with the initial
> > > > > > suggestion of `.MT` for matrix transpose, then I'd prefer
> > > > > > `.CT` over `.HT` as its conjugate version.
> > > > > > >>>
> > > > > > >>> But it seems there is little interest in that
> > > > > > suggestion, although sadly a clear path forward has not yet
> > > > > > emerged either.
> > > > > > >>>
> > > > > > >>> All the best,
> > > > > > >>>
> > > > > > >>> Marten
> > > > > > >>>
> > > > > > >>> _______________________________________________
> > > > > > >>> NumPy-Discussion mailing list
> > > > > > >>> NumPy-Discussion at python.org
> > > > > > >>> 
> > > > > > https://mail.python.org/mailman/listinfo/numpy-discussion
> > > > > > >>
> > > > > > >> _______________________________________________
> > > > > > >> NumPy-Discussion mailing list
> > > > > > >> NumPy-Discussion at python.org
> > > > > > >> 
> > > > > > https://mail.python.org/mailman/listinfo/numpy-discussion
> > > > > > >
> > > > > > > _______________________________________________
> > > > > > > NumPy-Discussion mailing list
> > > > > > > NumPy-Discussion at python.org
> > > > > > > https://mail.python.org/mailman/listinfo/numpy-discussion
> > > > > > _______________________________________________
> > > > > > NumPy-Discussion mailing list
> > > > > > NumPy-Discussion at python.org
> > > > > > https://mail.python.org/mailman/listinfo/numpy-discussion
> > > > > 
> > > > > _______________________________________________
> > > > > NumPy-Discussion mailing list
> > > > > NumPy-Discussion at python.org
> > > > > https://mail.python.org/mailman/listinfo/numpy-discussion
> > > > 
> > > > _______________________________________________
> > > > NumPy-Discussion mailing list
> > > > NumPy-Discussion at python.org
> > > > https://mail.python.org/mailman/listinfo/numpy-discussion
> > > 
> > > _______________________________________________
> > > NumPy-Discussion mailing list
> > > NumPy-Discussion at python.org
> > > https://mail.python.org/mailman/listinfo/numpy-discussion
> > 
> > _______________________________________________
> > NumPy-Discussion mailing list
> > NumPy-Discussion at python.org
> > https://mail.python.org/mailman/listinfo/numpy-discussion
> 
> _______________________________________________
> NumPy-Discussion mailing list
> NumPy-Discussion at python.org
> https://mail.python.org/mailman/listinfo/numpy-discussion
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 833 bytes
Desc: This is a digitally signed message part
URL: <http://mail.python.org/pipermail/numpy-discussion/attachments/20190625/1c6f240b/attachment.sig>


More information about the NumPy-Discussion mailing list