feat(fhe_circuit): create FHECircuit class to combine operation graph and compiler engine

This commit is contained in:
Umut
2021-10-04 12:05:20 +03:00
parent 6fc6991839
commit 003bad581a
11 changed files with 239 additions and 137 deletions

View File

@@ -22,13 +22,13 @@ x = hnp.EncryptedScalar(hnp.UnsignedInteger(2))
y = hnp.EncryptedScalar(hnp.UnsignedInteger(1))
# Compile the function to its homomorphic equivalent
engine = hnp.compile_numpy_function(
circuit = hnp.compile_numpy_function(
f, {"x": x, "y": y},
[(0, 0), (0, 1), (1, 0), (1, 1), (2, 0), (2, 1), (3, 0), (3, 1)],
)
# Make homomorphic inference
engine.run(1, 0)
circuit.run(1, 0)
```
## Overview

View File

@@ -12,6 +12,10 @@ In this section we will go over some terms that we use throughout the project.
- bounds
- before intermediate representation is sent to the compiler, we need to know which node will output which type (e.g., uint3 vs uint5)
- there are several ways to do this but the simplest one is to evaluate the intermediate representation with all combinations of inputs and remember the maximum and the minimum values for each node, which is what we call bounds, and bounds can be used to determine the appropriate type for each node
- fhe circuit
- it is the result of compilation
- it contains the operation graph and the compiler engine in it
- it has methods for printing, visualizing, and evaluating
## Module structure

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -41,7 +41,7 @@ Finally, we can compile our function to its homomorphic equivalent.
<!--python-test:cont-->
```python
engine = hnp.compile_numpy_function(
circuit = hnp.compile_numpy_function(
f, {"x": x, "y": y},
inputset=inputset,
)
@@ -49,17 +49,17 @@ engine = hnp.compile_numpy_function(
## Performing homomorphic evaluation
You can use `.run(...)` method of `engine` returned by `hnp.compile_numpy_function(...)` to perform fully homomorphic evaluation. Here are some examples:
You can use `.run(...)` method of `FHECircuit` returned by `hnp.compile_numpy_function(...)` to perform fully homomorphic evaluation. Here are some examples:
<!--python-test:cont-->
```python
engine.run(3, 4)
circuit.run(3, 4)
# 7
engine.run(1, 2)
circuit.run(1, 2)
# 3
engine.run(7, 7)
circuit.run(7, 7)
# 14
engine.run(0, 0)
circuit.run(0, 0)
# 0
```

View File

@@ -28,8 +28,8 @@ results in
<!--python-test:skip-->
```python
engine.run(3) == 45
engine.run(0) == 42
circuit.run(3) == 45
circuit.run(0) == 42
```
### Dynamic ClearScalar and EncryptedScalar
@@ -52,8 +52,8 @@ results in
<!--python-test:skip-->
```python
engine.run(6, 4) == 10
engine.run(1, 1) == 2
circuit.run(6, 4) == 10
circuit.run(1, 1) == 2
```
where
@@ -78,8 +78,8 @@ results in
<!--python-test:skip-->
```python
engine.run(7, 7) == 14
engine.run(3, 4) == 7
circuit.run(7, 7) == 14
circuit.run(3, 4) == 7
```
## Subtraction
@@ -100,8 +100,8 @@ results in
<!--python-test:skip-->
```python
engine.run(2) == 1
engine.run(3) == 0
circuit.run(2) == 1
circuit.run(3) == 0
```
### Dynamic ClearScalar and EncryptedScalar
@@ -121,8 +121,8 @@ results in
<!--python-test:skip-->
```python
engine.run(2, 4) == 2
engine.run(1, 7) == 6
circuit.run(2, 4) == 2
circuit.run(1, 7) == 6
```
## Multiplication
@@ -151,8 +151,8 @@ results in
<!--python-test:skip-->
```python
engine.run(2) == 4
engine.run(5) == 10
circuit.run(2) == 4
circuit.run(5) == 10
```
### Dynamic ClearScalar and EncryptedScalar
@@ -180,8 +180,8 @@ results in
<!--python-test:skip-->
```python
engine.run(2, 3) == 6
engine.run(1, 7) == 7
circuit.run(2, 3) == 6
circuit.run(1, 7) == 7
```
## Dot Product
@@ -211,8 +211,8 @@ results in
<!--python-test:skip-->
```python
engine.run([1, 1], [2, 3]) == 5
engine.run([2, 3], [2, 3]) == 13
circuit.run([1, 1], [2, 3]) == 5
circuit.run([2, 3], [2, 3]) == 13
```
## Combining all together
@@ -233,6 +233,6 @@ results in
<!--python-test:skip-->
```python
engine.run([1, 2], [4, 3], 10) == 60
engine.run([2, 3], [3, 2], 5) == 66
circuit.run([1, 2], [4, 3], 10) == 60
circuit.run([2, 3], [3, 2], 5) == 66
```

View File

@@ -23,10 +23,10 @@ results in
<!--python-test:skip-->
```python
engine.run(0) == 2
engine.run(1) == 1
engine.run(2) == 3
engine.run(3) == 0
circuit.run(0) == 2
circuit.run(1) == 1
circuit.run(2) == 3
circuit.run(3) == 0
```
## Fused table lookup
@@ -49,14 +49,14 @@ results in
<!--python-test:skip-->
```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
circuit.run(0) == 77
circuit.run(1) == 35
circuit.run(2) == 32
circuit.run(3) == 70
circuit.run(4) == 115
circuit.run(5) == 125
circuit.run(6) == 91
circuit.run(7) == 45
```
Initially, the function is converted to this operation graph

View File

@@ -16,11 +16,11 @@ results in
<!--python-test:skip-->
```python
engine.run(3) == 27
engine.run(0) == 0
engine.run(1) == 90
engine.run(10) == 91
engine.run(60) == 58
circuit.run(3) == 27
circuit.run(0) == 0
circuit.run(1) == 90
circuit.run(10) == 91
circuit.run(60) == 58
```
## Supported operations