docs: update doc to the new API

This commit is contained in:
youben11
2022-04-06 07:06:55 +01:00
committed by Umut
parent 2e831e4415
commit 28a4d2301c
6 changed files with 44 additions and 35 deletions

View File

@@ -25,7 +25,7 @@ inputset = [(0, 0), (0, 1), (1, 0), (1, 1), (2, 0), (2, 1), (3, 0), (3, 1)]
circuit = compiler.compile_on_inputset(inputset)
# Make homomorphic inference
circuit.run(1, 0)
circuit.encrypt_run_decrypt(1, 0)
```
## Overview of the numpy compilation process

View File

@@ -78,17 +78,17 @@ Here is the graph from the previous code block drawn with `draw_graph`:
## Performing homomorphic evaluation
You can use `.run(...)` method of `FHECircuit` returned by `hnp.compile_numpy_function(...)` to perform fully homomorphic evaluation. Here are some examples:
You can use `.encrypt_run_decrypt(...)` method of `FHECircuit` returned by `hnp.compile_numpy_function(...)` to perform fully homomorphic evaluation. Here are some examples:
<!--pytest-codeblocks:cont-->
```python
circuit.run(3, 4)
circuit.encrypt_run_decrypt(3, 4)
# 7
circuit.run(1, 2)
circuit.encrypt_run_decrypt(1, 2)
# 3
circuit.run(7, 7)
circuit.encrypt_run_decrypt(7, 7)
# 14
circuit.run(0, 0)
circuit.encrypt_run_decrypt(0, 0)
# 0
```
@@ -97,11 +97,20 @@ Be careful about the inputs, though.
If you were to run with values outside the range of the inputset, the result might not be correct.
```
Today, we cannot simulate a client / server API in python, but it is for very soon. Then, we will have:
- a `keygen` API, which is used to generate both public and private keys
- an `encrypt` API, which happens on the user's device, and is using private keys
- a `run_inference` API, which happens on the untrusted server and only uses public material
- a `encrypt` API, which happens on the user's device to get final clear result, and is using private keys
While `.encrypt_run_decrypt(...)` is a good start for prototyping examples, more advanced usages require control over the different steps that are happening behind the scene, mainly key generation, encryption, execution, and decryption. The different steps can of course be called separately as in the example below:
<!--pytest-codeblocks:cont-->
```python
# generate keys required for encrypted computation
circuit.keygen()
# this will encrypt arguments that require encryption and pack all arguments
# as well as public materials (public keys)
public_args = circuit.encrypt(3, 4)
# this will run the encrypted computation using public materials and inputs provided
encrypted_result = circuit.run(public_args)
# the execution returns the encrypted result which can later be decrypted
decrypted_result = circuit.decrypt(encrypted_result)
```
## Further reading

View File

@@ -23,7 +23,7 @@ circuit = compiler.compile_on_inputset(inputset)
test_input = np.array([4, 2, 6], dtype=np.uint8)
expected_output = 2
assert np.array_equal(circuit.run(test_input), expected_output)
assert np.array_equal(circuit.encrypt_run_decrypt(test_input), expected_output)
```
You can use negative indexing.
@@ -43,7 +43,7 @@ circuit = compiler.compile_on_inputset(inputset)
test_input = np.array([4, 2, 6], dtype=np.uint8)
expected_output = 6
assert np.array_equal(circuit.run(test_input), expected_output)
assert np.array_equal(circuit.encrypt_run_decrypt(test_input), expected_output)
```
You can use multidimensional indexing as well.
@@ -63,7 +63,7 @@ circuit = compiler.compile_on_inputset(inputset)
test_input = np.array([[4, 2], [1, 5], [7, 6]], dtype=np.uint8)
expected_output = 6
assert np.array_equal(circuit.run(test_input), expected_output)
assert np.array_equal(circuit.encrypt_run_decrypt(test_input), expected_output)
```
### Extracting a slice
@@ -83,7 +83,7 @@ circuit = compiler.compile_on_inputset(inputset)
test_input = np.array([4, 2, 6, 1, 7], dtype=np.uint8)
expected_output = np.array([2, 6, 1], dtype=np.uint8)
assert np.array_equal(circuit.run(test_input), expected_output)
assert np.array_equal(circuit.encrypt_run_decrypt(test_input), expected_output)
```
You can use multidimensional slicing as well.

View File

@@ -23,10 +23,10 @@ results in
<!--pytest-codeblocks:skip-->
```python
circuit.run(0) == 2
circuit.run(1) == 1
circuit.run(2) == 3
circuit.run(3) == 0
circuit.encrypt_run_decrypt(0) == 2
circuit.encrypt_run_decrypt(1) == 1
circuit.encrypt_run_decrypt(2) == 3
circuit.encrypt_run_decrypt(3) == 0
```
Moreover, direct lookup tables can be used with tensors where the same table lookup is applied to each value in the tensor, so
@@ -38,7 +38,7 @@ results in
<!--pytest-codeblocks:skip-->
```python
input = np.array([[0, 1, 3], [2, 3, 1]], dtype=np.uint8)
circuit.run(input) == [[2, 1, 0], [3, 0, 1]]
circuit.encrypt_run_decrypt(input) == [[2, 1, 0], [3, 0, 1]]
```
## Direct Multi Table Lookup
@@ -71,7 +71,7 @@ results in
<!--pytest-codeblocks:skip-->
```python
input = np.array([[2, 3], [1, 2], [3, 0]], dtype=np.uint8)
circuit.run(input) == [[4, 27], [1, 8], [9, 0]]
circuit.encrypt_run_decrypt(input) == [[4, 27], [1, 8], [9, 0]]
```
Basically, we applied `squared` table to the first column and `cubed` to the second one.
@@ -96,14 +96,14 @@ results in
<!--pytest-codeblocks:skip-->
```python
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
circuit.encrypt_run_decrypt(0) == 77
circuit.encrypt_run_decrypt(1) == 35
circuit.encrypt_run_decrypt(2) == 32
circuit.encrypt_run_decrypt(3) == 70
circuit.encrypt_run_decrypt(4) == 115
circuit.encrypt_run_decrypt(5) == 125
circuit.encrypt_run_decrypt(6) == 91
circuit.encrypt_run_decrypt(7) == 45
```
Initially, the function is converted to this operation graph

View File

@@ -540,7 +540,7 @@
" \n",
" # We setup an example tensor that will be encrypted and passed on to the current operation\n",
" sample = np.random.randint(3, 11, size=(3, 2), dtype=np.uint8)\n",
" result = circuit.run(sample)\n",
" result = circuit.encrypt_run_decrypt(sample)\n",
" \n",
" print(\"#######################################################################################\")\n",
" print()\n",

View File

@@ -15,11 +15,11 @@ def f(x):
compiler = hnp.NPFHECompiler(f, {"x": "encrypted"})
circuit = compiler.compile_on_inputset(range(64))
print(circuit.run(3) == f(3))
print(circuit.run(0) == f(0))
print(circuit.run(1) == f(1))
print(circuit.run(10) == f(10))
print(circuit.run(60) == f(60))
print(circuit.encrypt_run_decrypt(3) == f(3))
print(circuit.encrypt_run_decrypt(0) == f(0))
print(circuit.encrypt_run_decrypt(1) == f(1))
print(circuit.encrypt_run_decrypt(10) == f(10))
print(circuit.encrypt_run_decrypt(60) == f(60))
print("All good!")
```