====================================================================
Matrix examples
====================================================================

The Matrix domain provides arithmetic operations on matrices
and standard functions from linear algebra.
This domain is similar to the TwoDimensionalArray domain, except
that the entries for Matrix must belong to a  Ring.

====================================================================
Creating Matrices
====================================================================

There are many ways to create a matrix from a collection of values or
from existing matrices.

If the matrix has almost all items equal to the same value, use new to
create a matrix filled with that value and then reset the entries that
are different.

  m : Matrix(Integer) := new(3,3,0)
    +0  0  0+
    |       |
    |0  0  0|
    |       |
    +0  0  0+
                      Type: Matrix Integer

To change the entry in the second row, third column to 5, use setelt.

  setelt(m,2,3,5)
    5
                      Type: PositiveInteger

An alternative syntax is to use assignment.

  m(1,2) := 10
    10
                      Type: PositiveInteger

The matrix was destructively modified.

  m
    +0  10  0+
    |        |
    |0  0   5|
    |        |
    +0  0   0+
                      Type: Matrix Integer

If you already have the matrix entries as a list of lists, use matrix.

  matrix [ [1,2,3,4],[0,9,8,7] ]
    +1  2  3  4+
    |          |
    +0  9  8  7+
                      Type: Matrix Integer

If the matrix is diagonal, use diagonalMatrix.

  dm := diagonalMatrix [1,x**2,x**3,x**4,x**5]
        +1  0   0   0   0 +
        |                 |
        |    2            |
        |0  x   0   0   0 |
        |                 |
        |        3        |
        |0  0   x   0   0 |
        |                 |
        |            4    |
        |0  0   0   x   0 |
        |                 |
        |                5|
        +0  0   0   0   x +
                     Type: Matrix Polynomial Integer

Use setRow and setColumn to change a row or column of a matrix.

  setRow!(dm,5,vector [1,1,1,1,1])
        +1  0   0   0   0+
        |                |
        |    2           |
        |0  x   0   0   0|
        |                |
        |        3       |
        |0  0   x   0   0|
        |                |
        |            4   |
        |0  0   0   x   0|
        |                |
        +1  1   1   1   1+
                    Type: Matrix Polynomial Integer

  setColumn!(dm,2,vector [y,y,y,y,y])
        +1  y  0   0   0+
        |               |
        |0  y  0   0   0|
        |               |
        |       3       |
        |0  y  x   0   0|
        |               |
        |           4   |
        |0  y  0   x   0|
        |               |
        +1  y  1   1   1+
                    Type: Matrix Polynomial Integer

Use copy to make a copy of a matrix.

  cdm := copy(dm)
        +1  y  0   0   0+
        |               |
        |0  y  0   0   0|
        |               |
        |       3       |
        |0  y  x   0   0|
        |               |
        |           4   |
        |0  y  0   x   0|
        |               |
        +1  y  1   1   1+
                    Type: Matrix Polynomial Integer

This is useful if you intend to modify a matrix destructively but
want a copy of the original.

  setelt(dm,4,1,1-x**7)
        7
     - x  + 1
                    Type: Polynomial Integer

  [dm,cdm]
          +   1      y  0   0   0+ +1  y  0   0   0+
          |                      | |               |
          |   0      y  0   0   0| |0  y  0   0   0|
          |                      | |               |
          |              3       | |       3       |
         [|   0      y  x   0   0|,|0  y  x   0   0|]
          |                      | |               |
          |   7              4   | |           4   |
          |- x  + 1  y  0   x   0| |0  y  0   x   0|
          |                      | |               |
          +   1      y  1   1   1+ +1  y  1   1   1+
                     Type: List Matrix Polynomial Integer

Use subMatrix to extract part of an existing matrix.  The syntax is 
subMatrix(m, firstrow, lastrow, firstcol, lastcol).

  subMatrix(dm,2,3,2,4)
         +y  0   0+
         |        |
         |    3   |
         +y  x   0+
                     Type: Matrix Polynomial Integer

To change a submatrix, use setsubMatrix.

  d := diagonalMatrix [1.2,-1.3,1.4,-1.5]
         +1.2   0.0   0.0   0.0 +
         |                      |
         |0.0  - 1.3  0.0   0.0 |
         |                      |
         |0.0   0.0   1.4   0.0 |
         |                      |
         +0.0   0.0   0.0  - 1.5+
                     Type: Matrix Float

If e is too big to fit where you specify, an error message is
displayed.  Use subMatrix to extract part of e, if necessary.

  e := matrix [ [6.7,9.11],[-31.33,67.19] ]
         +  6.7    9.11 +
         |              |
         +- 31.33  67.19+
                      Type: Matrix Float

This changes the submatrix of d whose upper left corner is at the
first row and second column and whose size is that of e.

  setsubMatrix!(d,1,2,e)
         +1.2    6.7    9.11    0.0 +
         |                          |
         |0.0  - 31.33  67.19   0.0 |
         |                          |
         |0.0    0.0     1.4    0.0 |
         |                          |
         +0.0    0.0     0.0   - 1.5+
                       Type: Matrix Float

  d
         +1.2    6.7    9.11    0.0 +
         |                          |
         |0.0  - 31.33  67.19   0.0 |
         |                          |
         |0.0    0.0     1.4    0.0 |
         |                          |
         +0.0    0.0     0.0   - 1.5+
                        Type: Matrix Float

Matrices can be joined either horizontally or vertically to make
new matrices.

  a := matrix [ [1/2,1/3,1/4],[1/5,1/6,1/7] ]
         +1  1  1+
         |-  -  -|
         |2  3  4|
         |       |
         |1  1  1|
         |-  -  -|
         +5  6  7+
                         Type: Matrix Fraction Integer

  b := matrix [ [3/5,3/7,3/11],[3/13,3/17,3/19] ] 
         +3   3    3+
         |-   -   --|
         |5   7   11|
         |          |
         | 3   3   3|
         |--  --  --|
         +13  17  19+
                         Type: Matrix Fraction Integer

Use horizConcat to append them side to side.  The two matrices must
have the same number of rows.

  horizConcat(a,b)
         +1  1  1  3   3    3+
         |-  -  -  -   -   --|
         |2  3  4  5   7   11|
         |                   |
         |1  1  1   3   3   3|
         |-  -  -  --  --  --|
         +5  6  7  13  17  19+
                         Type: Matrix Fraction Integer

Use vertConcat to stack one upon the other.  The two matrices must
have the same number of columns.

  vab := vertConcat(a,b)
         +1   1   1 +
         |-   -   - |
         |2   3   4 |
         |          |
         |1   1   1 |
         |-   -   - |
         |5   6   7 |
         |          |
         |3   3    3|
         |-   -   --|
         |5   7   11|
         |          |
         | 3   3   3|
         |--  --  --|
         +13  17  19+
                         Type: Matrix Fraction Integer

The operation transpose is used to create a new matrix by reflection
across the main diagonal.

  transpose vab
         +1  1  3    3+
         |-  -  -   --|
         |2  5  5   13|
         |            |
         |1  1  3    3|
         |-  -  -   --|
         |3  6  7   17|
         |            |
         |1  1   3   3|
         |-  -  --  --|
         +4  7  11  19+
                         Type: Matrix Fraction Integer

====================================================================
Operations on Matrices
====================================================================

FriCAS provides both left and right scalar multiplication.

  m := matrix [ [1,2],[3,4] ]
         +1  2+
         |    |
         +3  4+
                          Type: Matrix Integer

  4 * m * (-5)
         +- 20  - 40+
         |          |
         +- 60  - 80+
                          Type: Matrix Integer

You can add, subtract, and multiply matrices provided, of course, that
the matrices have compatible dimensions.  If not, an error message is
displayed.

  n := matrix([ [1,0,-2],[-3,5,1] ])
         + 1   0  - 2+
         |           |
         +- 3  5   1 +
                          Type: Matrix Integer

This following product is defined but n * m is not.

  m * n
         +- 5  10   0 +
         |            |
         +- 9  20  - 2+
                          Type: Matrix Integer

The operations nrows and ncols return the number of rows and columns
of a matrix.  You can extract a row or a column of a matrix using the
operations row and column.  The object returned is a Vector.

Here is the third column of the matrix n.

  vec := column(n,3)
     [- 2,1]
                          Type: Vector Integer

You can multiply a matrix on the left by a "row vector" and on the right
by a "column vector".

  vec * m
     [1,0]
                          Type: Vector Integer

Of course, the dimensions of the vector and the matrix must be compatible
or an error message is returned.

  m * vec
    [0,- 2]
                          Type: Vector Integer

The operation inverse computes the inverse of a matrix if the matrix
is invertible, and returns "failed" if not.

This Hilbert matrix is invertible.

  hilb := matrix([ [1/(i + j) for i in 1..3] for j in 1..3])
         +1  1  1+
         |-  -  -|
         |2  3  4|
         |       |
         |1  1  1|
         |-  -  -|
         |3  4  5|
         |       |
         |1  1  1|
         |-  -  -|
         +4  5  6+
                          Type: Matrix Fraction Integer

  inverse(hilb)
         + 72    - 240   180 +
         |                   |
         |- 240   900   - 720|
         |                   |
         + 180   - 720   600 +
                          Type: Union(Matrix Fraction Integer,...)

This matrix is not invertible.

  mm := matrix([ [1,2,3,4], [5,6,7,8], [9,10,11,12], [13,14,15,16] ])
         +1   2   3   4 +
         |              |
         |5   6   7   8 |
         |              |
         |9   10  11  12|
         |              |
         +13  14  15  16+
                           Type: Matrix Integer

  inverse(mm)
     "failed"
                           Type: Union("failed",...)

The operation determinant computes the determinant of a matrix
provided that the entries of the matrix belong to a CommutativeRing.

The above matrix mm is not invertible and, hence, must have determinant 0.

  determinant(mm)
    0
                           Type: NonNegativeInteger

The operation trace computes the trace of a square matrix.

  trace(mm)
    34
                           Type: PositiveInteger

The operation rank computes the rank of a matrix: the maximal number
of linearly independent rows or columns.

  rank(mm)
    2
                           Type: PositiveInteger

The operation nullity computes the nullity of a matrix: the dimension
of its null space.

  nullity(mm)
    2
                           Type: PositiveInteger

The operation nullSpace returns a list containing a basis for the null
space of a matrix.  Note that the nullity is the number of elements in
a basis for the null space.

  nullSpace(mm)
    [[1,- 2,1,0],[2,- 3,0,1]]
                           Type: List Vector Integer

The operation rowEchelon returns the row echelon form of a matrix.  It
is easy to see that the rank of this matrix is two and that its
nullity is also two.

  rowEchelon(mm)
         +1  2  3  4 +
         |           |
         |0  4  8  12|
         |           |
         |0  0  0  0 |
         |           |
         +0  0  0  0 +
                           Type: Matrix Integer

See Also
o )help OneDimensionalArray
o )help TwoDimensionalArray
o )help Vector
o )help Permanent
o )show Matrix

