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:
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 //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.You can do it on your own, it is quite a learning-full experience, or you can use my package provided here: 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:
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!