doc: write table lookup and working with floating points tutorials

This commit is contained in:
Umut
2021-09-17 12:32:10 +03:00
parent 327a85eb97
commit b2b8f5dbae
5 changed files with 142 additions and 3 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 36 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

View File

@@ -14,8 +14,8 @@ Concrete Framework's documentation
:caption: Tutorial
user/tutorial/ARITHMETIC_OPERATIONS.md
user/tutorial/WORKING_WITH_FLOATING_POINTS.md
user/tutorial/TABLE_LOOKUP.md
user/tutorial/WORKING_WITH_FLOATING_POINTS.md
user/tutorial/COMPILATION_ARTIFACTS.md
.. toctree::

View File

@@ -1,3 +1,77 @@
# Table Lookup
Umut to do: #314
In this tutorial, we are going to go over the ways to perform table lookups in **concrete**. Please read [Compiling and Executing](../howto/COMPILING_AND_EXECUTING.md) before reading further to see how you can compile the functions below.
## Direct table lookup
**concrete** provides a special class to allow direct table lookups. Here is how to import and use it:
```python
from concrete.common.extensions.table import LookupTable
table = LookupTable([2, 1, 3, 0])
def f(x):
return table[x]
```
where
- `x = EncryptedScalar(UnsignedInteger(2))`
results in
```python
engine.run(0) == 2
engine.run(1) == 1
engine.run(2) == 3
engine.run(3) == 0
```
## Fused table lookup
Direct tables are tedious to prepare by hand. When possible, **concrete** fuses the floating point operations into a single table lookup automatically. There are some limitations on fusing operations, which you can learn more about on the next tutorial, [Working With Floating Points](./WORKING_WITH_FLOATING_POINTS.md).
Here is an example function that results in fused table lookup:
```python
def f(x):
return 127 - (50 * (np.sin(x) + 1)).astype(np.uint32) # astype is to go back to integer world
```
where
- `x = EncryptedScalar(UnsignedInteger(3))`
results in
```python
engine.run(0) == 77
engine.run(1) == 35
engine.run(2) == 32
engine.run(3) == 70
engine.run(4) == 115
engine.run(5) == 125
engine.run(6) == 91
engine.run(7) == 45
```
Initially, the function is converted to this operation graph
![](../../_static/tutorials/table-lookup/1.initial.graph.png)
and after floating point operations are fused, we get the following operation graph
![](../../_static/tutorials/table-lookup/3.final.graph.png)
Internally, it uses the following lookup table
```python
table = LookupTable([50, 92, 95, 57, 12, 2, 36, 82])
```
which is calculated by:
```python
[(50 * (np.sin(x) + 1)).astype(np.uint32) for x in range(2 ** 3)]
```

View File

@@ -1,3 +1,68 @@
# Working With Floating Points
Umut to do: #313
## An example
```python
def f(x):
np.fabs(100 * (2 * np.sin(x) * np.cos(x))).astype(np.uint32) # astype is to go back to integer world
```
where
- `x = EncryptedScalar(UnsignedInteger(bits))`
results in
```python
engine.run(3) == 27
engine.run(0) == 0
engine.run(1) == 90
engine.run(10) == 91
engine.run(60) == 58
```
## Supported operations
The following operations are supported in the latest release, and we'll add more operations in the upcoming releases.
- np.arccos
- np.arccosh
- np.arcsin
- np.arcsinh
- np.arctan
- np.arctanh
- np.cbrt
- np.ceil
- np.cos
- np.cosh
- np.deg2rad
- np.degrees
- np.exp
- np.exp2
- np.expm1
- np.fabs
- np.floor
- np.log
- np.log10
- np.log1p
- np.log2
- np.rad2deg
- np.radians
- np.rint
- np.sin
- np.sinh
- np.spacing
- np.sqrt
- np.tan
- np.tanh
- np.trunc
## Limitations
Floating point support in **concrete** is very limited for the time being. They can't appear on inputs, or they can't be outputs. However, they can be used in intermediate results. Unfortunately, there are limitations on that front as well.
This biggest one is that, because floating point operations are fused into table lookups with a single unsigned integer input and single unsigned integer output, only univariate portion of code can be replaced with table lookups, which means multivariate portions cannot be compiled.
To give a precise example, `100 - np.fabs(50 * (np.sin(x) + np.sin(y)))` cannot be compiled because the floating point part depends on both `x` and `y` (i.e., it cannot be rewritten in the form `100 - table[z]` for a `z` that could be computed easily from `x` and `y`).
To dive into implementation details, you may refer to [Fusing Floating Point Operations](../../dev/explanation/FLOAT-FUSING.md) document.