324 lines
12 KiB
Racket
324 lines
12 KiB
Racket
#lang scribble/manual
|
|
@(require ; "../math-scribble/math-scribble.rkt"
|
|
(for-label "../matrix.rkt"
|
|
racket
|
|
racket/contract
|
|
racket/dict
|
|
racket/base)
|
|
"../matrix.rkt"
|
|
racket/string
|
|
racket/list
|
|
scribble/eval
|
|
"pr-math.rkt")
|
|
|
|
@setup-math
|
|
|
|
|
|
@;@$$[(tex-matrix (matrix 2 3 1 2 3 4 5 6))]
|
|
@;@$$[(build-tex-matrix 2 3 (λ (i j) (format "a_{~a~a}" i j)))]
|
|
|
|
@(define (make-matrix-eval print-matrix-as-snip)
|
|
(let ([eval (make-base-eval)])
|
|
(eval `(begin
|
|
(require "../matrix.rkt"
|
|
slideshow/pict
|
|
"pr-math.rkt")
|
|
(begin
|
|
(require racket/list)
|
|
(define (subscript a i [j #f])
|
|
(if j
|
|
(hb-append (scale (text a) 2)
|
|
(scale (text (format "~a~a" i j)) 0.75))
|
|
(hb-append (scale (text a) 2)
|
|
(scale (text (format "~a" i)) 0.75))))
|
|
(define (a i j)
|
|
(subscript "a" i j))
|
|
(define (b i j)
|
|
(subscript "a" i j))
|
|
(define (add-brackets p)
|
|
(define bw 5)
|
|
(define bh 1)
|
|
(let ([h (pict-height p)])
|
|
(hc-append
|
|
; left bracket
|
|
(filled-rectangle 1 h)
|
|
(vl-append (filled-rectangle bw bh)
|
|
(blank bw (- h (* 2 bh)))
|
|
(filled-rectangle bw bh))
|
|
; contents
|
|
p
|
|
; right bracket
|
|
(vl-append (filled-rectangle bw bh)
|
|
(blank bw (- h (* 2 bh)))
|
|
(filled-rectangle bw bh))
|
|
(filled-rectangle 1 h))))
|
|
(define (build-array-pict m n f)
|
|
(apply hc-append
|
|
(add-between
|
|
(for/list ([j (in-range n)])
|
|
(apply vr-append
|
|
|
|
(for/list ([i (in-range m)])
|
|
(let ([f_ij (f i j)])
|
|
(cond
|
|
[(number? f_ij)
|
|
(text (number->string f_ij))]
|
|
[(pict? f_ij) f_ij]
|
|
[(string? f_ij)
|
|
(text f_ij)]
|
|
[else (error)])))))
|
|
(blank 5))))
|
|
(define (build-matrix-pict m n f)
|
|
(add-brackets
|
|
(build-array-pict m n f)))
|
|
(define (matrix->pict M)
|
|
(define-values (m n) (matrix-size M))
|
|
(add-brackets
|
|
(build-array-pict
|
|
m n (λ (i j) (matrix-ref M i j)))))
|
|
,(if print-matrix-as-snip
|
|
'(current-print
|
|
(let ([print (current-print)])
|
|
(define (maybe->matrix v)
|
|
(if (matrix? v) (matrix->pict v) v))
|
|
(λ (v) (print
|
|
(cond
|
|
[(matrix? v) (matrix->pict v)]
|
|
[(list? v) (map maybe->matrix v)]
|
|
[else v])))))
|
|
'(begin))
|
|
)))
|
|
eval))
|
|
|
|
@;@racketinput[(matrix 2 3 1 2 3 4 5 6)]
|
|
@;@$[(tex-matrix (matrix 2 3 1 2 3 4 5 6))]
|
|
|
|
@racketblock[> (matrix 2 3 1 2 3 4 5 6)
|
|
#,(math-in (tex-matrix (matrix 2 3 1 2 3 4 5 6)))]
|
|
|
|
|
|
|
|
@(define matrix-eval (make-matrix-eval #f))
|
|
@(define matrix-eval/snip (make-matrix-eval #t))
|
|
|
|
@;defmodulelang[@racketmodname[matrix] #:module-paths ("../matrix.rkt")]
|
|
@defmodule[(file "../matrix.rkt")]
|
|
|
|
@(define the-eval (make-base-eval))
|
|
@(the-eval '(require "../matrix.rkt"))
|
|
|
|
@title[#:tag "matrix"]{Matrix Library}
|
|
|
|
A @italic{matrix} is a rectangular array of numbers. A typical example:
|
|
@centered{
|
|
@interaction-eval-show[#:eval matrix-eval
|
|
(scale
|
|
(matrix->pict
|
|
(matrix 3 2 1 2 3 4 5 6)) 2)]}
|
|
The horizontal lines are called @italic{rows} and the vertical lines
|
|
are called @italic{columns}. The matrix above has @italic{m}=3 rows
|
|
and @italic{n}=2 columns and is an example of an @italic{3x2}-matrix.
|
|
In general a matrix with @italic{m} rows and @italic{n} columns is
|
|
called an @italic{mxn}-matrix.
|
|
|
|
Matrices with one row (1xn) only are called @italic{row vectors} and
|
|
matrices with one column (mx1) only are called @italic{column vectors}.
|
|
|
|
The @italic{entries} or @italic{elements} of a matrix is referred to by their
|
|
row and column number. In this library the row and columns are counted from 0.
|
|
@centered{
|
|
@interaction-eval-show[#:eval matrix-eval
|
|
(build-matrix-pict 3 2 (λ (i j) (a i j)))]}
|
|
Note: In standard mathematical notation row and column numbers are counted from 1.
|
|
|
|
@;-----------------------------------------------------------------------
|
|
|
|
@section{A basic example}
|
|
|
|
|
|
First require the libary:
|
|
@racketinput[(require "matrix.rkt")]
|
|
Create a 2x3 matrix with entries 1, 2, 3, 4, 5, and, 6.
|
|
@interaction[#:eval matrix-eval
|
|
(matrix 2 3 1 2 3 4 5 6)]
|
|
Display the matrix as a picture:
|
|
@interaction[#:eval matrix-eval
|
|
(matrix->pict
|
|
(matrix 2 3 1 2 3 4 5 6))]
|
|
Let's change the print handler, so we don't need to call @racket{matrix->pict}
|
|
ourselves.
|
|
@interaction[#:eval matrix-eval
|
|
(current-print
|
|
(let ([print (current-print)])
|
|
(λ (v) (print (if (matrix? v) (matrix->pict v) v)))))
|
|
(matrix 2 2 1 2 3 4)]
|
|
The basic operations are addition, subtraction and multiplication.
|
|
@interaction[#:eval matrix-eval/snip
|
|
(define A (matrix 2 2 1 2 3 4))
|
|
(define B (matrix 2 2 1 -2 3 -4))
|
|
A
|
|
B
|
|
(matrix-add A B)
|
|
(matrix-sub A B)
|
|
(matrix-mul A B)]
|
|
Scale a matrix by a factor 2.
|
|
@interaction[#:eval matrix-eval/snip
|
|
(matrix-scale 2 (matrix 2 2 1 2 3 4))]
|
|
Multiply a matrix on a column-vector.
|
|
@interaction[#:eval matrix-eval/snip
|
|
(matrix-mul (matrix 2 2 1 2 3 4)
|
|
(column-vector 1 0))]
|
|
|
|
@;---------------------------------------------------------------------
|
|
|
|
@section[#:tag "matrix constructors"]{Constructors}
|
|
|
|
@defproc[(matrix [m index/c] [n index/c] [x number?] ...)
|
|
matrix
|
|
]{
|
|
Construct a mxn-matrix with elements @racket[x ...].
|
|
@interaction[#:eval matrix-eval/snip
|
|
(matrix 2 2 1 2 3 4)]}
|
|
|
|
@defproc[(row-vector [x number?] ...)
|
|
matrix]{
|
|
Construct a row vector (a 1xn-matrix) with elements @racket[x ...].
|
|
@interaction[#:eval matrix-eval/snip
|
|
(row-vector 1 2 3)]}
|
|
|
|
@defproc[(column-vector [x number?] ...)
|
|
matrix]{
|
|
Construct a column vector (a mx1-matrix) with elements @racket[x ...].
|
|
@interaction[#:eval matrix-eval/snip
|
|
(column-vector 1 2 3)]}
|
|
|
|
@defproc[(make-matrix [m size/c] [n size/c] [x number?])
|
|
matrix]{
|
|
Construct a mxn-matrix where all entries are @racket[x].
|
|
@interaction[#:eval matrix-eval/snip
|
|
(make-matrix 2 3 4)]
|
|
}
|
|
|
|
@defproc[(build-matrix [m size/c] [n size/c] [f (index/c index/c -> number?)])
|
|
matrix]{
|
|
Construct a mxn-matrix where element (i,j) is @racket[(f i j)].
|
|
@interaction[#:eval matrix-eval/snip
|
|
(build-matrix 3 4 +)]
|
|
}
|
|
|
|
@defproc[(submatrix [M matrix?] [i index/c] [j index/c] [m size/c] [n size/c])
|
|
matrix]{
|
|
Construct a mxn-matrix with elements from row i to i+m and from column j to j+m.
|
|
@interaction[#:eval matrix-eval/snip
|
|
(define A (build-matrix 5 5 (λ (i j) (+ (* i 5) j))))
|
|
A
|
|
(submatrix A 2 3 1 2)]
|
|
}
|
|
|
|
@defproc[(matrix-augment [M matrix?] [N matrix?])
|
|
matrix]{
|
|
Augment the matrices M and N by "appending" their columns.
|
|
The number of rows in M and N must be the same.
|
|
@interaction[#:eval matrix-eval/snip
|
|
(matrix-augment (matrix 2 2 1 2
|
|
3 4)
|
|
(matrix 2 3 5 6 7
|
|
8 9 10))]
|
|
}
|
|
|
|
@defproc[(matrix-augment* [Ms (listof matrix?)])
|
|
matrix]{
|
|
Augment the matrices in the list Ms "appending" their columns.
|
|
The number of rows in alle the matrices must be the same.
|
|
@interaction[#:eval matrix-eval/snip
|
|
(matrix-augment* (list (matrix 2 1 1 2)
|
|
(matrix 2 1 3 4)
|
|
(matrix 2 1 5 6)))]
|
|
}
|
|
|
|
@defproc[(matrix-copy [M matrix?])
|
|
matrix]{
|
|
Copy the matrix M.
|
|
@interaction[#:eval matrix-eval/snip
|
|
(matrix-copy (matrix 1 2 3 4))]
|
|
}
|
|
|
|
@defproc[(matrix-row [M matrix?] [i index/c])
|
|
matrix]{
|
|
Construct a row vector from the i'th column of M.
|
|
@interaction[#:eval matrix-eval/snip
|
|
(define M (matrix 2 4 1 2 3 4 5 6 7 8))
|
|
M
|
|
(matrix-row M 1)]
|
|
}
|
|
|
|
@defproc[(matrix-column [M matrix?] [j index/c])
|
|
matrix]{
|
|
Construct a column vector from the j'th column of M.
|
|
@interaction[#:eval matrix-eval/snip
|
|
(define M (matrix 2 4 1 2 3 4 5 6 7 8))
|
|
M
|
|
(matrix-column M 2)]
|
|
}
|
|
|
|
@defproc*[([(matrix-identity [m size/c]) matrix]
|
|
[(matrix-identity [m size/c] [n size/c]) matrix])]{
|
|
Return m x n matrix with ones on the diagonal and zeros elsewhere.
|
|
If only one argument is given, a square matrix is produced.
|
|
@interaction[#:eval matrix-eval/snip
|
|
(matrix-identity 3)
|
|
(matrix-identity 3 2)]
|
|
}
|
|
|
|
@defproc[(matrix-diagonal [xs (listof number?)])
|
|
matrix]{
|
|
Construct a square matrix with elements from xs on the diagonal and 0 elsewhere.
|
|
@interaction[#:eval matrix-eval/snip
|
|
(matrix-diagonal '(1 2 3))]
|
|
}
|
|
|
|
|
|
@section[#:tag "matrix operations"]{Operations}
|
|
|
|
@defproc[(matrix-scale [s number?] [M matrix?])
|
|
matrix]{
|
|
Multiply each element of M with s.
|
|
@interaction[#:eval matrix-eval/snip
|
|
(matrix-scale 3 (matrix 2 2 1 2 3 4))]
|
|
}
|
|
|
|
@defproc[(matrix-add [M matrix?] [N matrix?])
|
|
matrix]{
|
|
Return the sum of M and N.
|
|
@interaction[#:eval matrix-eval/snip
|
|
(define M (matrix 2 2 1 2 3 4))
|
|
(define N (matrix 2 2 1 -2 3 -4))
|
|
(list M N (matrix-add M N))]
|
|
}
|
|
|
|
@defproc[(matrix-mul [M matrix?] [N matrix?])
|
|
matrix]{
|
|
Return the product of M and N.
|
|
The number of columns in M must be equal to the number of rows in N.
|
|
@interaction[#:eval matrix-eval/snip
|
|
(define M (matrix 2 2 1 2 3 4))
|
|
(define N (matrix 2 2 2 0 0 1))
|
|
(list M N (matrix-mul M N))]
|
|
}
|
|
|
|
@defproc[(matrix-linear [a number?] [M matrix?] [b number?] [N matrix?])
|
|
matrix]{
|
|
Return the linear combination of M and N @math-in{a*M + b*N}.
|
|
@interaction[#:eval matrix-eval/snip
|
|
(define M (matrix 2 2 1 1 1 0))
|
|
(define N (matrix 2 2 0 0 1 1))
|
|
(list M N (matrix-linear -1 M 2 N))]
|
|
}
|
|
|
|
|
|
@section[#:tag "matrix unary operators"]{Unary Operators}
|
|
|
|
@section[#:tag "matrix comprehensions"]{Comprehensions}
|
|
@section{Binary Operators}
|
|
|
|
|