in web pages made easy

LALOLib (Linear ALgebra Online Library) is a library entirely written in Javascript to enable and ease mathematical computing within web pages. It is developed as a part of the MLweb project and constitutes the core of LALOLab (an online scientific computing environment). It also provides the basic building blocks for ML.js, a javascript library for machine learning.

LALOLib includes functions for

- linear algebra,
- statistics,
- optimization (based on glpk.js),
- machine learning (in the
variant),*ML.js*

<script src="http://mlweb.loria.fr/lalolib.js"></script>or

<script src="http://mlweb.loria.fr/ml.js"></script>for ML.js.

Alternatively, you can use a local copy of the library (download lalolib or ml.js) and modify the path accordingly.

The following shows how to use the library. The list of available functions can also be quickly accessed in LALOLab, on the right of the screen, and a few machine learning oriented tutorials are also available.

- The direct (synchronous) method
- The safer (asynchronous) method: Computing in a background Lab
- Sending data to and retrieving data from a background Lab
- Parallel computing with multiple Labs
- Closing a Lab
- The direct method for scripts
- Importing LALOLab scripts
- Importing Javascript/LALOLib code
- Implementation details and data types
- Using the machine learning functions (ML.js)
- Writing efficient code with LALOLib
- Extending LALOLib/LALOLab
- Available functions / API reference

LALOLib functions can be used in a straightforward manner to implement computations in the current scope.

In this example we used the ** laloprint()** function to print a vector. Here are the various ways in which it can be used:

// Print the vector or matrix X to the standard LALOLib output (an HTML div with id="LALOLibOutput") laloprint( X ); // Print X to the HTML element with id=htmlId laloprint( X, htmlId ); // Append X to the HTML element with id=htmlId ( laloprint( X, htmlId, true ); // Return an HTML formated String for X str = laloprint(X, true);

The direct method is unsafe in the sense that it makes the browser freeze while waiting for the result.

If the computations take too long, the alternative is to do them in the background. This is implemented by opening a Lab with

var lab = new Lalolab() ; // open a standard Labor with

var lab = new MLlab() ; // open a Lab with machine learning capabilitiesdepending on the desired capabilities. Then, commands can then be sent the the lab with

**Note:** when using a local copy of lalolib.js (or ml.js), this requires a local copy of lalolibworker.js (or mlworker.js) in the same directory. In addition, the relative path to these files from the html page must be supplied as `var lab = new Lalolab("labname", false, path_to_lalolib ) ;`

or `var lab = new MLlab("labname", path_to_mljs ) ;`

.

The difference between *do( script, callback )* and *exec( command_string, callback )* is that *do* parses the string argument before executing it, whereas *exec* directly executes it. Thus,

lab.do( "x = (2*A + C*D) \ b" )is equivalent to

lab.exec("x = solve( add( mul(2,A), mul(C,D) ), b)");

Any Lab running in the background works with an independent scope, i.e., it cannot access variables in the current scope, nor can you access its variables directly.

Example 3 shows how to send data to a Lab with the function

load( variable_in_current_scope, variable_name_in_the_lab, callback)and how to recover data from a Lab with a call to

getObject( variable_name_in_the_lab, callback )

Note that this method can be combined with the direct method for instance to generate random data in the current scope with *randn()* before sending it to the lab.

Multiple Labs can be created. Each Lab works with its own private scope and runs in a different thread (a web worker in javascript language).

In order to free the memory or to force a Lab to stop computing, a Lab can be closed with

lab.close();

The direct method can also be used with LALOLab scripts without having to memorize LALOLib functions. To execute a script in the current global scope, use *lalo( script )*, where *script* is a string referring to global variables in the page.

Scripts written with LALOLab instructions can be imported in a Lab with the *import( script, callback )* function. However, the script must comply with the same-origin policy (typically, it must be located on the same server).

File "test.lalo": function sumsquares ( x ) { return (sum(x.*x)) }

Scripts written in pure Javascript (possibly calling LALOLib functions) can be imported in a Lab with the *importjs( JSscript, callback )* function. However, the script must comply with the same-origin policy (typically, it must be located on the same server).

File "test.js": function sumsquaresjs (x) { var ss = 0; for ( var i = 0; i < x.length; i++) ss += x[i] * x[i]; return ss; }

`x`

is recovered with
type(x) // returns the type of x as a string

"undefined" "number" // all numbers are 64-bit floats (double) "boolean" "string" "function" // functions are stored in variables "object"The basic type of a variable

`x`

can be recovered with
typeof(x)which returns the uninformative "object" for all the types below.

`type(x)`

returns the correct type (but is typically slower) as
"vector" "matrix" "spvector" "spmatrix" "Array" // standard javascript ArrayNote that

`"vector"`

is also returned for Arrays containing only numbers. Arrays can be used in general for lists of variable length with easy insertion and removal of entries.
Vectors are implemented as standard `Float64Array`

objects with a fixed size stored in the property `length`

:

x = zeros(5); // this is equivalent to x = new Float64Array(5); dim = x.length; // returns dim = 5The entries can be accessed directly with square brackets and indexes in the range 0...x.length-1 as

x[0] = first component of the vector x x[1] = second component of the vector x ... x[x.length-1] = last component of the vector x

A vector can be copied with

x2 = vectorCopy( x );while

`x2 = x`

makes `x2`

point to the same location in memory as `x`

(in a LALOLab script, x2 = x actually copies x into x2).
** Creating a Vector from an Array:** the vector copy can also be used to convert a standard javascript

`Array`

of numbers to a vector with
x = vectorCopy( [1, 2, 3, -4.2] ); // returns a Float64Array (i.e. a vector) initialized with the given values y = array2vec( [1, 2, 3, -4.2] ); // returns the same vector (this is equivalent)However, most functions working on vectors also work with Arrays of numbers.

`Matrix`

objects created with
A = new Matrix(m,n); // this is equivalent to A = zeros(m,n);and having the following properties:

A.type : object type = "matrix" (constant) A.m : number of rows (constant) A.n : number of columns (constant) A.length : number of rows (constant) (= A.m) A.size : size as an Array = [A.m, A.n] (constant) A.val : vector of valuesThe matrix entries are stored rowwise in a single vector

`A.val`

, i.e., the entry at the ith row and jth column is
A.val[i*A.n + j] // = A[i,j] in LALOLabfor i in the range 0...A.m-1 and j in the range 0...A.n-1.

** Creating a Matrix from a 2D Array:** given a 2D Array, a matrix is obtained with the function

a2DArray = [ [ 1, 2, 3], [4, 5, 6] ]; // an Array of as many Arrays as rows in the matrix aMatrix = array2mat(a2DArray); // a Matrix with 2 rows and 3 columns

Sparse vectors and matrices are created with

a = sparse( b ); A = sparse( B );The dense versions can be recovered with

b = full( a ); B = full( A );

Sparse vectors are implemented as `spVectors`

objects having the following properties:

a.type : object type = "spvector" (constant) a.length : size of the vector (constant) a.size : size as an Array = [a.length, 1] (constant) a.val : vector of values a.ind : vector of indexes a.nnz : number of nonzerosThe vector entries are stored such that a

`a.val[k]`

with `i = a.ind[k]`

.
Sparse matrices are implemented as `spMatrix`

objects having the following properties:

A.type : object type = "spmatrix" (constant) A.m : number of rows (constant) A.n : number of columns (constant) A.length : number of rows (constant) (= A.m) A.rowmajor : true/false for row/column compressed format A.size : size as an Array = [A.m, A.n] (constant) A.val : vector of values A.cols : list of column starting indexes A.rows : list of row indexes A.nnz : number of nonzerosThe matrix entries are stored by default (with

`A.rowmajor = true`

) in a row-sparse format with
A.rows[i] = starting index of row i in A.val and A.cols A.cols[k] = column of the value A.val[k]or (with

`A.rowmajor = false`

) in a column-sparse format with
A.cols[j] = starting index of column j in A.val and A.rows A.rows[k] = row of the value A.val[k]

`"Class:Subclass"`

, for instance:
"Distribution:Gaussian" // an object created by 'new Distribution(Gaussian,...)' "Classifier:SVM" // an object created by 'new Classifier(SVM, ... )' "Regression:LASSO" // an object created by 'new Regression(LASSO, ... )'

**ML.js** extends LALOLib with machine learning functions. Many examples can be found in the API reference below and the online help of LALOLab. You can also look at a few online demos and tutorials.

For supervised learning, predictive models are created with a *new* statement. For instance,

model = new Classifier(SVM, params);creates a new support vector machine (SVM) classifier with an optional argument (params) to set hyperparameters. Then, given an N-by-d matrix

model.train(X, Y);To see the result, the

prediction = model.predict(Xtest);where

Most machine learning models come with a self-tuning function, which automatically determines (or more precisely tries to determine) the best hyperparameters for training. This function can be used instead of the train() function as

model.tune(X, Y);

Below is the list of functions provided by LALOLib. The help shows both the script-like LALOLab syntax and the corresponding javascript calls. Examples are mostly written for LALOLab and should be executed by a lab.do() statement in a javascript context.

Select a topic on the left to see the help.

Linear algebra