Solving Matrix Algebra in JavaScript [An Overview] | Hacker Noon

June 22nd 2020

Author profile picture

Many problems, especially in scientific computing, end up being formulated as matrix operations. This can be anything from PDE-solvers (PDE – Partial Differential Equation) up to image-processing or ML-algorithms.

The list is endless.

Usually one has written on paper some final equations which describe your model or whatever it is, and it involves some matrix algebra like this:

Okay, looks quite easy on paper. Now, when it comes to implementation of this in JavaScript, whatever technique you are going to use (for-loops, iterators, …), your code won’t resemble above easy to read line.

There is a huge amount of good matrix-libraries available, and usually they let you write something like this:

A = B.add(C)

This still looks not quite different from our paper version, but imagine our paper version would be this:

A = (B * (C + D)) * (E + F)

To put this into one line by using the ‘.add’ notation might hurt a little and one would tend to split the code into multiple lines. Though, due to all these parenthesis, readability would be destroyed:

const H1 = E.add(F);
const H2 = C.add(D);
const H3 = B.multiply(H2);
const A = H3.multiply(H1);

If we were in context of a language like C++, we can give sense to expressions involving mathematical operators between any custom types – a concept called Operator Overloading. At the time of writing, JavaScript is lacking this nice feature though.

We can find some resort if we take a look at ‘Tagged Templates’ (see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Template_literals). In essence they give us a way to interpret a given string together with value filled placeholders:

const A: Matrix = ...;
const B: Matrix = ...;
const C: Matrix = calc`${A}+${B}`;

Here ‘Matrix’ shall be some type representing a matrix. The ‘calc’ is a tagged template function, written by us, and it will be called with all string parts and values for given placeholders. In other words we somewhere define a function like this:

function calc(stringParts: TemplateStringsArray, ...values: any[]){
        '1.) parse the expression
         2.) calculate it by using given   
             placeholder-values
         3.) return the result'
}

Our main task remains to implement the ‘calc’ function such that it can cope with any kind of expression from matrix-algebra.

With this at hand you can write expressions like these:

calc`${A} = 3 * ${B} - ${C}`;

A = calc`3 * ${B} - ${C}`;

calc`pow(${A}, 5)`;

The library also supports some form of slicing which becomes very handy in some occasions:

calc`${A.slice(1,1,5,5) =   
  cos(${B.slice(1,1,5,5)})`;

It also has some support of creating a matrix-type from given array:

const A = mat([[1,2],
               [3,4]]);   

Or just create a new instance of some dimensions and with all values set to 0:

const A = zeros(10, 10);
calc`${A}=sqrt(abs(${A})) + 7`;

Note: when you add or multiply a number with a matrix-type, as in above example, the parser is handling this by element-wise applying the operation to the matrix.

And finally our initial example would look like this:

calc`${A} = (${B} * (${C} + ${D})) * (${E} + ${F})`; 

For more you can look into its docs or tests. Please keep the following in mind: The library is not intended for use in computation intensive environments. It rather should be used for educational purposes or for presentation of some computations on a web-page. I used it successfully in some small project which intended to explain the solution procedure of a PDE.

I hope this helps or contributes to getting new ideas!

Tags

The Noonification banner

Subscribe to get your daily round-up of top tech stories!

read original article here