[PYTHON MATRIX-SIG] Functions and names

Konrad HINSEN hinsenk@ere.umontreal.ca
Tue, 20 Feb 1996 15:12:08 -0500


I have made an attempt to put some order into the array functions.  I
have made a list of functions that should be available and proposed a
name for each function. Until now I have covered constructors
and structural functions; the rest will follow later, assuming
I am not hit by too many 16-ton weights before ;-)

Lines that describe new or modified operations are marked with a
'+'. Comments are at the end of the file.

As I have suggested before, it is useful to have an additional module
defining abbreviations and/or more meaningful names for often-used
combinations. These should not be part of the standard module to
reduce name space pollution and learning overhead, but they should
nevertheless be part of the standard distribution to ensure
uniformity. I'll include recommended abbreviations in the respective
sections.

Comments of any kind are of course welcome.


Constructors
============

1) Construct an array from an arbitrary sequence object or a function:
+  array(sequenceOrFunction, shape=None, type=None)
     Returns an array of the given shape and type using the
     elements from the flattened sequence. If not all
     elements of the sequence are used, the rest is discarded.
     If more elements are needed, the sequence is reused from
     the beginning.
     If a callable object is passed instead of a sequence,
     it is called for each element with its indices as
     parameters.

   Calling the current constructor oldArray(), the new one
   behaves like
     def array(sequenceOrFunction, shape=None, type=None):
       if isSequence(sequenceOrFunction):
         a = oldArray(sequence, type)
         if shape is not None:
	   a = copyAndReshape(a, shape)
         return a
       else:
         return fromFunction(map(shape), sequenceOrFunction)

   This constructor replaces the current constructors
   array(), copyAndReshape(), and fromFunction(), and
   makes special cases like zeros() so easy that they
   don't have to be standard functions any more.

2) Construct a rank-1 array of equally spaced points:
+  arrayRange(x1, x2=None, x3=None)

   Currently: function arange() does exactly the same.

Abbreviations:

  zeros(n1,n2,...) equals array(0,(n1,n2,...))
  ones(n1,n2,...) equals array(1,(n1,n2,...))
  unitMatrix(n) equals array([1]+n*[0], (n,n))
  arange equals arrayRange


Structural array operations
===========================

1) Selecting subarrays

1.1) Selecting on a "raster" along each coordinate:
     Done by indexing with integers and slices

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

     Currently: method a.take(i, axis=0), i can be of any type, but
     must have rank 1.

1.3) Selecting the diagonal, i.e. those values where the indices
     along two axes are equal (see comment 1):
+    diagonal(a, axis1=0, axis2=1)
       Conditions: axis1 < len(a.shape), axis2 < len(a.shape),
       a.shape[axis1] == a.shape[axis2]


2) Rearranging array elements

2.1) Changing the shape

2.1.1) General reshaping:
+      reshape(a,shape)
         shape can be of any non-nested sequence type
         Condition: multiply.reduce(shape) == multiply.reduce(a.shape)

       Currently: method a.reshape(shape), shape must be a tuple

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

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

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

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

     Currently: method a.transpose(axes) does the same, but
     there is a bug that sometimes gives wrong results if
     an axis is used more than once in the list. It also
     insists that len(axes) == len(a.shape), although there
     is no need for this restriction.


3) Replicating and combining array elements

3.1) Replicating elements along an axis:
+    repeat(a, n, axis=0)
       n is a non-nested integer sequence with len(n) == a.shape[axis]
       Each element in a is repeated as often as indicated by
       the corresponding element in n. The length of the result
       along the specified axis is add.reduce(n).

     Currently: function compress(n, a, axis=0) is a special case
     limited to boolean (0/1) elements in n.

3.2) Concatenation of arrays along an axis:
+    concatenate((a1,a2,a3,...), axis=0)
       Condition: all arrays must have the same shape for the
       remaining axes.

     Currently: method a.concat(a1,a2,a3,...) works only along
     first axis.

3.3) Concatenation of arrays along a new axis:
     Can be done by combining concatenate() and indexing with NewAxis.
     (see comment 4)

Abbreviation:
  reverse(a) = a[::-1]



Comments
========

1) APL uses a special case of transposition for selecting a
   diagonal, but this is very confusing.

2) In J this is done by using ravel() with reduced rank, but
   as long as we don't have functions with bounded ranks,
   we need a special function.

3) I tried to find a construction that does not require
   yet another syntax and this is the best I could think
   of. But I am not particularly attached to it, so feel
   free to think of something better.

4) APL does this with fractional indices, which is probably
   the weirdest feature in APL.

-------------------------------------------------------------------------------
Konrad Hinsen                     | E-Mail: hinsenk@ere.umontreal.ca
Departement de chimie             | Tel.: +1-514-343-6111 ext. 3953
Universite de Montreal            | Fax:  +1-514-343-7586
C.P. 6128, succ. Centre-Ville     | Deutsch/Esperanto/English/Nederlands/
Montreal (QC) H3C 3J7             | Francais (phase experimentale)
-------------------------------------------------------------------------------

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

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