[PYTHON MATRIX-SIG] Pseudo Indices

James Hugunin jjh@Goldilocks.LCS.MIT.EDU
Tue, 30 Jan 96 12:42:49 EST

Well, here's a fairly long and slightly confusing response, but what
do you expect from a first draft?

The idea of pseudo indices comes from the language Yorick created by
Dave Munro at LLNL, not from APL/J.

Everybody expects this to work:
a = array([1,2,3])

a+2 -> array([3,4,5])

2 is 0-dimensional array with shape [], and a has shape [3].  The rule
says that any non-existent dimension is "broadcast" to match a higher
dimensional array as required.

The idea is to extend this notion of broadcasting to any dimension of
length one.  So the following will also work:

a+array([2]) -> array([3,4,5])

array([2]) has shape [1], and a has shape [3].  The [1] is broadcast
to match the [3].

The classic example of where this is useful is in taking an
outer product.

b = array([10, 20])

a * b.reshape(2, 1) -> array([[11, 12, 13], [21, 22, 23]])

a has shape [3], and b.reshape(2,1) has shape [2, 1].  The result of a binary
operator applied to them has shape [2,3].

In order to make such code easier to read, Yorick introduces the
notion of a pseudo index that can be added to any multidimensional index
and means, add a new dimension here.

ie. b[2, PseudoIndex] <--> b.reshape(2, 1)

"All" is not in fact related to Yorick pseudo indices at all, but is
related to Slices.

c = array([[1,2,3], [11,12,13]])

I'd really like to be able to say c[:, 3] -> array([3,13]).  Python
syntax doesn't currently allow this, so until somebody convinces Guido
to make the change, the following objects are used instead.

c[:, 1:2] --> c[Slice(), Slice(1,2)]

All = Slice()

One more piece is needed to handle multidimensional indexing properly.
Let's say that I want to extract the third element from the last
dimension of an array.

In Yorick that would look like a[.., 3].  Since Python doesn't yet
have this rubber index, I use the following:

a[RubberIndex, 3].

So, the following special symbols are needed to properly treat
multidimensional indexing:


My current feeling on the best way to do this is to keep Slice's as
they are (until somebody lobbys Guido for a better system).

Define string constants

NewAxis = "NewAxis" 
Ellipses = "Ellipses"

NewAxis is equivalent to the current "None" and indicates a

Ellipses is equivalent to the current "RubberIndex" and indicates
standard ellipses as in, fill in what should naturally go here.



MATRIX-SIG  - SIG on Matrix Math for Python

send messages to: matrix-sig@python.org
administrivia to: matrix-sig-request@python.org