[PYTHON MATRIX-SIG] Functions and names

Chris Chase S1A chris.chase@jhuapl.edu
Tue, 20 Feb 1996 17:33:19 -0500


>>>>> "Konrad" == Konrad HINSEN <hinsenk@ere.umontreal.ca> writes:

Konrad> Comments of any kind are of course welcome.

I like Konrad's other suggestions along with those already suggested
by Paul.  Paul seems to have a well thought-out naming convention.

I would like to make some comments and additions below:

Konrad> Constructors
Konrad> ============

Konrad> 1) Construct an array from an arbitrary sequence object or a function:
Konrad> +  array(sequenceOrFunction, shape=None, type=None)
Konrad>      Returns an array of the given shape and type using the
Konrad>      elements from the flattened sequence. 

I must admit that for constructing matrices the nested list argument
seemed natural.  This version does not allow it.  Otherwise, I like
its additional functionality.

Konrad> Structural array operations
Konrad> ===========================

Konrad> 1) Selecting subarrays

Support for mapped indexing (like the Tela language) would be useful.
Perhaps it should be an attribute so as to allow assignment:

print a.mapped[c1,c2,c3]
a.mapped[c1,c2,c3] = b

c1,c2,c3 index vectors that must have the same shape when converted to
an array.  Elements of 'a' are chosen by the indexes c1[i],c2[i],c3[i]
and the result has the same shape as the shape of the index vectors.
Think of the index vectors as being coordinates for some space (I use
this style of indexing for paths in two-dimensional image maps or
three-dimensional volume data).  For assignment 'b' must have the same
shape.

Konrad> 1.2) Selecting arbitrary elements specified by an array of indices i:
Konrad> +    take(a, i, axis=0)
Konrad>        Conditions: i must be of an integer array type,
Konrad>        minimum.reduce(ravel(i)) >= 0,
Konrad>        maximum.reduce(ravel(i)) < a.shape[axis]

As Paul suggested, perhaps gather() is a better name than take()
(gather is a name used in vector libraries).  But it really does not
matter very much to me.

There needs to be a dual capability for assigning the items specified by
an array of indices (a completely general form of product indexing).
Perhaps something like:

a.index[1,i,j] = b

with i and j index sequences applied to the second and third
dimensions.  Here, the 'index' attribute permits index vectors that
are scalars, sequences or slices.  There is no equivalent to take()
since all dimensions must treated simultaneously.  Perhaps a better
name would be 'subarray'.  In fact, such an 'subarray' attribute could
also be used for selection, only it would not return a reference but a
copy and always return the same rank as 'a' (i.e. does reduce the rank
for scalar indexes).  If it was only being used for assignment it
could be called "scatter" (the dual of gather).

An insertion method for inserting a subarray into a larger array would
also be useful.  Something like:

a.insert(b, c1, c2, c3)

or

a.insert[c1,c2,c3] = b

Perhaps someone can come up with a better idea.  The concept is: 
'b' is inserted into 'a' starting at index c1,c2,c3.  The operation
overwrites elements of 'a'.  It is more convenient then using slice
notation which would require one to compute the upper limit on the
slices.  It could have different behaviors by using a keyword argument
for when 'b' does not fit within the dimensions of 'a' (e.g. truncate,
wrap around or signal error.)

Konrad> 2) Rearranging array elements

Konrad> 2.1.2) Reshaping to a rank-1 array:
Konrad>        ravel(a)
Konrad>        equivalent to reshape(a,(multiply.reduce(a.shape),))

flatten() could also be a possible name.  Why should this be a
function rather than a method or attribute?  For example, 
a.flat == ravel(a)

but a.flat[s] would allow subscription/assignment of 'a' in flattened
form using a scalar, sequence object, or a slice.  Of course a
combination of take() and ravel() and subscripting can accomplish
this.  However, flat() and subarray() as methods could completely
replace ravel() and take() functions with the ability to simply support
flattened or product indexing subscription or assignment.


Konrad> 2.1.3) Combining a group of axes into one axis (see comment 2):
Konrad> +      a[i1, i2, ......, i3, i4]  (see comment 3)
Konrad>          The double ellipsis works similar to the single one, but
Konrad>          contracts all the axes covered into a single axis.

I do not like this.  Perhaps an attribute 'collapse' would work?  E.g.

a.collapse[i1, i2, ..., i3, i4]

collapse would interpret '...' to mean contract the axes.  Otherwise
it behaves exactly like normal subscripting.  This is not necessarily
a good idea either.

Konrad> 2.1.4) Adding an axis of length 1:
Konrad>        a[..., NewAxis, ...]

Of course the "..." are notational and have nothing to do with ellipses
indexes.  Otherwise, this does not make sense.

Konrad> 2.2) Transposition:
Konrad> +    transpose(a, axes)
Konrad>        axes is a non-nested sequence of non-negative integers
Konrad>        with maximum.reduce(axes) < len(a.shape)

Yorick has a nice general form of the transpose() function.  It allows
a variable length argument list where the arguments are cyclic
permutations of the indexes.  It is actually a little more general.
Rather than explain here,  a description is available in the Yorick
online docs at:

ftp://icf.llnl.gov/pub/Yorick/html/yorick_49.html#SEC49


Chris

=================
MATRIX-SIG  - SIG on Matrix Math for Python

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