Wiki

Clone wiki

scl-manips-group / nengo / Matrix

Implementation and Usage Notes

File: matrix.py

class Matrix(nef.SimpleNode)

The Matrix class let's the user build compound matrix computations without worrying about the connections in the neural representation. Each matrix class has up to two arrays of neural populations encoding the information it contains.

  • identity population - This is the most intuitive way of representing the matrix. An m by n matrix will have an identity population which is an array of m*n separate one dimensional ensembles, each encoding one element of the matrix
  • product population - This representation is generated when a matrix is created out of the product of two other existing matrices. Let A be an m-by-n matrix and B be an n-by-k matrix. Let C be the product of A and B. Then the product population of C is an array of m*n*k separate 2 dimensional ensembles. Each ensemble encodes a pair of elements (one from matrix A and one from matrix B) that are to be multiplied together in performing the matrix multiplication. When this population is created, a transform m*n-by-m*n*k transform matrix is also created and stored by the Matrix class. This transform indicates how the ensembles of the product population should be connected to another m*n length ensemble if you want to encode the actual elements of the matrix C.

Usage Patterns

Initialization
The following code will initialize a 3 by 6 matrix with elements in the range (-1,1).

m,n = (3,6)  # matrix dimensions
radius = 1   # max size of any particular element

A = Matrix('A')
A.initialize(net,m,n,radius=radius)

This, however, does not create any neural population to represent the matrix. We must do so explicitly via one of two functions:

N = 50  # neurons to use per matrix element

A.create_identity(neurons=N)

or...

num_variables = 3
N_variables = 200
functions = [lambda x: x[0]*x[1], lambda x: x[1]*x[2], lambda x: x[2]*x[0]]

variables_population = net.make('variables',dimensions=num_variables,neurons=N,_variables,radius=1)
A.create_identity_from_functions(variables_population,num_variables,functions,neurons=N)

The first method will create the array of neural ensembles but will make no connections, unless the Matrix already has a product population, in which case it will make the connection such that both product population and identity population encode the same information. The second creates the ensembles and connects from another population such that the matrix represents the specified functions of the first population in each of its elements. Thus the length of the functions argument must be the equal to m*n.


Multiplication
The most useful operations that this class implements are matrix multiplication and transpose. We'll step into a bit of detail into how these work. Suppose A and B are matrices with valid identity populations (created as above). Creating the product is as simple as...

C = A.matrix_multiply(B)

After this line, C will be an instance of the Matrix class with a valid product population, but NOT an identity population. Identity representations of such products are not automatically created because it is anticipated that the user will be cascading matrix multiplies in order to perform some larger, more complex computation. However, if at any stage, you wish to have a population explicitly represent a matrix (as might be the case for certain special matrices that represent unified concepts: jacobian, generalized mass, etc.) you can use:

C.create_identity()

But the matrix C can be used as a perfectly valid matrix without creating the identity population. In particular, you can call:

E = C.matrix_multiply(D)

This reduces the number of neural ensembles used to perform the computation, but still allows for explicit representation when desired.


Transpose
This function provides a convenient way to work with the transpose of a matrix that already has a representation. Specifically, the line...

A_transpose = A.transpose()

...will create another instance of the matrix class, but link it to the same neural population that represented A, simply reshuffling how connections will be made within the matrix_multiply() function.

WARNING: A_transpose.get_termination("identity") will not work as expected. It will return the non-transposed termination


Creating Matrix Functions from Mathematica Text
The matrix.py file also defines a function that will generate a python script containing a sequence of numbered functions corresponding to each matrix element (in row major order) based on the raw input form for a matrix in Mathematica (which looks like: MatrixForm[...])

The function assumes that you used subscripted variables in Mathematica to represent the variables. Furthermore, it creates a function called getMatrixFunctions() which will return a ordered list of the enumerated functions just created. Here's an example:

text = "MatrixForm[{{Cos[Subscript[t, 0]] * Sin[[Subscript[t, 1]], 2 * Subscript[t, 1]},{2 * Subscript[t, 0],Cos[Subscript[t, 1]] * Sin[[Subscript[t, 0]]}}]"
m,n = (2,2)
num_variables = 2

createMatrixFunctionsScript(text,m,n,num_variables,"randomMatrix.py","randomElem",variable_name='t')

You can later retrieve these functions by using

import randomMatrix
functions = randomMatrix.getMatrixFunctions()

Updated