NumPy and Python
Enough math review -- let's see how it looks in Numerical Python. The NumPy distribution brings to Python the concept of the multi-array. This is the ability to store sets of homogenous numbers in shaped containers. Sounds like a matrix, right? The multi-array (or array) can hold numeric values of any type (integers, floating point numbers, and complex values). The Numeric package also provides extensions to the mathematical functions to cover array arguments as well as scalar. In addition several other modules are provided (LinearAlgebra, FFT, RanLib and Matrix to name a few). We will use the LinearAlgebra module later to create an inverse.
NumPy provides for operations that extend beyond those defined in traditional matrix mathematics like we just reviewed. Although these operations are nonstandard, they make for more efficient computation in certain circumstances.
It is important for you to know that NumPy defines the operation of the binary operators '*' for multiplication and '/' for division to operate element-wise as in addition and subtraction (shape still matters, however). To perform traditional matrix multiplication or to create an inverse you will need to use explicit functions,
Creation of Matrices / Arrays
To use the features of NumPy you must import it:
>>> from Numeric import *.
Once the module has been imported, you generate an array with the
array() function. The
array() function takes two arguments, a tuple or list of values and an optional type code, e.g., Float or Int. The list may be nested to create a multi-dimensional array. The
array() function will create an array with the values and type specified. If no type is specified, the type of the array will be dependent on the type of the elements.
>>> a=array((1,2)) >>> print a [1 2]
Creates an integer array since the values in the tuple were integers.
>>> b=array((1,2),Float) >>> print b [ 1. 2.]
creates a floating-point array using integer arguments. The floating-point type overrides the integer arguments.
>>> c=array(((1,2),(3,4))) >>> print c [[1 2] [3 4]]
creates a multi-dimensional array using a multi-dimensional tuple.
Shape and Reshape
The shape attribute of an array is expressed as a tuple. To see the shape simply type
>>> a=array((1,2)) >>> a.shape (2,) >>> c=array(((1,2),(3,4))) >>> c.shape (2, 2)
a has only a single dimension (the shape tuple has only a single value) and that
c is multidimensional (two values in the shape tuple). By default, single dimensional arrays have only a length. The concept of rows and columns is not embodied in the structure of a single dimensional array. The shape of an array, however, can be altered via the
reshape() function. The reshape function takes two arguments: an array and a shape tuple.
>>> a=array((1,2)) >>> a.shape (2,) >>> print a [1 2] >>> ma=reshape(a,(1,2)) >>> ma.shape (1, 2) >>> print ma [ [1 2]] >>> mb=reshape(a,(2,1)) >>> mb.shape (2, 1) >>> print mb [ ]
The printout changes when you use reshape to give a single-dimensioned array a shape more like a traditional matrix. In the case of the 1-by-2 matrix
ma, the extra space shows the multidimensional nature of the matrix. Contrast the printing of
ma. See the difference between the original and the reshaped form? The elements are the same, but the shape is different.
Elements are taken row-wise from the source array when we reshape this 2-by-2 array:
>>> c=array(((1,2),(3,4))) >>> c.shape (2, 2) >>> print c [[1 2] [3 4]] >>> d=reshape(c,(1,4)) >>> d.shape (1, 4) >>> print d [ [1 2 3 4]]
Matrix MultiplicationAddition and subtraction work just like you would expect. Give them a try! But let's take a look at the trickier problem of multiplication. If you weren't paying attention to my earlier warning about multiplication and division, you might wonder what is happening in the next example. We create two arrays with different shapes. Using the default multiplication operation generates results that seem independent of the shape. Remember, in matrix multiplication shape is important. Only when we use the
matrixmultiply()do we get the results we expect.
>>> ma array([ [1, 2]]) >>> mb array([, ]) >>> ma*mb array([[1, 2], [2, 4]]) >>> mb*ma array([[1, 2], [2, 4]]) >>> matrixmultiply(ma,mb) array([ ]) >>> matrixmultiply(mb,ma) array([[1, 2], [2, 4]])
The multiplication operation is governed by actions called 'Pseudo Indices.' They really are useful. I will explain them in a later article. For now, stick with the
matrixmultiply() function to achieve the expected results.
The Matrix Inverse
To generate a matrix inverse, you simply use the
inverse() function found in the LinearAlgebra module supplied along with the basic NumPy. To gain access to the function, first perform an import.
>>> From LinearAlgebra import *
A simple example shows how to use the function
>>> a=array(((3,2),(2,4)),Float) >>> print a [[ 3. 2.] [ 2. 4.]] >>> a_inv = inverse(a) >>> print a_inv [[ 0.5 -0.25 ] [-0.25 0.375]]
To check the result, multiply
a (which should give the identity matrix).
>>> matrixmultiply(a_inv,a) array([[ 1.00000000e+000, 1.11022302e-016], [ 0.00000000e+000, 1.00000000e+000]])