mirror of
https://github.com/zama-ai/concrete.git
synced 2026-02-09 20:25:34 -05:00
docs: migrate from Sphinx to Gitbook
This commit is contained in:
@@ -2,10 +2,7 @@
|
||||
|
||||
## What is **concrete-numpy**?
|
||||
|
||||
**concrete-numpy** is a convenient python package, made on top of **Concrete compiler** and **Concrete library**, for developing homomorphic applications.
|
||||
One of its essential functionalities is to transform Python functions to their `MLIR` equivalent.
|
||||
Unfortunately, not all python functions can be converted due to the limits of current product (we are in the alpha stage), or sometimes due to inherent restrictions of FHE itself.
|
||||
However, you can already build interesting and impressing use cases, and more will be available in further versions of the framework.
|
||||
**concrete-numpy** is a convenient python package, made on top of **Concrete compiler** and **Concrete library**, for developing homomorphic applications. One of its essential functionalities is to transform Python functions to their `MLIR` equivalent. Unfortunately, not all python functions can be converted due to the limits of current product (we are in the alpha stage), or sometimes due to inherent restrictions of FHE itself. However, you can already build interesting and impressing use cases, and more will be available in further versions of the framework.
|
||||
|
||||
## How can I use it?
|
||||
|
||||
@@ -30,27 +27,19 @@ circuit.encrypt_run_decrypt(1, 0)
|
||||
|
||||
## Overview of the numpy compilation process
|
||||
|
||||
The compilation journey begins with tracing to get an easy to understand and manipulate representation of the function.
|
||||
We call this representation `Computation Graph` which is basically a Directed Acyclic Graph (DAG) containing nodes representing the computations done in the function.
|
||||
Working with graphs is good because they have been studied extensively over the years and there are a lot of algorithms to manipulate them.
|
||||
Internally, we use [networkx](https://networkx.org) which is an excellent graph library for Python.
|
||||
The compilation journey begins with tracing to get an easy to understand and manipulate representation of the function. We call this representation `Computation Graph` which is basically a Directed Acyclic Graph (DAG) containing nodes representing the computations done in the function. Working with graphs is good because they have been studied extensively over the years and there are a lot of algorithms to manipulate them. Internally, we use [networkx](https://networkx.org) which is an excellent graph library for Python.
|
||||
|
||||
The next step in the compilation is transforming the computation graph.
|
||||
There are many transformations we perform, and they will be discussed in their own sections.
|
||||
In any case, the result of transformations is just another computation graph.
|
||||
The next step in the compilation is transforming the computation graph. There are many transformations we perform, and they will be discussed in their own sections. In any case, the result of transformations is just another computation graph.
|
||||
|
||||
After transformations are applied, we need to determine the bounds (i.e., the minimum and the maximum values) of each intermediate node.
|
||||
This is required because FHE currently allows a limited precision for computations.
|
||||
Bound measurement is our way to know what is the needed precision for the function.
|
||||
After transformations are applied, we need to determine the bounds (i.e., the minimum and the maximum values) of each intermediate node. This is required because FHE currently allows a limited precision for computations. Bound measurement is our way to know what is the needed precision for the function.
|
||||
|
||||
The final step is to transform the computation graph to equivalent `MLIR` code.
|
||||
How this is done will be explained in detail in its own chapter.
|
||||
The final step is to transform the computation graph to equivalent `MLIR` code. How this is done will be explained in detail in its own chapter.
|
||||
|
||||
Once the MLIR is prepared, the rest of the stack, which you can learn more about [here](http://docs.zama.ai/), takes over and completes the compilation process.
|
||||
|
||||
Here is the visual representation of the pipeline:
|
||||
|
||||

|
||||

|
||||
|
||||
## Tracing
|
||||
|
||||
@@ -63,13 +52,11 @@ def f(x):
|
||||
|
||||
the goal of tracing is to create the following computation graph without needing any change from the user.
|
||||
|
||||

|
||||

|
||||
|
||||
(Note that the edge labels are for non-commutative operations. To give an example, a subtraction node represents `(predecessor with edge label 0) - (predecessor with edge label 1)`)
|
||||
|
||||
To do this, we make use of Tracers, which are objects that record the operation performed during their creation.
|
||||
We create a `Tracer` for each argument of the function and call the function with those tracers.
|
||||
Tracers make use of operator overloading feature of Python to achieve their goal.
|
||||
To do this, we make use of Tracers, which are objects that record the operation performed during their creation. We create a `Tracer` for each argument of the function and call the function with those tracers. Tracers make use of operator overloading feature of Python to achieve their goal.
|
||||
|
||||
Here is an example:
|
||||
|
||||
@@ -83,16 +70,11 @@ y = Tracer(computation=Input("y"))
|
||||
resulting_tracer = f(x, y)
|
||||
```
|
||||
|
||||
`2 * y` will be performed first, and `*` is overloaded for `Tracer` to return another tracer:
|
||||
`Tracer(computation=Multiply(Constant(2), self.computation))` which is equal to:
|
||||
`Tracer(computation=Multiply(Constant(2), Input("y")))`
|
||||
`2 * y` will be performed first, and `*` is overloaded for `Tracer` to return another tracer: `Tracer(computation=Multiply(Constant(2), self.computation))` which is equal to: `Tracer(computation=Multiply(Constant(2), Input("y")))`
|
||||
|
||||
`x + (2 * y)` will be performed next, and `+` is overloaded for `Tracer` to return another tracer:
|
||||
`Tracer(computation=Add(self.computation, (2 * y).computation))` which is equal to:
|
||||
`Tracer(computation=Add(Input("x"), Multiply(Constant(2), Input("y")))`
|
||||
`x + (2 * y)` will be performed next, and `+` is overloaded for `Tracer` to return another tracer: `Tracer(computation=Add(self.computation, (2 * y).computation))` which is equal to: `Tracer(computation=Add(Input("x"), Multiply(Constant(2), Input("y")))`
|
||||
|
||||
In the end, we will have output Tracers that can be used to create the computation graph.
|
||||
The implementation is a bit more complex than this, but the idea is the same.
|
||||
In the end, we will have output Tracers that can be used to create the computation graph. The implementation is a bit more complex than this, but the idea is the same.
|
||||
|
||||
Tracing is also responsible for indicating whether the values in the node would be encrypted or not, and the rule for that is if a node has an encrypted predecessor, it is encrypted as well.
|
||||
|
||||
@@ -100,15 +82,13 @@ Tracing is also responsible for indicating whether the values in the node would
|
||||
|
||||
The goal of topological transforms is to make more functions compilable.
|
||||
|
||||
With the current version of **Concrete Numpy**, floating point inputs and floating point outputs are not supported.
|
||||
However, if the floating points operations are intermediate operations, they can sometimes be fused into a single table lookup from integer to integer thanks to some specific transforms.
|
||||
With the current version of **Concrete Numpy**, floating point inputs and floating point outputs are not supported. However, if the floating points operations are intermediate operations, they can sometimes be fused into a single table lookup from integer to integer thanks to some specific transforms.
|
||||
|
||||
Let's take a closer look at the transforms we can currently perform.
|
||||
|
||||
### Fusing floating point operations
|
||||
|
||||
We have allocated a whole new chapter to explaining float fusing.
|
||||
You can find it [here](./float-fusing.md).
|
||||
We have allocated a whole new chapter to explaining float fusing. You can find it [here](float-fusing.md).
|
||||
|
||||
## Bounds measurement
|
||||
|
||||
@@ -126,16 +106,13 @@ Let's take a closer look at how we perform bounds measurement.
|
||||
|
||||
This is a simple approach that requires an inputset to be provided by the user.
|
||||
|
||||
The inputset is not to be confused with the dataset which is classical in ML, as it doesn't require labels.
|
||||
Rather, it is a set of values which are typical inputs of the function.
|
||||
The inputset is not to be confused with the dataset which is classical in ML, as it doesn't require labels. Rather, it is a set of values which are typical inputs of the function.
|
||||
|
||||
The idea is to evaluate each input in the inputset and record the result of each operation in the computation graph.
|
||||
Then we compare the evaluation results with the current minimum/maximum values of each node and update the minimum/maximum accordingly.
|
||||
After the entire inputset is evaluated, we assign a data type to each node using the minimum and the maximum value it contains.
|
||||
The idea is to evaluate each input in the inputset and record the result of each operation in the computation graph. Then we compare the evaluation results with the current minimum/maximum values of each node and update the minimum/maximum accordingly. After the entire inputset is evaluated, we assign a data type to each node using the minimum and the maximum value it contains.
|
||||
|
||||
Here is an example, given this computation graph where `x` is encrypted:
|
||||
|
||||

|
||||

|
||||
|
||||
and this inputset:
|
||||
|
||||
@@ -144,57 +121,64 @@ and this inputset:
|
||||
```
|
||||
|
||||
Evaluation Result of `2`:
|
||||
- `x`: 2
|
||||
- `2`: 2
|
||||
- `*`: 4
|
||||
- `3`: 3
|
||||
- `+`: 7
|
||||
|
||||
* `x`: 2
|
||||
* `2`: 2
|
||||
* `*`: 4
|
||||
* `3`: 3
|
||||
* `+`: 7
|
||||
|
||||
New Bounds:
|
||||
- `x`: [**2**, **2**]
|
||||
- `2`: [**2**, **2**]
|
||||
- `*`: [**4**, **4**]
|
||||
- `3`: [**3**, **3**]
|
||||
- `+`: [**7**, **7**]
|
||||
|
||||
* `x`: \[**2**, **2**]
|
||||
* `2`: \[**2**, **2**]
|
||||
* `*`: \[**4**, **4**]
|
||||
* `3`: \[**3**, **3**]
|
||||
* `+`: \[**7**, **7**]
|
||||
|
||||
Evaluation Result of `3`:
|
||||
- `x`: 3
|
||||
- `2`: 2
|
||||
- `*`: 6
|
||||
- `3`: 3
|
||||
- `+`: 9
|
||||
|
||||
* `x`: 3
|
||||
* `2`: 2
|
||||
* `*`: 6
|
||||
* `3`: 3
|
||||
* `+`: 9
|
||||
|
||||
New Bounds:
|
||||
- `x`: [2, **3**]
|
||||
- `2`: [2, 2]
|
||||
- `*`: [4, **6**]
|
||||
- `3`: [3, 3]
|
||||
- `+`: [7, **9**]
|
||||
|
||||
* `x`: \[2, **3**]
|
||||
* `2`: \[2, 2]
|
||||
* `*`: \[4, **6**]
|
||||
* `3`: \[3, 3]
|
||||
* `+`: \[7, **9**]
|
||||
|
||||
Evaluation Result of `1`:
|
||||
- `x`: 1
|
||||
- `2`: 2
|
||||
- `*`: 2
|
||||
- `3`: 3
|
||||
- `+`: 5
|
||||
|
||||
* `x`: 1
|
||||
* `2`: 2
|
||||
* `*`: 2
|
||||
* `3`: 3
|
||||
* `+`: 5
|
||||
|
||||
New Bounds:
|
||||
- `x`: [**1**, 3]
|
||||
- `2`: [2, 2]
|
||||
- `*`: [**2**, 6]
|
||||
- `3`: [3, 3]
|
||||
- `+`: [**5**, 9]
|
||||
|
||||
* `x`: \[**1**, 3]
|
||||
* `2`: \[2, 2]
|
||||
* `*`: \[**2**, 6]
|
||||
* `3`: \[3, 3]
|
||||
* `+`: \[**5**, 9]
|
||||
|
||||
Assigned Data Types:
|
||||
- `x`: Encrypted\<**uint2**>
|
||||
- `2`: Clear\<**uint2**>
|
||||
- `*`: Encrypted\<**uint3**>
|
||||
- `3`: Clear\<**uint2**>
|
||||
- `+`: Encrypted\<**uint4**>
|
||||
|
||||
* `x`: Encrypted<**uint2**>
|
||||
* `2`: Clear<**uint2**>
|
||||
* `*`: Encrypted<**uint3**>
|
||||
* `3`: Clear<**uint2**>
|
||||
* `+`: Encrypted<**uint4**>
|
||||
|
||||
## MLIR conversion
|
||||
|
||||
The actual compilation will be done by the **Concrete** compiler, which is expecting an MLIR input. The MLIR conversion goes from a computation graph to its MLIR equivalent. You can read more about it [here](./mlir.md)
|
||||
The actual compilation will be done by the **Concrete** compiler, which is expecting an MLIR input. The MLIR conversion goes from a computation graph to its MLIR equivalent. You can read more about it [here](mlir.md)
|
||||
|
||||
## Example walkthrough #1
|
||||
|
||||
@@ -213,7 +197,7 @@ x = "encrypted"
|
||||
|
||||
#### Corresponding computation graph
|
||||
|
||||

|
||||

|
||||
|
||||
### Topological transforms
|
||||
|
||||
@@ -221,14 +205,15 @@ x = "encrypted"
|
||||
|
||||
This transform isn't applied since the computation doesn't involve any floating point operations.
|
||||
|
||||
### Bounds measurement using [2, 3, 1] as inputset (same settings as above)
|
||||
### Bounds measurement using \[2, 3, 1] as inputset (same settings as above)
|
||||
|
||||
Data Types:
|
||||
- `x`: Encrypted\<**uint2**>
|
||||
- `2`: Clear\<**uint2**>
|
||||
- `*`: Encrypted\<**uint3**>
|
||||
- `3`: Clear\<**uint2**>
|
||||
- `+`: Encrypted\<**uint4**>
|
||||
|
||||
* `x`: Encrypted<**uint2**>
|
||||
* `2`: Clear<**uint2**>
|
||||
* `*`: Encrypted<**uint3**>
|
||||
* `3`: Clear<**uint2**>
|
||||
* `+`: Encrypted<**uint4**>
|
||||
|
||||
### MLIR lowering
|
||||
|
||||
@@ -244,7 +229,6 @@ module {
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
## Example walkthrough #2
|
||||
|
||||
### Function to homomorphize
|
||||
@@ -263,7 +247,7 @@ y = "encrypted"
|
||||
|
||||
#### Corresponding computation graph
|
||||
|
||||

|
||||

|
||||
|
||||
### Topological transforms
|
||||
|
||||
@@ -271,61 +255,67 @@ y = "encrypted"
|
||||
|
||||
This transform isn't applied since the computation doesn't involve any floating point operations.
|
||||
|
||||
### Bounds measurement using [(6, 0), (5, 1), (3, 0), (4, 1)] as inputset
|
||||
### Bounds measurement using \[(6, 0), (5, 1), (3, 0), (4, 1)] as inputset
|
||||
|
||||
Evaluation Result of `(6, 0)`:
|
||||
- `42`: 42
|
||||
- `x`: 6
|
||||
- `y`: 0
|
||||
- `2`: 2
|
||||
- `-`: 36
|
||||
- `*`: 0
|
||||
- `+`: 36
|
||||
|
||||
* `42`: 42
|
||||
* `x`: 6
|
||||
* `y`: 0
|
||||
* `2`: 2
|
||||
* `-`: 36
|
||||
* `*`: 0
|
||||
* `+`: 36
|
||||
|
||||
Evaluation Result of `(5, 1)`:
|
||||
- `42`: 42
|
||||
- `x`: 5
|
||||
- `y`: 1
|
||||
- `2`: 2
|
||||
- `-`: 37
|
||||
- `*`: 2
|
||||
- `+`: 39
|
||||
|
||||
* `42`: 42
|
||||
* `x`: 5
|
||||
* `y`: 1
|
||||
* `2`: 2
|
||||
* `-`: 37
|
||||
* `*`: 2
|
||||
* `+`: 39
|
||||
|
||||
Evaluation Result of `(3, 0)`:
|
||||
- `42`: 42
|
||||
- `x`: 3
|
||||
- `y`: 0
|
||||
- `2`: 2
|
||||
- `-`: 39
|
||||
- `*`: 0
|
||||
- `+`: 39
|
||||
|
||||
* `42`: 42
|
||||
* `x`: 3
|
||||
* `y`: 0
|
||||
* `2`: 2
|
||||
* `-`: 39
|
||||
* `*`: 0
|
||||
* `+`: 39
|
||||
|
||||
Evaluation Result of `(4, 1)`:
|
||||
- `42`: 42
|
||||
- `x`: 4
|
||||
- `y`: 1
|
||||
- `2`: 2
|
||||
- `-`: 38
|
||||
- `*`: 2
|
||||
- `+`: 40
|
||||
|
||||
* `42`: 42
|
||||
* `x`: 4
|
||||
* `y`: 1
|
||||
* `2`: 2
|
||||
* `-`: 38
|
||||
* `*`: 2
|
||||
* `+`: 40
|
||||
|
||||
Bounds:
|
||||
- `42`: [42, 42]
|
||||
- `x`: [3, 6]
|
||||
- `y`: [0, 1]
|
||||
- `2`: [2, 2]
|
||||
- `-`: [36, 39]
|
||||
- `*`: [0, 2]
|
||||
- `+`: [36, 40]
|
||||
|
||||
* `42`: \[42, 42]
|
||||
* `x`: \[3, 6]
|
||||
* `y`: \[0, 1]
|
||||
* `2`: \[2, 2]
|
||||
* `-`: \[36, 39]
|
||||
* `*`: \[0, 2]
|
||||
* `+`: \[36, 40]
|
||||
|
||||
Data Types:
|
||||
- `42`: Clear\<**uint6**>
|
||||
- `x`: Encrypted\<**uint3**>
|
||||
- `y`: Encrypted\<**uint1**>
|
||||
- `2`: Clear\<**uint2**>
|
||||
- `-`: Encrypted\<**uint6**>
|
||||
- `*`: Encrypted\<**uint2**>
|
||||
- `+`: Encrypted\<**uint6**>
|
||||
|
||||
* `42`: Clear<**uint6**>
|
||||
* `x`: Encrypted<**uint3**>
|
||||
* `y`: Encrypted<**uint1**>
|
||||
* `2`: Clear<**uint2**>
|
||||
* `-`: Encrypted<**uint6**>
|
||||
* `*`: Encrypted<**uint2**>
|
||||
* `+`: Encrypted<**uint6**>
|
||||
|
||||
### MLIR lowering
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
|
||||
# Contributing
|
||||
|
||||
```{important}
|
||||
{% hint style='info' %}
|
||||
There are two ways to contribute to **concrete-numpy** or to **Concrete** tools in general:
|
||||
- you can open issues to report bugs and typos and to suggest ideas
|
||||
- you can ask to become an official contributor by emailing hello@zama.ai. Only approved contributors can send pull requests, so please make sure to get in touch before you do!
|
||||
```
|
||||
{% endhint %}
|
||||
|
||||
Let's go over some other important things that you need to be careful about.
|
||||
|
||||
@@ -70,9 +70,9 @@ To learn more about conventional commits, check [this](https://www.conventionalc
|
||||
|
||||
## Before creating pull request
|
||||
|
||||
```{important}
|
||||
{% hint style='tip' %}
|
||||
We remind that only official contributors can send pull requests. To become such an official contributor, please email hello@zama.ai.
|
||||
```
|
||||
{% endhint %}
|
||||
|
||||
You should rebase on top of `main` branch before you create your pull request. We don't allow merge commits, so rebasing on `main` before pushing gives you the best chance of avoiding having to rewrite parts of your PR later if some conflicts arise with other PRs being merged. After you commit your changes to your new branch, you can use the following commands to rebase:
|
||||
|
||||
@@ -1,10 +0,0 @@
|
||||
Explanations
|
||||
============
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 1
|
||||
|
||||
compilation.md
|
||||
terminology_and_structure.md
|
||||
float-fusing.md
|
||||
mlir.md
|
||||
@@ -1,3 +0,0 @@
|
||||
# MLIR
|
||||
|
||||
TODO
|
||||
@@ -25,15 +25,15 @@ Any computation where there is a single variable integer input and a single inte
|
||||
|
||||
The `quantized_sin` graph of operations:
|
||||
|
||||

|
||||

|
||||
|
||||
The float subgraph that was detected:
|
||||
|
||||

|
||||

|
||||
|
||||
The simplified graph of operations with the float subgraph condensed in a `GenericFunction` node:
|
||||
|
||||

|
||||

|
||||
|
||||
## How is it done in **Concrete Numpy**?
|
||||
|
||||
@@ -59,15 +59,15 @@ def fusable_with_bigger_search(x, y):
|
||||
|
||||
The `fusable_with_bigger_search` graph of operations:
|
||||
|
||||

|
||||

|
||||
|
||||
The float subgraph that was detected:
|
||||
|
||||

|
||||

|
||||
|
||||
The simplified graph of operations with the float subgraph condensed in a `GenericFunction` node:
|
||||
|
||||

|
||||

|
||||
|
||||
An example of a non fusable computation with that technique is:
|
||||
|
||||
@@ -83,4 +83,4 @@ def non_fusable(x, y):
|
||||
return add_int
|
||||
```
|
||||
|
||||
From `add_int` you will find two `Add` nodes going from int to float (`x_1` and `y_1`) which we cannot represent with a single input table look-up. Kolmogorov–Arnold representation theorem states that every multivariate continuous function can be represented as a superposition of continuous functions of one variable ([from Wikipedia](https://en.wikipedia.org/wiki/Kolmogorov%E2%80%93Arnold_representation_theorem)), so the above case could be handled in future versions of **Concrete** tools.
|
||||
From `add_int` you will find two `Add` nodes going from int to float (`x_1` and `y_1`) which we cannot represent with a single input table look-up. Kolmogorov–Arnold representation theorem states that every multivariate continuous function can be represented as a superposition of continuous functions of one variable ([from Wikipedia](https://en.wikipedia.org/wiki/Kolmogorov%E2%80%93Arnold\_representation\_theorem)), so the above case could be handled in future versions of **Concrete** tools.
|
||||
@@ -1,27 +0,0 @@
|
||||
|
||||
# Documenting
|
||||
|
||||
## Using Sphinx
|
||||
|
||||
One can simply create docs with Sphinx and open them, by doing:
|
||||
|
||||
```shell
|
||||
make docs
|
||||
```
|
||||
|
||||
Reminder that this needs to be done in docker.
|
||||
|
||||
The documentation contains both files written by hand by developers (the .md files) and files automatically created by parsing the source files.
|
||||
|
||||
### Opening doc
|
||||
|
||||
On macOS, you can do
|
||||
|
||||
```shell
|
||||
make open_docs
|
||||
```
|
||||
|
||||
On other systems, simply open `docs/_build/html/index.html`
|
||||
|
||||
|
||||
|
||||
@@ -1,11 +0,0 @@
|
||||
How To
|
||||
======
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 1
|
||||
|
||||
project_setup.md
|
||||
docker.md
|
||||
documenting.md
|
||||
releasing.md
|
||||
contributing.md
|
||||
@@ -1,9 +0,0 @@
|
||||
Developer Guide
|
||||
===============
|
||||
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 2
|
||||
|
||||
How To <howto/index>
|
||||
Explanations <explanation/index>
|
||||
17
docs/dev/mlir.md
Normal file
17
docs/dev/mlir.md
Normal file
@@ -0,0 +1,17 @@
|
||||
# MLIR
|
||||
|
||||
The MLIR project is a sub-project of the LLVM project. It's designed to simplify building domain-specific compilers such as ours: Concrete Compiler.
|
||||
|
||||
Concrete Compiler accepts MLIR as input and emits compiled assembly code for the target architecture.
|
||||
|
||||
Concrete NumPy does the MLIR generation from the computation graph. Code related to this conversion is in `concrete/numpy/mlir` folder.
|
||||
|
||||
The conversion can be performed using `convert` method of `GraphConverter` class.
|
||||
|
||||
Within `convert` method of `GraphConverter`:
|
||||
|
||||
* MLIR compatibility of the graph is checked
|
||||
* Bit-width constraints are checked
|
||||
* Negative lookup tables are offsetted
|
||||
* Computation graph is traversed and each node is converted to their corresponding MLIR representation using `NodeConverter` class
|
||||
* String representation of resulting MLIR is returned
|
||||
@@ -1,10 +1,10 @@
|
||||
# Project Setup
|
||||
|
||||
```{note}
|
||||
{% hint style='info' %}
|
||||
It is strongly recommended to use the development docker (see the [docker](./docker.md) guide). However you can setup the project on bare macOS and Linux provided you install the required dependencies (check Dockerfile.env for the required binary packages like make).
|
||||
|
||||
The project targets Python 3.8 through 3.9 inclusive.
|
||||
```
|
||||
{% endhint %}
|
||||
|
||||
## Installing Python
|
||||
|
||||
@@ -18,11 +18,11 @@ You can follow [this](https://realpython.com/installing-python/) guide to instal
|
||||
|
||||
You can follow [this](https://python-poetry.org/docs/#installation) official guide to install it.
|
||||
|
||||
```{WARNING}
|
||||
{% hint style='danger' %}
|
||||
As there is no `concrete-compiler` package for Windows, only the dev dependencies can be installed. This requires poetry >= 1.2.
|
||||
|
||||
At the time of writing (January 2022), there is only an alpha version of poetry 1.2 that you can install. In the meantime we recommend following [this link to setup the docker environment](./docker.md) on Windows.
|
||||
```
|
||||
{% endhint %}
|
||||
|
||||
## Installing make
|
||||
|
||||
@@ -45,9 +45,9 @@ It is possible to install `gmake` as `make`, check this [StackOverflow post](htt
|
||||
|
||||
On Windows check [this GitHub gist](https://gist.github.com/evanwill/0207876c3243bbb6863e65ec5dc3f058#make).
|
||||
|
||||
```{hint}
|
||||
{% hint style='tip' %}
|
||||
In the following sections, be sure to use the proper `make` tool for your system: `make`, `gmake`, or other.
|
||||
```
|
||||
{% endhint %}
|
||||
|
||||
## Cloning repository
|
||||
|
||||
@@ -59,9 +59,9 @@ Clone the code repository using the link for your favourite communication protoc
|
||||
|
||||
We are going to make use of virtual environments. This helps to keep the project isolated from other `Python` projects in the system. The following commands will create a new virtual environment under the project directory and install dependencies to it.
|
||||
|
||||
```{DANGER}
|
||||
{% hint style='danger' %}
|
||||
The following command will not work on Windows if you don't have poetry >= 1.2. As poetry 1.2 is still in alpha we recommend following [this link to setup the docker environment](./docker.md) instead.
|
||||
```
|
||||
{% endhint %}
|
||||
|
||||
```shell
|
||||
cd concrete-numpy
|
||||
Reference in New Issue
Block a user