From ce48a757c632c2593a610effe73a3b4bb18815ac Mon Sep 17 00:00:00 2001 From: Umut Date: Mon, 13 Dec 2021 15:50:22 +0300 Subject: [PATCH] feat: create a method in the new interface to compile using an inputset in one go --- concrete/numpy/np_fhe_compiler.py | 20 +++++++++++++++++++ concrete/quantization/quantized_module.py | 6 +++--- docs/dev/explanation/compilation.md | 4 ++-- docs/user/basics/compiling_and_executing.md | 3 +++ docs/user/howto/reduce_needed_precision.md | 3 +-- docs/user/tutorial/compilation_artifacts.md | 2 +- docs/user/tutorial/indexing.md | 12 ++++------- .../tutorial/working_with_floating_points.md | 4 +--- 8 files changed, 35 insertions(+), 19 deletions(-) diff --git a/concrete/numpy/np_fhe_compiler.py b/concrete/numpy/np_fhe_compiler.py index cafe12d32..737fa1b5e 100644 --- a/concrete/numpy/np_fhe_compiler.py +++ b/concrete/numpy/np_fhe_compiler.py @@ -249,6 +249,26 @@ class NPFHECompiler: dtype.bit_width = 128 dtype.is_signed = True + def compile_on_inputset( + self, + inputset: Union[Iterable[Any], Iterable[Tuple[Any, ...]]], + show_mlir: bool = False, + ) -> FHECircuit: + """Compile the function on an inputset and get resulting FHECircuit. + + Args: + inputset (Union[Iterable[Any], Iterable[Tuple[Any, ...]]]): + The inputset on which the function is evaluated. + show_mlir (bool, optional, defaults to False): + The flag to enable printing the MLIR that is being compiled for debugging purposes. + + Returns: + FHECircuit: the compiled FHECircuit + """ + + self.eval_on_inputset(inputset) + return self.get_compiled_fhe_circuit(show_mlir) + def get_compiled_fhe_circuit(self, show_mlir: bool = False) -> FHECircuit: """Return a compiled FHECircuit if the instance was evaluated on an inputset. diff --git a/concrete/quantization/quantized_module.py b/concrete/quantization/quantized_module.py index a6210034f..9670c5983 100644 --- a/concrete/quantization/quantized_module.py +++ b/concrete/quantization/quantized_module.py @@ -121,8 +121,8 @@ class QuantizedModule: compilation_configuration, compilation_artifacts, ) - compiler.eval_on_inputset((numpy.expand_dims(arr, 0) for arr in self.q_input.qvalues)) - - self.forward_fhe = compiler.get_compiled_fhe_circuit(show_mlir) + self.forward_fhe = compiler.compile_on_inputset( + (numpy.expand_dims(arr, 0) for arr in self.q_input.qvalues), show_mlir + ) return self.forward_fhe diff --git a/docs/dev/explanation/compilation.md b/docs/dev/explanation/compilation.md index cc583b572..0d3dbdda8 100644 --- a/docs/dev/explanation/compilation.md +++ b/docs/dev/explanation/compilation.md @@ -21,8 +21,8 @@ def f(x, y): compiler = hnp.NPFHECompiler(f, {"x": "encrypted", "y": "encrypted"}) # Compile an FHE Circuit using an inputset -compiler.eval_on_inputset([(0, 0), (0, 1), (1, 0), (1, 1), (2, 0), (2, 1), (3, 0), (3, 1)]) -circuit = compiler.get_compiled_fhe_circuit() +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) diff --git a/docs/user/basics/compiling_and_executing.md b/docs/user/basics/compiling_and_executing.md index 9002ca63e..ca1624679 100644 --- a/docs/user/basics/compiling_and_executing.md +++ b/docs/user/basics/compiling_and_executing.md @@ -44,6 +44,9 @@ Finally, we can compile our function to its homomorphic equivalent. compiler = hnp.NPFHECompiler( f, {"x": x, "y": y}, ) +circuit = compiler.compile_on_inputset(inputset) + +# If you want, you can separate tracing and compilation steps like so: # You can either evaluate in one go: compiler.eval_on_inputset(inputset) diff --git a/docs/user/howto/reduce_needed_precision.md b/docs/user/howto/reduce_needed_precision.md index 6d84881ca..7ccdff84b 100644 --- a/docs/user/howto/reduce_needed_precision.md +++ b/docs/user/howto/reduce_needed_precision.md @@ -15,8 +15,7 @@ def f(x): return 42 * x compiler = hnp.NPFHECompiler(f, {"x": "encrypted"}) -compiler.eval_on_inputset(range(2 ** 3)) -compiler.get_compiled_fhe_circuit() +circuit = compiler.compile_on_inputset(range(2 ** 3)) ``` results in diff --git a/docs/user/tutorial/compilation_artifacts.md b/docs/user/tutorial/compilation_artifacts.md index 3250958ed..1e76ffb44 100644 --- a/docs/user/tutorial/compilation_artifacts.md +++ b/docs/user/tutorial/compilation_artifacts.md @@ -125,7 +125,7 @@ def f(x): artifacts = hnp.CompilationArtifacts(pathlib.Path("/tmp/custom/export/path")) compiler = hnp.NPFHECompiler(f, {"x": "encrypted"}, compilation_artifacts=artifacts) -compiler.eval_on_inputset(range(2 ** 3)) +compiler.compile_on_inputset(range(2 ** 3)) artifacts.export() ``` diff --git a/docs/user/tutorial/indexing.md b/docs/user/tutorial/indexing.md index 9dc2695d2..42c4e8bf2 100644 --- a/docs/user/tutorial/indexing.md +++ b/docs/user/tutorial/indexing.md @@ -18,8 +18,7 @@ def f(x): inputset = [np.random.randint(0, 2 ** 3, size=(3,), dtype=np.uint8) for _ in range(10)] compiler = hnp.NPFHECompiler(f, {"x": "encrypted"}) -compiler.eval_on_inputset(inputset) -circuit = compiler.get_compiled_fhe_circuit() +circuit = compiler.compile_on_inputset(inputset) test_input = np.array([4, 2, 6], dtype=np.uint8) expected_output = 2 @@ -39,8 +38,7 @@ def f(x): inputset = [np.random.randint(0, 2 ** 3, size=(3,), dtype=np.uint8) for _ in range(10)] compiler = hnp.NPFHECompiler(f, {"x": "encrypted"}) -compiler.eval_on_inputset(inputset) -circuit = compiler.get_compiled_fhe_circuit() +circuit = compiler.compile_on_inputset(inputset) test_input = np.array([4, 2, 6], dtype=np.uint8) expected_output = 6 @@ -60,8 +58,7 @@ def f(x): inputset = [np.random.randint(0, 2 ** 3, size=(3, 2), dtype=np.uint8) for _ in range(10)] compiler = hnp.NPFHECompiler(f, {"x": "encrypted"}) -compiler.eval_on_inputset(inputset) -circuit = compiler.get_compiled_fhe_circuit() +circuit = compiler.compile_on_inputset(inputset) test_input = np.array([[4, 2], [1, 5], [7, 6]], dtype=np.uint8) expected_output = 6 @@ -81,8 +78,7 @@ def f(x): inputset = [np.random.randint(0, 2 ** 3, size=(5,), dtype=np.uint8) for _ in range(10)] compiler = hnp.NPFHECompiler(f, {"x": "encrypted"}) -compiler.eval_on_inputset(inputset) -circuit = compiler.get_compiled_fhe_circuit() +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) diff --git a/docs/user/tutorial/working_with_floating_points.md b/docs/user/tutorial/working_with_floating_points.md index 757bae628..fcaf2c050 100644 --- a/docs/user/tutorial/working_with_floating_points.md +++ b/docs/user/tutorial/working_with_floating_points.md @@ -13,9 +13,7 @@ def f(x): # Compiling with x encrypted compiler = hnp.NPFHECompiler(f, {"x": "encrypted"}) -compiler.eval_on_inputset(range(64)) - -circuit = compiler.get_compiled_fhe_circuit() +circuit = compiler.compile_on_inputset(range(64)) assert circuit.run(3) == f(3) assert circuit.run(0) == f(0)