Published on (
 See this if you're having trouble printing code examples

Numerically Python

Numerical Python Basics


Installing Numerical Python

To use Numerical Python, you'll need to install it first. For the details, see our handy guide with instructions and download locations here.

On its own, Python is a potent tool for mathematics. When extended with the addition of two modules, Numerical Python and the DISLIN data visualization tool, Python becomes a powerhouse for numeric computing and problem solving. Numerical Python (NumPy) extends the Python language to handle matrices and supports the associated mathematics of linear algebra. Like Python, NumPy is a collaborative effort. The principal code writer was Jim Hugunin, a student at MIT. Paul Dubois at Lawrence Livermore National Labs and a few other major supporters (Konrad Hinsen and Travis Oliphant) eventually took on the project.

While NumPy and Python make a good combination, the ability of Python to serve the scientific community is not complete without a data visualization package. An excellent choice for data visualization is the DISLIN package freely provided to the Python community by Helmut Michels of the Max-Planck Institute. DISLIN is an extensive cross platform (Win32/Linux/Unix) library that can be accessed in many languages, including Python. With its support for 2D and 3D plotting and basic drawing commands, you can create informative and eye-catching graphics.

Over the next five months I will show you how to use both NumPy and DISLIN in real applications, starting this week with a review of the useful and interesting world of matrices and linear algebra. You may feel like you are having a flashback to high-school math, but stick with me. It gets interesting.

Introduction to Matrices and Matrix Mathematics

A matrix is a homogenous collection of numbers with a particular shape, like a table of numbers of the same type. The most common matrices are one or two-dimensional. One-dimensional matrices are also called vectors. A, b, and C are examples of matrices; a and b could also be called vectors.

3 matrix examples

Although a and b both contain the same elements, they are different in shape. The shape of a matrix is described by the number of rows and columns. The a matrix can be described as either a column vector or a 3-by-1 matrix, b is a row-vector or a 1-by-3 matrix. The C matrix is and example of a 3-by-3 matrix.

Addition and Subtraction

You add and subtract matrices, as you might expect, element by element - with only a slight twist. The shape of the matrices must be the same. Thus the following are valid operations,

adding 2 2-by-1 matrices and 2 1-by-2 matrices.


adding a 2-by-1 matrix to a 1-by-2 matrix

is not.

Matrix Multiplication

Matrix multiplication is a more complicated operation. For addition the matrices have to be the same size, but in multiplication only the inner dimensions have to be the same: the columns of the first matrix must be the same as the rows of the second matrix. The resulting matrix will be the size of the remaining outer dimensions. As an example, multiplication of a 1-by-3 matrix by a 3-by-1 matrix results in a 1-by-1 matrix (3 being the 'inner' dimension). If a 5-by-2 matrix is multiplied by a 2-by-5 matrix, a 5-by-5 matrix results.

The Formula

The governing formula is:

The forumla using summation.

This formula describes how the rows of matrix a and the columns of matrix b can be multiplied to generate matrix c. The indices in c(i,j) are used to specify the element located at the ith row and jth column of the new c matrix. (The same concept holds for the a and b matrices.) The Greek letter Sigma stands for summation. Think of it as a kind of for loop from k=1 to n where n is the size of the inner dimension. Add the resulting value of each trip through the loop together.

The following shows the difference between matrices with the same values but different shapes. The first example is a 2-by-1 matrix multiplied by a 1-by-2 matrix resulting in a 2-by-2 matrix. The second example is a 1-by-2 matrix multiplied by a 2-by-1 matrix resulting in a 1-by-1 matrix (also known as a scalar).

the outer dimensions determine the shape of the product

What about division?

Matrix division is undefined; the concept is replaced by the matrix inverse. The inverse of a matrix A is defined by the following equation:

a matrix multiplied by its inverse creates an identity matrix

When a matrix and its inverse are multiplied together, the result is the identity matrix or I. The identity matrix is a square matrix where all elements are 0 except along the main diagonal (going from upper left to lower right). A 3-by-3 identity matrix is shown

an identity matrix

While the matrix inverse is a bit different from traditional division, the concept follows directly from scalar mathematics where:

a number multiplied by its inverse equals 1

There are couple of limitations: the matrix inverse is only defined for square matrices (same number of rows as columns), and it may not exist for certain sets of elements. This is similar to how dividing a scalar by zero is undefined. You just can't work out an inverse for every set of numbers. Where the inverse does exist, it is very useful for solving difficult equations, as we will see later in this tutorial.

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, matrixmultiply() and inverse().

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

>>> c.shape
(2, 2)

Note that 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
 >>> 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 a with 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.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 Multiplication

Addition 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
>>> ma*mb
array([[1, 2],
       [2, 4]])
>>> mb*ma
array([[1, 2],
       [2, 4]])
>>> matrixmultiply(ma,mb)
array([  [5]])
>>> 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_inv by a (which should give the identity matrix).

>>> matrixmultiply(a_inv,a)
array([[ 1.00000000e+000,  1.11022302e-016],
       [ 0.00000000e+000,  1.00000000e+000]])

The End Game





The same equations in a table


creating three matrices


Giving the matrices symbolic letters

Using algebra to isolate our variables





>>> Ainv = inverse(A)
>>> z=matrixmultiply(Ainv,b)
>>> z
array([[ 1.],
       [ 2.]])


>>> matrixmultiply(A,z)
array([[ 11.],
       [  9.]])




More to Come


A pretty 3D graph generated by DISLIN

Further Reading




Discuss this article in the O'Reilly Network Python Forum.

Return to the Python DevCenter.


Copyright © 2009 O'Reilly Media, Inc.