From b2b8f5dbae223bce6c4ceead328bb786be43007f Mon Sep 17 00:00:00 2001 From: Umut Date: Fri, 17 Sep 2021 12:32:10 +0300 Subject: [PATCH] doc: write table lookup and working with floating points tutorials --- .../table-lookup/1.initial.graph.png | Bin 0 -> 36616 bytes .../tutorials/table-lookup/3.final.graph.png | Bin 0 -> 16902 bytes docs/index.rst | 2 +- docs/user/tutorial/TABLE_LOOKUP.md | 76 +++++++++++++++++- .../tutorial/WORKING_WITH_FLOATING_POINTS.md | 67 ++++++++++++++- 5 files changed, 142 insertions(+), 3 deletions(-) create mode 100644 docs/_static/tutorials/table-lookup/1.initial.graph.png create mode 100644 docs/_static/tutorials/table-lookup/3.final.graph.png diff --git a/docs/_static/tutorials/table-lookup/1.initial.graph.png b/docs/_static/tutorials/table-lookup/1.initial.graph.png new file mode 100644 index 0000000000000000000000000000000000000000..c6dc84e8c36411bc3fa92d5d457e711351825ded GIT binary patch literal 36616 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

bRBhZpp*FfihJZhpb&R!3HSHt+4?IHa9smFU literal 0 HcmV?d00001 diff --git a/docs/_static/tutorials/table-lookup/3.final.graph.png b/docs/_static/tutorials/table-lookup/3.final.graph.png new file mode 100644 index 0000000000000000000000000000000000000000..73b5ab86d4f1ca5d268902e370abcefe8349b25d GIT binary patch literal 16902 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 literal 0 HcmV?d00001 diff --git a/docs/index.rst b/docs/index.rst index 15754b2e3..967bb94d7 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -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:: diff --git a/docs/user/tutorial/TABLE_LOOKUP.md b/docs/user/tutorial/TABLE_LOOKUP.md index 1d92db930..4943e6c86 100644 --- a/docs/user/tutorial/TABLE_LOOKUP.md +++ b/docs/user/tutorial/TABLE_LOOKUP.md @@ -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)] +``` diff --git a/docs/user/tutorial/WORKING_WITH_FLOATING_POINTS.md b/docs/user/tutorial/WORKING_WITH_FLOATING_POINTS.md index 4b396c886..60ee51ad0 100644 --- a/docs/user/tutorial/WORKING_WITH_FLOATING_POINTS.md +++ b/docs/user/tutorial/WORKING_WITH_FLOATING_POINTS.md @@ -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.