Class Equation


  • public class Equation
    extends java.lang.Object

    Equation allows the user to manipulate matrices in a more compact symbolic way, similar to Matlab and Octave. Aliases are made to Matrices and scalar values which can then be manipulated by specifying an equation in a string. These equations can either be "pre-compiled" [1] into a sequence of operations or immediately executed. While the former is more verbose, when dealing with small matrices it significantly faster and runs close to the speed of normal hand written code.

    Each string represents a single line and must have one and only one assignment '=' operator. Temporary variables are handled transparently to the user. Temporary variables are declared at compile time, but resized at runtime. If the inputs are not resized and the code is precompiled, then no new memory will be declared. When a matrix is assigned the results of an operation it is resized so that it can store the results.

    The compiler currently produces simplistic code. For example, if it encounters the following equation "a = b*c' it will not invoke multTransB(b,c,a), but will explicitly transpose c and then call mult(). In the future it will recognize such short cuts.

    Usage example:
     Equation eq = new Equation();
     eq.alias(x,"x", P,"P", Q,"Q");
    
     eq.process("x = F*x");
     eq.process("P = F*P*F' + Q");
     
    Which will modify the matrices 'x' and 'P'. Support for sub-matrices and inline matrix construction is also available.
     eq.process("x = [2 1 0; 0 1 3;4 5 6]*x");  // create a 3x3 matrix then multiply it by x
     eq.process("x(1:3,5:9) = [a ; b]*2");      // fill the sub-matrix with the result
     eq.process("x(:) = a(4:2:20)");            // fill all elements of x with the specified elements in 'a'
     eq.process("x( 4 3 ) = a");                // fill only the specified number sequences with 'a'
     eq.process("x = [2:3:25 1 4]");            // create a row matrix from the number sequence
     
    To pre-compile one of the above lines, do the following instead:
     Sequence predictX = eq.compile("x = F*x");
     predictX.perform();
     
    Then you can invoke it as much as you want without the "expensive" compilation step. If you are dealing with larger matrices (e.g. 100 by 100) then it is likely that the compilation step has an insignificant runtime cost. Variables can also be lazily declared and their type inferred under certain conditions. For example:
     eq.alias(A,"A", B,"B");
     eq.process("C = A*B");
     DMatrixRMaj C = eq.lookupMatrix("C");
     
    In this case 'C' was lazily declared. To access the variable, or any others, you can use one of the lookup*() functions. Sometimes you don't get the results you expect and it can be helpful to print out the tokens and which operations the compiler selected. To do this set the second parameter to eq.compile() or eq.process() to true:
     Code:
     eq.process("C=2.1*B'*A",true);
    
     Output:
     Parsed tokens:
     ------------
     Word:C
     ASSIGN
     VarSCALAR
     TIMES
     VarMATRIX
     TRANSPOSE
     TIMES
     VarMATRIX
    
     Operations:
     ------------
     transpose-m
     multiply-ms
     multiply-mm
     copy-mm
     

    Built in Constants

     pi = Math.PI
     e  = Math.E
     

    Supported functions

     eye(N)       Create an identity matrix which is N by N.
     eye(A)       Create an identity matrix which is A.numRows by A.numCols
     normF(A)     Frobenius normal of the matrix.
     normP(A,p)   P-norm for a matrix or vector.  p=1 or p=2 is typical.
     sum(A)       Sum of every element in A
     sum(A,d)     Sum of rows for d = 0 and columns for d = 1
     det(A)       Determinant of the matrix
     inv(A)       Inverse of a matrix
     pinv(A)      Pseudo-inverse of a matrix
     rref(A)      Reduced row echelon form of A
     trace(A)     Trace of the matrix
     zeros(r,c)   Matrix full of zeros with r rows and c columns.
     ones(r,c)    Matrix full of ones with r rows and c columns.
     rand(r,c)    Matrix filled with i.i.d uniform numbers from 0 to 1
     randn(r,c)   Matrix filled with i.i.d normal distribution with mean of zero and stdev of 1
     rng(seed)    Specifies the random number generator's seed
     diag(A)      If a vector then returns a square matrix with diagonal elements filled with vector
     diag(A)      If a matrix then it returns the diagonal elements as a column vector
     dot(A,B)     Returns the dot product of two vectors as a double.  Does not work on general matrices.
     solve(A,B)   Returns the solution X from A*X = B.
     kron(A,B)    Kronecker product
     abs(A)       Absolute value of A.
     max(A)       Element with the largest value in A.
     max(A,d)     Vector containing largest element along the rows (d=0) or columns (d=1)
     min(A)       Element with the smallest value in A.
     min(A,d)     Vector containing largest element along the rows (d=0) or columns (d=1)
     pow(a,b)     Computes a to the power of b.  Can also be invoked with "a^b" scalars only.
     sqrt(a)      Computes the square root of a.
     sin(a)       Math.sin(a) for scalars only
     cos(a)       Math.cos(a) for scalars only
     atan(a)      Math.atan(a) for scalars only
     atan2(a,b)   Math.atan2(a,b) for scalars only
     exp(a)       Math.exp(a) for scalars is also an element-wise matrix operator
     log(a)       Math.log(a) for scalars is also an element-wise matrix operator
     

    Supported operations

     '*'        multiplication (Matrix-Matrix, Scalar-Matrix, Scalar-Scalar)
     '+'        addition (Matrix-Matrix, Scalar-Matrix, Scalar-Scalar)
     '-'        subtraction (Matrix-Matrix, Scalar-Matrix, Scalar-Scalar)
     '/'        divide (Matrix-Scalar, Scalar-Scalar)
     '/'        matrix solve "x=b/A" is equivalent to x=solve(A,b) (Matrix-Matrix)
     '^'        Scalar power.  a^b is a to the power of b.
     '\'        left-divide.  Same as divide but reversed.  e.g. x=A\b is x=solve(A,b)
     '.*'       element-wise multiplication (Matrix-Matrix)
     './'       element-wise division (Matrix-Matrix)
     '.^'       element-wise power. (scalar-scalar) (matrix-matrix) (scalar-matrix) (matrix-scalar)
     '''        matrix transpose
     '='        assignment by value (Matrix-Matrix, Scalar-Scalar)
     
    Order of operations: [ ' ] precedes [ ^ .^ ] precedes [ * / .* ./ ] precedes [ + - ]

    Specialized submatrix and matrix construction syntax

     Extracts a sub-matrix from A with rows 1 to 10 (inclusive) and column 3.
                   A(1:10,3)
     Extracts a sub-matrix from A with rows 2 to numRows-1 (inclusive) and all the columns.
                   A(2:,:)
     Will concat A and B along their columns and then concat the result with  C along their rows.
                    [A,B;C]
     Defines a 3x2 matrix.
                [1 2; 3 4; 4 5]
     You can also perform operations inside:
                [[2 3 4]';[4 5 6]']
     Will assign B to the sub-matrix in A.
                 A(1:3,4:8) = B
     

    Integer Number Sequences

    Previous example code has made much use of integer number sequences. There are three different types of integer number sequences 'explicit', 'for', and 'for-range'.
     1) Explicit:
        Example: "1 2 4 0"
        Example: "1 2,-7,4"     Commas needed to create negative numbers. Otherwise it will be subtraction.
     2) for:
        Example:  "2:10"        Sequence of "2 3 4 5 6 7 8 9 10"
        Example:  "2:2:10"      Sequence of "2 4 6 8 10"
     3) for-range:
        Example:  "2:"          Sequence of "2 3 ... max"
        Example:  "2:2:"        Sequence of "2 4 ... max"
     4) combined:
        Example:  "1 2 7:10"    Sequence of "1 2 7 8 9 10"
     

    Macros

    Macros are used to insert patterns into the code. Consider this example:
     eq.process("macro ata( a ) = (a'*a)");
     eq.process("b = ata(c)");
     
    The first line defines a macro named "ata" with one parameter 'a'. When compiled the equation in the second line is replaced with "b = (a'*a)". The "(" ")" in the macro isn't strictly necissary in this situation, but is a good practice. Consider the following.
     eq.process("b = ata(c)*r");
     
    Will become "b = (a'*a)*r" but with out () it will be "b = a'*a*r" which is not the same thing!

    NOTE:In the future macros might be replaced with functions. Macros are harder for the user to debug, but functions are harder for EJML's developer to implement.

    Footnotes:

     [1] It is not compiled into Java byte-code, but into a sequence of operations stored in a List.
     
    • Nested Class Summary

      Nested Classes 
      Modifier and Type Class Description
      protected static class  Equation.TokenType  
    • Constructor Summary

      Constructors 
      Constructor Description
      Equation()  
      Equation​(java.lang.Object... args)
      Consturctor which allows you to alias variables
    • Method Summary

      All Methods Static Methods Instance Methods Concrete Methods 
      Modifier and Type Method Description
      void alias​(double value, java.lang.String name)
      Adds a new floating point variable.
      void alias​(int value, java.lang.String name)
      Adds a new integer variable.
      void alias​(java.lang.Object... args)
      Creates multiple aliases at once.
      void alias​(org.ejml.data.DMatrixRMaj variable, java.lang.String name)
      Adds a new Matrix variable.
      void alias​(org.ejml.data.DMatrixSparseCSC variable, java.lang.String name)  
      void alias​(org.ejml.data.FMatrixRMaj variable, java.lang.String name)  
      void alias​(SimpleMatrix variable, java.lang.String name)  
      protected void aliasGeneric​(java.lang.Object variable, java.lang.String name)
      Aliases variables with an unknown type.
      Sequence compile​(java.lang.String equation)  
      Sequence compile​(java.lang.String equation, boolean assignment, boolean debug)
      Parses the equation and compiles it into a sequence which can be executed later on
      protected org.ejml.equation.TokenList.Token createFunction​(org.ejml.equation.TokenList.Token name, java.util.List<org.ejml.equation.TokenList.Token> inputs, org.ejml.equation.TokenList tokens, Sequence sequence)
      Adds a new operation to the list from the operation and two variables.
      protected org.ejml.equation.TokenList.Token createOp​(org.ejml.equation.TokenList.Token left, org.ejml.equation.TokenList.Token op, org.ejml.equation.TokenList.Token right, org.ejml.equation.TokenList tokens, Sequence sequence)
      Adds a new operation to the list from the operation and two variables.
      protected org.ejml.equation.TokenList extractTokens​(java.lang.String equation, ManagerTempVariables managerTemp)
      Parses the text string to extract tokens.
      ManagerFunctions getFunctions()
      Returns the functions manager
      protected void handleParentheses​(org.ejml.equation.TokenList tokens, Sequence sequence)
      Searches for pairs of parentheses and processes blocks inside of them.
      protected org.ejml.equation.TokenList.Token insertTranspose​(org.ejml.equation.TokenList.Token variable, org.ejml.equation.TokenList tokens, Sequence sequence)
      Adds a new operation to the list from the operation and two variables.
      protected static boolean isLetter​(char c)
      Returns true if the character is a valid letter for use in a variable name
      protected static boolean isOperatorLR​(Symbol s)
      Operators which affect the variables to its left and right
      protected boolean isReserved​(java.lang.String name)
      Returns true if the specified name is NOT allowed.
      protected static boolean isSymbol​(char c)  
      protected static boolean isTargetOp​(org.ejml.equation.TokenList.Token token, Symbol[] ops)
      Checks to see if the token is in the list of allowed character operations.
      org.ejml.data.DMatrixRMaj lookupDDRM​(java.lang.String token)  
      double lookupDouble​(java.lang.String token)  
      org.ejml.data.FMatrixRMaj lookupFDRM​(java.lang.String token)  
      int lookupInteger​(java.lang.String token)  
      Macro lookupMacro​(java.lang.String token)  
      SimpleMatrix lookupSimple​(java.lang.String token)  
      <T extends Variable>
      T
      lookupVariable​(java.lang.String token)
      Looks up a variable given its name.
      protected org.ejml.equation.TokenList.Token parseBlockNoParentheses​(org.ejml.equation.TokenList tokens, Sequence sequence, boolean insideMatrixConstructor)
      Parses a code block with no parentheses and no commas.
      protected void parseBracketCreateMatrix​(org.ejml.equation.TokenList tokens, Sequence sequence)
      Searches for brackets which are only used to construct new matrices by concatenating 1 or more matrices together
      protected void parseCombineIntegerLists​(org.ejml.equation.TokenList tokens)
      Looks for sequences of integer lists and combine them into one big sequence
      protected void parseIntegerLists​(org.ejml.equation.TokenList tokens)
      Searches for a sequence of integers example: 1 2 3 4 6 7 -3
      protected void parseNegOp​(org.ejml.equation.TokenList tokens, Sequence sequence)
      Searches for cases where a minus sign means negative operator.
      protected void parseOperationsL​(org.ejml.equation.TokenList tokens, Sequence sequence)
      Parses operations where the input comes from variables to its left only.
      protected void parseOperationsLR​(Symbol[] ops, org.ejml.equation.TokenList tokens, Sequence sequence)
      Parses operations where the input comes from variables to its left and right
      protected java.util.List<org.ejml.equation.TokenList.Token> parseParameterCommaBlock​(org.ejml.equation.TokenList tokens, Sequence sequence)
      Searches for commas in the set of tokens.
      protected void parseSequencesWithColons​(org.ejml.equation.TokenList tokens, Sequence sequence)
      Searches for descriptions of integer sequences and array ranges that have a colon character in them Examples of integer sequences: 1:6 2:4:20 : Examples of array range 2: 2:4:
      protected org.ejml.equation.TokenList.Token parseSubmatrixToExtract​(org.ejml.equation.TokenList.Token variableTarget, org.ejml.equation.TokenList tokens, Sequence sequence)
      Converts a submatrix into an extract matrix operation.
      void print​(java.lang.String equation)
      Prints the results of the equation to standard out.
      Equation process​(java.lang.String equation)
      Compiles and performs the provided equation.
      Equation process​(java.lang.String equation, boolean debug)
      Compiles and performs the provided equation.
      void setSeed()
      Sets the random seed using a seed based on the current time
      void setSeed​(long seed)
      Specifies the seed used in random number generators
      • Methods inherited from class java.lang.Object

        clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
    • Constructor Detail

      • Equation

        public Equation()
      • Equation

        public Equation​(java.lang.Object... args)
        Consturctor which allows you to alias variables
        Parameters:
        args - arguments for alias
        See Also:
        alias(Object...)
    • Method Detail

      • setSeed

        public void setSeed​(long seed)
        Specifies the seed used in random number generators
        Parameters:
        seed - New seed for random number generator
      • setSeed

        public void setSeed()
        Sets the random seed using a seed based on the current time
      • alias

        public void alias​(org.ejml.data.DMatrixRMaj variable,
                          java.lang.String name)
        Adds a new Matrix variable. If one already has the same name it is written over. While more verbose for multiple variables, this function doesn't require new memory be declared each time it's called.
        Parameters:
        variable - Matrix which is to be assigned to name
        name - The name of the variable
      • alias

        public void alias​(org.ejml.data.FMatrixRMaj variable,
                          java.lang.String name)
      • alias

        public void alias​(org.ejml.data.DMatrixSparseCSC variable,
                          java.lang.String name)
      • alias

        public void alias​(SimpleMatrix variable,
                          java.lang.String name)
      • alias

        public void alias​(double value,
                          java.lang.String name)
        Adds a new floating point variable. If one already has the same name it is written over.
        Parameters:
        value - Value of the number
        name - Name in code
      • alias

        public void alias​(int value,
                          java.lang.String name)
        Adds a new integer variable. If one already has the same name it is written over.
        Parameters:
        value - Value of the number
        name - Name in code
      • alias

        public void alias​(java.lang.Object... args)
        Creates multiple aliases at once.
      • aliasGeneric

        protected void aliasGeneric​(java.lang.Object variable,
                                    java.lang.String name)
        Aliases variables with an unknown type.
        Parameters:
        variable - The variable being aliased
        name - Name of the variable
      • compile

        public Sequence compile​(java.lang.String equation)
      • compile

        public Sequence compile​(java.lang.String equation,
                                boolean assignment,
                                boolean debug)
        Parses the equation and compiles it into a sequence which can be executed later on
        Parameters:
        equation - String in simple equation format.
        assignment - if true an assignment is expected and an exception if thrown if there is non
        debug - if true it will print out debugging information
        Returns:
        Sequence of operations on the variables
      • handleParentheses

        protected void handleParentheses​(org.ejml.equation.TokenList tokens,
                                         Sequence sequence)
        Searches for pairs of parentheses and processes blocks inside of them. Embedded parentheses are handled with no problem. On output only a single token should be in tokens.
        Parameters:
        tokens - List of parsed tokens
        sequence - Sequence of operators
      • parseParameterCommaBlock

        protected java.util.List<org.ejml.equation.TokenList.Token> parseParameterCommaBlock​(org.ejml.equation.TokenList tokens,
                                                                                             Sequence sequence)
        Searches for commas in the set of tokens. Used for inputs to functions. Ignore comma's which are inside a [ ] block
        Returns:
        List of output tokens between the commas
      • parseSubmatrixToExtract

        protected org.ejml.equation.TokenList.Token parseSubmatrixToExtract​(org.ejml.equation.TokenList.Token variableTarget,
                                                                            org.ejml.equation.TokenList tokens,
                                                                            Sequence sequence)
        Converts a submatrix into an extract matrix operation.
        Parameters:
        variableTarget - The variable in which the submatrix is extracted from
      • parseBlockNoParentheses

        protected org.ejml.equation.TokenList.Token parseBlockNoParentheses​(org.ejml.equation.TokenList tokens,
                                                                            Sequence sequence,
                                                                            boolean insideMatrixConstructor)
        Parses a code block with no parentheses and no commas. After it is done there should be a single token left, which is returned.
      • parseSequencesWithColons

        protected void parseSequencesWithColons​(org.ejml.equation.TokenList tokens,
                                                Sequence sequence)
        Searches for descriptions of integer sequences and array ranges that have a colon character in them Examples of integer sequences: 1:6 2:4:20 : Examples of array range 2: 2:4:
      • parseIntegerLists

        protected void parseIntegerLists​(org.ejml.equation.TokenList tokens)
        Searches for a sequence of integers example: 1 2 3 4 6 7 -3
      • parseCombineIntegerLists

        protected void parseCombineIntegerLists​(org.ejml.equation.TokenList tokens)
        Looks for sequences of integer lists and combine them into one big sequence
      • parseBracketCreateMatrix

        protected void parseBracketCreateMatrix​(org.ejml.equation.TokenList tokens,
                                                Sequence sequence)
        Searches for brackets which are only used to construct new matrices by concatenating 1 or more matrices together
      • parseNegOp

        protected void parseNegOp​(org.ejml.equation.TokenList tokens,
                                  Sequence sequence)
        Searches for cases where a minus sign means negative operator. That happens when there is a minus sign with a variable to its right and no variable to its left Example: a = - b * c
      • parseOperationsL

        protected void parseOperationsL​(org.ejml.equation.TokenList tokens,
                                        Sequence sequence)
        Parses operations where the input comes from variables to its left only. Hard coded to only look for transpose for now
        Parameters:
        tokens - List of all the tokens
        sequence - List of operation sequence
      • parseOperationsLR

        protected void parseOperationsLR​(Symbol[] ops,
                                         org.ejml.equation.TokenList tokens,
                                         Sequence sequence)
        Parses operations where the input comes from variables to its left and right
        Parameters:
        ops - List of operations which should be parsed
        tokens - List of all the tokens
        sequence - List of operation sequence
      • insertTranspose

        protected org.ejml.equation.TokenList.Token insertTranspose​(org.ejml.equation.TokenList.Token variable,
                                                                    org.ejml.equation.TokenList tokens,
                                                                    Sequence sequence)
        Adds a new operation to the list from the operation and two variables. The inputs are removed from the token list and replaced by their output.
      • createOp

        protected org.ejml.equation.TokenList.Token createOp​(org.ejml.equation.TokenList.Token left,
                                                             org.ejml.equation.TokenList.Token op,
                                                             org.ejml.equation.TokenList.Token right,
                                                             org.ejml.equation.TokenList tokens,
                                                             Sequence sequence)
        Adds a new operation to the list from the operation and two variables. The inputs are removed from the token list and replaced by their output.
      • createFunction

        protected org.ejml.equation.TokenList.Token createFunction​(org.ejml.equation.TokenList.Token name,
                                                                   java.util.List<org.ejml.equation.TokenList.Token> inputs,
                                                                   org.ejml.equation.TokenList tokens,
                                                                   Sequence sequence)
        Adds a new operation to the list from the operation and two variables. The inputs are removed from the token list and replaced by their output.
      • lookupVariable

        public <T extends Variable> T lookupVariable​(java.lang.String token)
        Looks up a variable given its name. If none is found then return null.
      • lookupMacro

        public Macro lookupMacro​(java.lang.String token)
      • lookupDDRM

        public org.ejml.data.DMatrixRMaj lookupDDRM​(java.lang.String token)
      • lookupFDRM

        public org.ejml.data.FMatrixRMaj lookupFDRM​(java.lang.String token)
      • lookupInteger

        public int lookupInteger​(java.lang.String token)
      • lookupDouble

        public double lookupDouble​(java.lang.String token)
      • extractTokens

        protected org.ejml.equation.TokenList extractTokens​(java.lang.String equation,
                                                            ManagerTempVariables managerTemp)
        Parses the text string to extract tokens.
      • lookupSimple

        public SimpleMatrix lookupSimple​(java.lang.String token)
      • isTargetOp

        protected static boolean isTargetOp​(org.ejml.equation.TokenList.Token token,
                                            Symbol[] ops)
        Checks to see if the token is in the list of allowed character operations. Used to apply order of operations
        Parameters:
        token - Token being checked
        ops - List of allowed character operations
        Returns:
        true for it being in the list and false for it not being in the list
      • isSymbol

        protected static boolean isSymbol​(char c)
      • isOperatorLR

        protected static boolean isOperatorLR​(Symbol s)
        Operators which affect the variables to its left and right
      • isLetter

        protected static boolean isLetter​(char c)
        Returns true if the character is a valid letter for use in a variable name
      • isReserved

        protected boolean isReserved​(java.lang.String name)
        Returns true if the specified name is NOT allowed. It isn't allowed if it matches a built in operator or if it contains a restricted character.
      • process

        public Equation process​(java.lang.String equation)
        Compiles and performs the provided equation.
        Parameters:
        equation - String in simple equation format
      • process

        public Equation process​(java.lang.String equation,
                                boolean debug)
        Compiles and performs the provided equation.
        Parameters:
        equation - String in simple equation format
      • print

        public void print​(java.lang.String equation)
        Prints the results of the equation to standard out. Useful for debugging
      • getFunctions

        public ManagerFunctions getFunctions()
        Returns the functions manager