# Matrices and vectors in STACK

This page documents the use of matrices in STACK.  There is a topics page for setting [linear algebra](../Topics/Linear_algebra/index.md) STACK questions.

## Matrices ##

The operator `.` represents noncommutative multiplication and scalar product. The star `A*B` gives element-wise multiplication.

Maxima functions `addrow` and `addcol` appends rows/columns onto the matrix.

Maxima functions perform row operations

    rowswap(m,i,j)
    rowadd(m,i,j,k)

Where ` m[i]: m[i] + k * m[j]`.

    rowmul(m,i,k)

Where `m[i]: k * m[i]`.

STACK provides a function to compute reduced row echelon form

    rref(m)

## Assigning individual elements ##

To assign values to individual elements, use the simple syntax such as the following.

    m:matrix([1,1],[1,2])
    m[1,2]:3

Note also Maxima's `setelmx` function:

    setelmx (<x>, <i>, <j>, <M>)

Assigns `<x>` to the `(<i>, <j>)`'th element of the matrix `<M>`, and returns the altered matrix. `<M> [<i>, <j>]: <x>` has the same effect, but returns `<x>` instead of `<M>`.


### Showing working {#Showing-working}

It is quite common to want to show part of a matrix calculation "un-evaluated".  For example, the following is typical.

\[ \left[\begin{array}{cc} 1 & 2 \\ 4 & 5 \\ \end{array}\right] + \left[\begin{array}{cc} 1 & -1 \\ 1 & 2 \\ \end{array}\right] = \left[\begin{array}{cc} 1+1 & 2-1 \\ 4+1 & 5+2 \\  \end{array}\right] = \left[\begin{array}{cc} 2 & 1 \\ 5 & 7 \\ \end{array}\right] .\]

This is achieved, by having a question in which simplification is off, and we define the question variables as follows.

    A:matrix([1,2],[4,5]);
    B:matrix([1,-1],[1,2]);
    C:zip_with_matrix(A,B);
    D:ev(C,simp);

Notice the use of `zip_with_matrix` which is not a core Maxima function, but is defined by STACK.
The above equation is then generated by the CASText

    \[ {@A@}+{@B@}={@C@}={@D@}.\]

A similar procedure is needed for showing working when multiplying matrices.   Here we need to loop over the matrices, for square matrices we use the following.

    A:ev(rand(matrix([5,5],[5,5]))+matrix([2,2],[2,2]),simp);
    B:ev(rand(matrix([5,5],[5,5]))+matrix([2,2],[2,2]),simp);
    BT:transpose(B);
    C:zeromatrix (first(matrix_size(A)), second(matrix_size(A)));
    S:for a:1 thru first(matrix_size(A)) do for b:1 thru second(matrix_size(A)) do C[ev(a,simp),ev(b,simp)]:apply("+",zip_with("*",A[ev(a,simp)],BT[ev(b,simp)]));
    D:ev(C,simp);

Notice we need to simplify the arguments before we take indices of expressions, and the use of `zip_with`.  This is one problem with `simp:false`.

For non-square matrices we can use this.

    A:ev(rand(matrix([5,5,5],[5,5,5]))+matrix([2,2,2],[2,2,2]),simp);
    B:transpose(ev(rand(matrix([5,5,5],[5,5,5]))+matrix([2,2,2],[2,2,2]),simp));
    TA:ev(A.B,simp);
    BT:transpose(B);
    C:zeromatrix (first(matrix_size(A)), second(matrix_size(B)));
    S:for a:1 thru first(matrix_size(A)) do for b:1 thru second(matrix_size(B)) do C[ev(a,simp),ev(b,simp)]:apply("+",zip_with("*",A[ev(a,simp)],BT[ev(b,simp)]));
    D:ev(C,simp);

Now it makes no sense to include the point wise multiplication of elements as a possible wrong answer.

There must be a more elegant way to do this!

## Display of matrices ## {#matrixparens}

You can set the type of parentheses used to surround matrices in a number of ways.  Firstly, the admin user should set the site default in the qtype_stack options page.

For an individual question, the teacher can set the variable

    lmxchar:"(";

in any of the usual places, e.g. in the question variables.

To set the display of an individual matrix, `m` say, in castext you can use

    {@(lmxchar:"|", m)@}

Since `lmxchar` is a global setting in Maxima, you will have to set it back when you next display a matrix.  Not ideal, but there we are.

Note, STACK only displays matrices with matching parentheses.  If you want something like
\[ f(x) = \left\{ \begin{array}{cc} 1, & x<0 \\ 0, & x\geq 0 \end{array}\right.\]
then you will have to display the matrix without parentheses and sort out the mismatching parentheses in the CASText at the level of display.

For example, if we have the question variable `f:matrix([4*x+4, x<1],[-x^2-4*x-8, x>=1];` and the castext `\[ f(x) := \left\{ {@(lmxchar:"", f)@} \right. \]` 

STACK generates \[ f(x) := \left\{ {\begin{array}{cc} 4\cdot x+4 & x < 1 \\ -x^2-4\cdot x-8 & x\geq 1 \end{array}} \right. \]

LaTeX automatically sizes the parentheses and puts in `\right.` to represent a matching, but invisible closing parentesis.

You can control the alignment of the columns of the matrix using the function `stack_matrix_col(m)`. This function takes the matrix, and returns the string of characters "c", "l", or "r" to decide how to format the column in the LaTeX representation of the array.  By default, this is centered with "c". We need a _function_ to count the number of columns.  This is the default function.

    stack_matrix_col(ex) := simplode(maplist(lambda([ex], "c"), first(args(ex))))$

To change to right aligned columns, switch `"c"` to `"r"`.  This function takes the whole matrix and therefore potentially gives you full control.

For this function to take effect in the whole question, including validation of students' input, place the redefinition before `%_stack_preamble_end;` in the question variables.

