Mentions légales du service

Skip to content
Snippets Groups Projects
Commit 456e82fc authored by hhakim's avatar hhakim
Browse files

Fix missing link in lazylinop jupyter notebook.

parent 71b4aedb
No related branches found
No related tags found
No related merge requests found
Pipeline #834133 skipped
......@@ -14165,7 +14165,7 @@ lF shape after concatenation: (8192, 4096)
<div class="jp-Cell-inputWrapper"><div class="jp-InputPrompt jp-InputArea-prompt">
</div><div class="jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput " data-mime-type="text/markdown">
<p>Note that we know the shape of the resulting <code>LazyLinearOp</code> without the need to evaluate it.</p>
<p>For a tour of all supported operations on <code>LazyLinearOp</code> objects please take a look at : <a href="TODO">link</a>.</p>
<p>For a tour of all supported operations on <code>LazyLinearOp</code> objects please take a look at : <a href="LazyLinearOp reference">https://faustgrp.gitlabpages.inria.fr/faust/last-doc/html/classpyfaust_1_1lazylinop_1_1LazyLinearOp.html</a>.</p>
 
</div>
</div>
......
%% Cell type:markdown id: tags:
# Using LazyLinearOp-s
The ``LazyLinearOp`` class is a kind of linear operator (indeed, it extends the scipy [LinearOperator](https://docs.scipy.org/doc/scipy/reference/generated/scipy.sparse.linalg.LinearOperator.html) class) for which the operations you make are delayed until you choose to evaluate them.
This class is intended to lower the computational cost in situations where many operations are made on linear operators but eventually not all of them will be used / evaluated.
Theoretically, it might also be useful to distribute the calculations around many computation units.
In this notebook we shall see how to create a ``LazyLinearOp`` instance, make operations on it and finally how to evaluate it to get the real result of these operations. We assume the reader is familiar with at least numpy arrays and their operations.
%% Cell type:markdown id: tags:
### 1. Creating a LazyLinearOp
In order to create this kind of object, you simply need to use the ``asLazyLinearOp`` function. This function receives an object that represents a linear operator, for instance a ``Faust`` (but it can also be a numpy array or a scipy matrix). The function instantiates a ``LazyLinearOp`` that encapsulates the ``Faust`` you gave.
%% Cell type:code id: tags:
``` python
from pyfaust.lazylinop import asLazyLinearOp
import pyfaust as pf
# create a random Faust
F = pf.rand(4096, 4096, density=.001)
# create a LazyLinearOp upon it
lF = asLazyLinearOp(F)
print(lF)
```
%% Cell type:markdown id: tags:
As said earlier, it is also possible to create a ``LazyLinearOp`` upon numpy arrays or scipy matrices.
%% Cell type:code id: tags:
``` python
from scipy.sparse import random
from numpy.random import rand
S = random(4096, 4096, .2, format='csr') # scipy matrix
lS = asLazyLinearOp(S)
M = rand(4096, 4096)*1j # numpy complex array
lM = asLazyLinearOp(M)
```
%% Cell type:markdown id: tags:
Then we can start to do some operations on these new objects. For example, let's multiply ``lF`` by a scalar:
%% Cell type:code id: tags:
``` python
lF = 2 * lF
print(lF)
```
%% Cell type:markdown id: tags:
As you can see it stays a ``LazyLinearOp`` after the scalar multiplication. That's the principle of the lazy evaluation we talked about at the beginning of this notebook. No operation is really computed, only the track of the operations asked is kept in a new LazyLinearOp object.
Let's continue asking other operations. For example, a matrix multiplication and then a concatenation.
%% Cell type:code id: tags:
``` python
import pyfaust.lazylinop as lp
lFs = lF @ lF
print("lF shape before concatenation:", lFs.shape)
lFc = lp.vstack((lFs, lFs))
print("lF shape after concatenation:", lFc.shape)
```
%% Cell type:markdown id: tags:
Note that we know the shape of the resulting LazyLinearOp without the need to evaluate it.
Let's try other operations with ``lM`` and ``lS``, all ``LazyLinearOp`` are compatible with each other.
%% Cell type:code id: tags:
``` python
lMSF = (2 * lM.conj().T + lS) @ lFc[:4096, :]
# then get back the imaginary part of the LazyLinearOp
lMSF_imag = lMSF.imag
```
%% Cell type:markdown id: tags:
Note that we know the shape of the resulting ``LazyLinearOp`` without the need to evaluate it.
For a tour of all supported operations on ``LazyLinearOp`` objects please take a look at : [link](TODO).
For a tour of all supported operations on ``LazyLinearOp`` objects please take a look at : [LazyLinearOp reference](https://faustgrp.gitlabpages.inria.fr/faust/last-doc/html/classpyfaust_1_1lazylinop_1_1LazyLinearOp.html).
%% Cell type:markdown id: tags:
### 2. Evaluating a LazyLinearOp
Now that we've seen how to create and operate a ``LazyLinearOp`` let's see how to get the evaluation done, that is obtaining the real results of our operations.
There are several ways to get these results. The most important way is to multiply the ``LazyLinearOp`` by a dense matrix (a numpy array) or a vector.
%% Cell type:code id: tags:
``` python
import numpy as np
lMSF_imag@np.random.rand(4096)
```
%% Cell type:markdown id: tags:
The other ways to evaluate is to call ``LazyLinearOp.eval`` or ``LazyLinearOp.toarray`` on our object. The former function returns an object whose type depends on the operations made so far on the starting object. The latter function returns always a numpy array which is the result of the same operations.
%% Cell type:markdown id: tags:
### 3. Checking the computation times
As a last step in this notebook, we shall verify how much computation time it takes to use a ``LazyLinearOperator`` compared to a numpy array. Of course it depends on the underlying objects used behind (in the operations encoded in the ``LazyLinearOperator``). Here we make the measurement on ``lFs`` which was initialized before upon a Faust object.
%% Cell type:code id: tags:
``` python
%timeit lFs@M
%timeit lFs.toarray()
FD = lFs.toarray() # FD is a numpy array
%timeit FD@M
print("consistent results:", np.allclose(lFs@M, FD@M))
```
%% Cell type:markdown id: tags:
Great! As excepted ``lFs`` is faster than its numpy array counterpart ``FD``.
%% Cell type:markdown id: tags:
This notebook comes to its end. We've seen quickly how to create and evaluate a ``LazyLinearOp`` objects based on a Faust object, numpy array or scipy matrices. For more information about ``LazyLinearOp`` objects you can take a look to the API documentation [here](TODO).
**NOTE**: this notebook was executed using the pyfaust version:
%% Cell type:code id: tags:
``` python
pf.version()
```
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment