Matrices

FISH supports two-dimensional matrices composed of floating-point values.

Addition and multiplication of appropriately sized matrices are supported.

Matrix components can be accessed using parentheses (), using row-column order. If the matrix has a single row or column, then only one index is necessary.

Four indices can be used to specify a sub-matrix of a larger matrix. In this case the first two are the starting row and column and the last two are the ending row and column. This notation can be used to retrieve a sub-matrix from a larger matrix, or on assignment to update a part of a larger matrix.

The following example illustrates accessing matrix components using parentheses:

    global m3 = matrix(3,3,   ...
                       1,2,3, ...
                       4,5,6, ...
                       7,8,9)
    global m1 = matrix(1,3,1,2,3)
	
    global a = m3(2,3)  ; a = 6.0
    m3(2,3) = 6.5       ; m3 = ((1,2,3) (4,5,6.5) (7,8,9))
    global b = m1(3)    ; b = 3.0
    m1(3) = 3.5
    global c = m3(2,1,2,3)  ; A 1x3 row vector removed from m3 (4,5,6.5)
    m3(3,1,3,3) = matrix(1,3,10,11,12) ; m3 = ((1,2,3) (4,5,6.5) (10,11,12))

Matrix types are created using the matrix library function. This function can also be used to convert lists, tensors, or arrays to matrices.

Matrices can be converted to a list, tensor, or array using the list, tensor, or array library functions.

A number of additional methods, detailed in the Matrix Utilities section, are available for matrix manipulation. These include matrix transpose, inversion, matrix determinant calculation and LU decomposition, among other operations. The math.outer.product performs the outer product of two vectors, returning a matrix.


Matrices are an iterable type. This means you can use it as the target of a loop foreach statement (see Loop ForEach and can be split (see Splitting). Each entry of the matrix is iterated rows first: so row 1 column 1 (1,1) followed by row 1 column 2 (1,2) followed by row 1 column 3 (1,3) etc.


As with most aggregate types, when the value is listed it will simply indicate that it is of type Matrix and give matrix size. To see the contents of the matrix use the fish list contents command.


The example below illustrates some simple matrix manipulations.

model new
; Matrix functionality tests
fish define setup
    alan = matrix(4,4)
    alan(1,3) = 6
    alan(2,1) = 2.2
    alan(3,4) = 6.6
    alan(4,2) = math.pi
end
[setup]
[alan(4,2)]
[alan = matrix.transpose(alan)]
[alan(2,4)]


fish define sum_tests
    herp = matrix(2,2, 6,-1,-3,2)
    derp = matrix(2,2, 4, 3,-7,0)
   
    klerp = herp + derp
    werp = herp - derp
    serp = herp * derp
end
[sum_tests]
[klerp(1,1)] 
[werp(1,1)] 
[serp(1,1)] 
 
fish define test
    local first = vector(2,4,3)
    local second = vector(8,1,5)
    local prod = math.outer.product(first, second)
    output = list(prod)
end
[test]
fish list contents [output]