Lisp-Stat has extensive built-in linear algebra capabilities, including matrix inner and outer products, LU decomposition, QR decomposition, Gaussian elimination, Singular Value Decomposition, and more. We will use these tools later when we introduce linear algebra systematically. For now, let us look at a few examples of how matrices are defined and manipulated.
We can make arrays of arbitrary dimensions with the
> (make-array (list 2 3)) #2A((NIL NIL NIL) (NIL NIL NIL)) > (print-matrix *) #2a( (NIL NIL NIL) (NIL NIL NIL) )The
#2Abit says that this is a rank 2 tensor. The
print-matrixfunction is useful for displaying matrices in a human-readable form. Unless we tell the interpreter otherwise, it doesn't initialize the matrix, so all the elements are
nil. We can fix this with the
> (make-array (list 2 3) :initial-element 1) #2A((1 1 1) (1 1 1))We could also use the
#2Aform to build an array directly as:
> '#2a((1 1 1) (1 1 1)) #2A((1 1 1) (1 1 1))In this case the single quote is needed since we don't want to evaluate the array.
Here is a function that returns a square Gaussian pseudo-random matrix of arbitrary size. In it we use several useful matrix tools, and we show how to loop over the elements of a matrix.
> (defun gaussian-matrix (l) (let* ((mat (make-array (list l l))) (row (array-dimension mat 0)) (col (array-dimension mat 1)) ) (dotimes (i row) (dotimes (j col) (setf (aref mat i j) (elt (normal-rand 1) 0)) ) ) (copy-array mat) ) ) GAUSSIAN-MATRIXAnd here is an example of its use:
> (print-matrix (gaussian-matrix 3)) #2a( ( 0.479400 0.871488 1.26546 ) ( 0.190493 -2.05859 1.25512 ) ( -8.075542E-2 -1.53208 -2.17642 ) )
First, as we saw in the autocorrelation example, we can
define local variables with
let. In this case
let*, which allows us to use, sequentially,
the results of previous local definitions. In this example,
we first define
mat, and then we can use
itself to define new local variables such as
aref is one way of accessing a given element of a
matrix. So the line
(setf (aref mat i j) (elt (normal-rand 1) 0))say to set the
i jelement of
matto a normal random number. But since
(normal-rand 1)returns a length 1 list, we somehow need to ``flatten'' this list so that we only have a number. There are several ways to do this, but talking the first (i.e., 0-th) element with
eltdoes the trick.
An even simpler, and vectorized, approach is
(defun gaussian-matrix (l) (make-array (list l l) :initial-contents (normal-rand (* l l))) )