diff --git a/benchmarks/unit.py b/benchmarks/unit.py index 880afe479..432c60395 100644 --- a/benchmarks/unit.py +++ b/benchmarks/unit.py @@ -1540,7 +1540,7 @@ def main(function, inputs, accuracy_alert_threshold): correct = 0 for sample_i, expectation_i in zip(samples, expectations): with progress.measure(id="evaluation-time-ms", label="Evaluation Time (ms)"): - result_i = circuit.run(*sample_i) + result_i = circuit.encrypt_run_decrypt(*sample_i) np_result_i = np.array(result_i, dtype=np.uint8) np_expectation_i = np.array(expectation_i, dtype=np.uint8) diff --git a/concrete/common/compilation/configuration.py b/concrete/common/compilation/configuration.py index 830bad6d1..79d64a665 100644 --- a/concrete/common/compilation/configuration.py +++ b/concrete/common/compilation/configuration.py @@ -11,7 +11,11 @@ class CompilationConfiguration: enable_unsafe_features: bool random_inputset_samples: int use_insecure_key_cache: bool + auto_parallelize: bool + loop_parallelize: bool + dataflow_parallelize: bool + # pylint: disable=too-many-arguments def __init__( self, dump_artifacts_on_unexpected_failures: bool = True, @@ -21,6 +25,9 @@ class CompilationConfiguration: enable_unsafe_features: bool = False, random_inputset_samples: int = 30, use_insecure_key_cache: bool = False, + auto_parallelize: bool = False, + loop_parallelize: bool = True, + dataflow_parallelize: bool = False, ): self.dump_artifacts_on_unexpected_failures = dump_artifacts_on_unexpected_failures self.enable_topological_optimizations = enable_topological_optimizations @@ -29,6 +36,11 @@ class CompilationConfiguration: self.enable_unsafe_features = enable_unsafe_features self.random_inputset_samples = random_inputset_samples self.use_insecure_key_cache = use_insecure_key_cache + self.auto_parallelize = auto_parallelize + self.loop_parallelize = loop_parallelize + self.dataflow_parallelize = dataflow_parallelize + + # pylint: enable=too-many-arguments def __eq__(self, other) -> bool: return isinstance(other, CompilationConfiguration) and self.__dict__ == other.__dict__ diff --git a/concrete/common/fhe_circuit.py b/concrete/common/fhe_circuit.py index f1d10e35d..ae9c73964 100644 --- a/concrete/common/fhe_circuit.py +++ b/concrete/common/fhe_circuit.py @@ -1,10 +1,21 @@ """Module to hold the result of compilation.""" from pathlib import Path -from typing import List, Optional, Union +from typing import Optional, Union import numpy -from concrete.compiler import CompilerEngine +from concrete.compiler import ( + ClientParameters, + ClientSupport, + CompilationOptions, + JITCompilationResult, + JITLambda, + JITSupport, + KeySet, + KeySetCache, + PublicArguments, + PublicResult, +) from .debugging import draw_graph, format_operation_graph from .operator_graph import OPGraph @@ -14,11 +25,38 @@ class FHECircuit: """Class which is the result of compilation.""" op_graph: OPGraph - engine: CompilerEngine + _jit_support: JITSupport + _compilation_result: JITCompilationResult + _client_parameters: ClientParameters + _server_lambda: JITLambda + _keyset_cache: KeySetCache + _keyset: KeySet - def __init__(self, op_graph: OPGraph, engine: CompilerEngine): + def __init__( + self, + op_graph: OPGraph, + mlir_str: str, + unsecure_key_set_cache_path: Optional[str] = None, + auto_parallelize: bool = False, + loop_parallelize: bool = False, + dataflow_parallelize: bool = False, + ): self.op_graph = op_graph - self.engine = engine + self._jit_support = JITSupport.new() + # Set compilation options + options = CompilationOptions.new("main") + options.set_auto_parallelize(auto_parallelize) + options.set_loop_parallelize(loop_parallelize) + options.set_dataflow_parallelize(dataflow_parallelize) + # Compile + self._compilation_result = self._jit_support.compile(mlir_str, options) + self._client_parameters = self._jit_support.load_client_parameters(self._compilation_result) + self._server_lambda = self._jit_support.load_server_lambda(self._compilation_result) + # Setup keyset cache + self._keyset_cache = None + if unsecure_key_set_cache_path: + self._keyset_cache = KeySetCache.new(unsecure_key_set_cache_path) + self._keyset = None def __str__(self): return format_operation_graph(self.op_graph) @@ -44,15 +82,63 @@ class FHECircuit: return draw_graph(self.op_graph, show, vertical, save_to) - def run(self, *args: List[Union[int, numpy.ndarray]]) -> Union[int, numpy.ndarray]: - """Encrypt, evaluate, and decrypt the inputs on the circuit. + def keygen(self, force: bool = False): + """Generate the keys required for the encrypted circuit. Args: - *args (List[Union[int, numpy.ndarray]]): inputs to the circuit + force (bool, optional): generate even if keyset already exists. Defaults to False. + """ + if self._keyset is None or force: + self._keyset = ClientSupport.key_set(self._client_parameters, self._keyset_cache) + + def encrypt(self, *args: Union[int, numpy.ndarray]) -> PublicArguments: + """Encrypt the inputs of the circuit. + + Args: + *args (Union[int, numpy.ndarray]): plain input of the circuit Returns: - Union[int, numpy.ndarray]: homomorphic evaluation result - + PublicArguments: encrypted and plain arguments as well as public keys """ + # Make sure keys are available: shouldn't regenerate if they already exist + self.keygen(force=False) + return ClientSupport.encrypt_arguments(self._client_parameters, self._keyset, args) - return self.engine.run(*args) + def run(self, args: PublicArguments) -> PublicResult: + """Evaluate the the encrypted circuit (no encryption or decryption involved). + + Args: + args (PublicArguments): encrypted inputs to the circuit + + Returns: + PublicResult: encrypted result + """ + return self._jit_support.server_call(self._server_lambda, args) + + def decrypt(self, result: PublicResult) -> Union[int, numpy.ndarray]: + """Decrypt the result of the circuit. + + Args: + result (PublicResult): encrypted result of the circuit + + Returns: + Union[int, numpy.ndarray]: plain result of the circuit + """ + return ClientSupport.decrypt_result(self._keyset, result) + + def encrypt_run_decrypt(self, *args: Union[int, numpy.ndarray]) -> Union[int, numpy.ndarray]: + """Encrypt, evaluate, and decrypt the inputs on the circuit. + + Generate keyset automatically if not yet done. + + Args: + *args (Union[int, numpy.ndarray]): plain inputs of the circuit + + Returns: + Union[int, numpy.ndarray]: plain result of the circuit + """ + self.keygen(force=False) + public_args = self.encrypt(*args) + encrypted_result = self.run(public_args) + decrypted_result = self.decrypt(encrypted_result) + return decrypted_result diff --git a/concrete/numpy/compile.py b/concrete/numpy/compile.py index f10e2ff24..444738420 100644 --- a/concrete/numpy/compile.py +++ b/concrete/numpy/compile.py @@ -6,7 +6,6 @@ from copy import deepcopy from typing import Any, Callable, Dict, Iterable, Optional, Tuple, Union, cast import numpy -from concrete.compiler import CompilerEngine from ..common.bounds_measurement.inputset_eval import eval_op_graph_bounds_on_inputset from ..common.common_helpers import check_op_graph_is_integer_program @@ -653,11 +652,14 @@ def _compile_op_graph_to_fhe_circuit_internal( "compilation_configuration" ) - # Compile the MLIR representation - engine = CompilerEngine() - engine.compile_fhe(mlir_result, unsecure_key_set_cache_path=_COMPILE_FHE_INSECURE_KEY_CACHE_DIR) - - return FHECircuit(op_graph, engine) + return FHECircuit( + op_graph, + mlir_result, + unsecure_key_set_cache_path=_COMPILE_FHE_INSECURE_KEY_CACHE_DIR, + auto_parallelize=compilation_configuration.auto_parallelize, + loop_parallelize=compilation_configuration.loop_parallelize, + dataflow_parallelize=compilation_configuration.dataflow_parallelize, + ) def compile_op_graph_to_fhe_circuit( diff --git a/deps_licenses/licenses_linux_user.txt b/deps_licenses/licenses_linux_user.txt index adcc552e3..638f3b8b8 100644 --- a/deps_licenses/licenses_linux_user.txt +++ b/deps_licenses/licenses_linux_user.txt @@ -1,20 +1,20 @@ - Name Version License - Pillow 9.0.1 Historical Permission Notice and Disclaimer (HPND) - PyYAML 6.0 MIT License - concrete-compiler 0.5.0 BSD-3 - cycler 0.11.0 BSD License - fonttools 4.31.2 MIT License - kiwisolver 1.4.2 BSD License - loguru 0.5.3 MIT License - matplotlib 3.5.1 Python Software Foundation License - networkx 2.7.1 BSD License - numpy 1.22.3 BSD License - packaging 21.3 Apache Software License; BSD License - pygraphviz 1.9 BSD License - pyparsing 3.0.7 MIT License - python-dateutil 2.8.2 Apache Software License; BSD License - setuptools-scm 6.4.2 MIT License - six 1.16.0 MIT License - tomli 1.2.3 MIT License - torch 1.11.0 BSD License - typing-extensions 4.1.1 Python Software Foundation License + Name Version License + Pillow 9.1.0 Historical Permission Notice and Disclaimer (HPND) + PyYAML 6.0 MIT License + concrete-compiler 0.6.0 BSD-3 + cycler 0.11.0 BSD License + fonttools 4.31.2 MIT License + kiwisolver 1.4.2 BSD License + loguru 0.5.3 MIT License + matplotlib 3.5.1 Python Software Foundation License + networkx 2.7.1 BSD License + numpy 1.22.3 BSD License + packaging 21.3 Apache Software License; BSD License + pygraphviz 1.9 BSD License + pyparsing 3.0.7 MIT License + python-dateutil 2.8.2 Apache Software License; BSD License + setuptools-scm 6.4.2 MIT License + six 1.16.0 MIT License + tomli 1.2.3 MIT License + torch 1.11.0 BSD License + typing-extensions 4.1.1 Python Software Foundation License diff --git a/docker/release_resources/sanity_check.py b/docker/release_resources/sanity_check.py index baff59316..87b86610d 100644 --- a/docker/release_resources/sanity_check.py +++ b/docker/release_resources/sanity_check.py @@ -34,7 +34,7 @@ def main(): correct = 0 for idx, (input_i, label_i) in enumerate(zip(inputs, labels), 1): print(f"Inference #{idx}") - result_i = engine.run(*input_i) + result_i = engine.encrypt_run_decrypt(*input_i) if result_i == label_i: correct += 1 diff --git a/poetry.lock b/poetry.lock index 99efb3972..e4a95ed61 100644 --- a/poetry.lock +++ b/poetry.lock @@ -8,7 +8,7 @@ python-versions = "*" [[package]] name = "appnope" -version = "0.1.2" +version = "0.1.3" description = "Disable App Nap on macOS >= 10.9" category = "dev" optional = false @@ -243,7 +243,7 @@ python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" [[package]] name = "concrete-compiler" -version = "0.5.0" +version = "0.6.0" description = "Concrete Compiler" category = "main" optional = false @@ -378,6 +378,17 @@ category = "dev" optional = false python-versions = "*" +[[package]] +name = "fastjsonschema" +version = "2.15.3" +description = "Fastest Python implementation of JSON schema" +category = "dev" +optional = false +python-versions = "*" + +[package.extras] +devel = ["colorama", "jsonschema", "json-spec", "pylint", "pytest", "pytest-benchmark", "pytest-cache", "validictory"] + [[package]] name = "flake8" version = "4.0.1" @@ -532,7 +543,7 @@ python-versions = "*" [[package]] name = "ipykernel" -version = "6.10.0" +version = "6.12.1" description = "IPython Kernel for Jupyter" category = "dev" optional = false @@ -540,17 +551,18 @@ python-versions = ">=3.7" [package.dependencies] appnope = {version = "*", markers = "platform_system == \"Darwin\""} -debugpy = ">=1.0.0,<2.0" +debugpy = ">=1.0" ipython = ">=7.23.1" -jupyter-client = "<8.0" -matplotlib-inline = ">=0.1.0,<0.2.0" +jupyter-client = ">=6.1.12" +matplotlib-inline = ">=0.1" nest-asyncio = "*" +packaging = "*" psutil = "*" -tornado = ">=5.0,<7.0" -traitlets = ">=5.1.0,<6.0" +tornado = ">=6.1" +traitlets = ">=5.1.0" [package.extras] -test = ["pytest (!=5.3.4)", "pytest-cov", "flaky", "ipyparallel"] +test = ["pytest (>=6.0)", "pytest-cov", "flaky", "ipyparallel", "pre-commit", "pytest-timeout"] [[package]] name = "ipython" @@ -646,14 +658,14 @@ testing = ["Django (<3.1)", "colorama", "docopt", "pytest (<7.0.0)"] [[package]] name = "jeepney" -version = "0.7.1" +version = "0.8.0" description = "Low-level, pure Python DBus protocol wrapper." category = "dev" optional = false -python-versions = ">=3.6" +python-versions = ">=3.7" [package.extras] -test = ["pytest", "pytest-trio", "pytest-asyncio", "testpath", "trio", "async-timeout"] +test = ["pytest", "pytest-trio", "pytest-asyncio (>=0.17)", "testpath", "trio", "async-timeout"] trio = ["trio", "async-generator"] [[package]] @@ -705,24 +717,24 @@ qtconsole = "*" [[package]] name = "jupyter-client" -version = "7.1.2" +version = "7.2.1" description = "Jupyter protocol implementation and client libraries" category = "dev" optional = false -python-versions = ">=3.6.1" +python-versions = ">=3.7" [package.dependencies] entrypoints = "*" -jupyter-core = ">=4.6.0" -nest-asyncio = ">=1.5" -python-dateutil = ">=2.1" -pyzmq = ">=13" -tornado = ">=4.1" +jupyter-core = ">=4.9.2" +nest-asyncio = ">=1.5.4" +python-dateutil = ">=2.8.2" +pyzmq = ">=22.3" +tornado = ">=6.0" traitlets = "*" [package.extras] -doc = ["myst-parser", "sphinx (>=1.3.6)", "sphinx-rtd-theme", "sphinxcontrib-github-alt"] -test = ["codecov", "coverage", "ipykernel", "ipython", "mock", "mypy", "pre-commit", "pytest", "pytest-asyncio", "pytest-cov", "pytest-timeout", "jedi (<0.18)"] +doc = ["ipykernel", "myst-parser", "sphinx (>=1.3.6)", "sphinx-rtd-theme", "sphinxcontrib-github-alt"] +test = ["codecov", "coverage", "ipykernel (>=6.5)", "ipython", "mypy", "pre-commit", "pytest", "pytest-asyncio (>=0.18)", "pytest-cov", "pytest-timeout"] [[package]] name = "jupyter-console" @@ -1026,20 +1038,20 @@ webpdf = ["pyppeteer (>=1,<1.1)"] [[package]] name = "nbformat" -version = "5.2.0" +version = "5.3.0" description = "The Jupyter Notebook format" category = "dev" optional = false python-versions = ">=3.7" [package.dependencies] -jsonschema = ">=2.4,<2.5.0 || >2.5.0" +fastjsonschema = "*" +jsonschema = ">=2.6" jupyter-core = "*" traitlets = ">=4.1" [package.extras] -fast = ["fastjsonschema"] -test = ["check-manifest", "fastjsonschema", "testpath", "pytest"] +test = ["check-manifest", "testpath", "pytest", "pre-commit"] [[package]] name = "nbmake" @@ -1075,7 +1087,7 @@ traitlets = "*" [[package]] name = "nest-asyncio" -version = "1.5.4" +version = "1.5.5" description = "Patch asyncio to allow nested event loops" category = "dev" optional = false @@ -1205,12 +1217,16 @@ python-versions = "*" [[package]] name = "pillow" -version = "9.0.1" +version = "9.1.0" description = "Python Imaging Library (Fork)" category = "main" optional = false python-versions = ">=3.7" +[package.extras] +docs = ["olefile", "sphinx (>=2.4)", "sphinx-copybutton", "sphinx-issues (>=3.0.1)", "sphinx-removed-in", "sphinx-rtd-theme (>=1.0)", "sphinxext-opengraph"] +tests = ["check-manifest", "coverage", "defusedxml", "markdown2", "olefile", "packaging", "pyroma", "pytest", "pytest-cov", "pytest-timeout"] + [[package]] name = "pip-api" version = "0.0.29" @@ -1298,7 +1314,7 @@ python-versions = "*" [[package]] name = "prometheus-client" -version = "0.13.1" +version = "0.14.0" description = "Python client for the Prometheus monitoring system." category = "dev" optional = false @@ -1309,7 +1325,7 @@ twisted = ["twisted"] [[package]] name = "prompt-toolkit" -version = "3.0.28" +version = "3.0.29" description = "Library for building powerful interactive command lines in Python" category = "dev" optional = false @@ -1889,7 +1905,7 @@ python-versions = "*" [[package]] name = "soupsieve" -version = "2.3.1" +version = "2.3.2" description = "A modern CSS selector implementation for Beautiful Soup." category = "dev" optional = false @@ -2134,7 +2150,7 @@ python-versions = ">= 3.5" [[package]] name = "tqdm" -version = "4.63.1" +version = "4.64.0" description = "Fast, Extensible Progress Meter" category = "dev" optional = false @@ -2146,6 +2162,7 @@ colorama = {version = "*", markers = "platform_system == \"Windows\""} [package.extras] dev = ["py-make (>=0.1.0)", "twine", "wheel"] notebook = ["ipywidgets (>=6)"] +slack = ["slack-sdk"] telegram = ["requests"] [[package]] @@ -2181,7 +2198,7 @@ urllib3 = ">=1.26.0" [[package]] name = "types-setuptools" -version = "57.4.11" +version = "57.4.12" description = "Typing stubs for setuptools" category = "dev" optional = false @@ -2264,15 +2281,15 @@ python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,>=2.7" [[package]] name = "zipp" -version = "3.7.0" +version = "3.8.0" description = "Backport of pathlib-compatible object wrapper for zip files" category = "dev" optional = false python-versions = ">=3.7" [package.extras] -docs = ["sphinx", "jaraco.packaging (>=8.2)", "rst.linker (>=1.9)"] -testing = ["pytest (>=6)", "pytest-checkdocs (>=2.4)", "pytest-flake8", "pytest-cov", "pytest-enabler (>=1.0.1)", "jaraco.itertools", "func-timeout", "pytest-black (>=0.3.7)", "pytest-mypy"] +docs = ["sphinx", "jaraco.packaging (>=9)", "rst.linker (>=1.9)"] +testing = ["pytest (>=6)", "pytest-checkdocs (>=2.4)", "pytest-flake8", "pytest-cov", "pytest-enabler (>=1.0.1)", "jaraco.itertools", "func-timeout", "pytest-black (>=0.3.7)", "pytest-mypy (>=0.9.1)"] [extras] extras = ["pygraphviz"] @@ -2281,7 +2298,7 @@ full = ["pygraphviz"] [metadata] lock-version = "1.1" python-versions = ">=3.8,<3.10" -content-hash = "93f07f06d597a0312b59e1d00cfa3efd69575ebdf07668b2a97316511cf29ba9" +content-hash = "de159b6c6e74909e3f3d147002f21a135743a52bf65efe4ad93b1abad5205b67" [metadata.files] alabaster = [ @@ -2289,8 +2306,8 @@ alabaster = [ {file = "alabaster-0.7.12.tar.gz", hash = "sha256:a661d72d58e6ea8a57f7a86e37d86716863ee5e92788398526d58b26a4e4dc02"}, ] appnope = [ - {file = "appnope-0.1.2-py2.py3-none-any.whl", hash = "sha256:93aa393e9d6c54c5cd570ccadd8edad61ea0c4b9ea7a01409020c9aa019eb442"}, - {file = "appnope-0.1.2.tar.gz", hash = "sha256:dd83cd4b5b460958838f6eb3000c660b1f9caf2a5b1de4264e941512f603258a"}, + {file = "appnope-0.1.3-py2.py3-none-any.whl", hash = "sha256:265a455292d0bd8a72453494fa24df5a11eb18373a60c7c0430889f22548605e"}, + {file = "appnope-0.1.3.tar.gz", hash = "sha256:02bd91c4de869fbb1e1c50aafc4098827a7a54ab2f39d9dcba6c9547ed920e24"}, ] argon2-cffi = [ {file = "argon2-cffi-21.3.0.tar.gz", hash = "sha256:d384164d944190a7dd7ef22c6aa3ff197da12962bd04b17f64d4e93d934dba5b"}, @@ -2432,12 +2449,12 @@ colorama = [ {file = "colorama-0.4.4.tar.gz", hash = "sha256:5941b2b48a20143d2267e95b1c2a7603ce057ee39fd88e7329b0c292aa16869b"}, ] concrete-compiler = [ - {file = "concrete_compiler-0.5.0-cp310-cp310-macosx_10_15_x86_64.whl", hash = "sha256:467c7a59286718c43b87f6e070dcf17789ef17d5154960e9849e74e7e93da3fa"}, - {file = "concrete_compiler-0.5.0-cp310-cp310-manylinux_2_24_x86_64.whl", hash = "sha256:c25be3c2cd84fd85963ec8a6078b2ce1e5e792e5d1665d6a208808b6084b6581"}, - {file = "concrete_compiler-0.5.0-cp38-cp38-macosx_10_15_x86_64.whl", hash = "sha256:ab6d8079f6ed7998ce84ae16a26ddfa5239fe412cc25bf72312f2fc6dc6d17a3"}, - {file = "concrete_compiler-0.5.0-cp38-cp38-manylinux_2_24_x86_64.whl", hash = "sha256:8e32437370748e98e18948e9cafbe7587e985fc59adb895e95a32275ce68a35f"}, - {file = "concrete_compiler-0.5.0-cp39-cp39-macosx_10_15_x86_64.whl", hash = "sha256:e2fa9049aa31bb93614d465d07e89450131e5023f1799f26864addf9aac41187"}, - {file = "concrete_compiler-0.5.0-cp39-cp39-manylinux_2_24_x86_64.whl", hash = "sha256:f797205f9c8058b19c7173734b03bd51b260f5e3f6134b06b138f0fdfe24fffa"}, + {file = "concrete_compiler-0.6.0-cp310-cp310-macosx_10_15_x86_64.whl", hash = "sha256:7ba9148e8cbb1728b6a28da06499c3b7268fb25a7e059eab1b0dbe03aa26b8c2"}, + {file = "concrete_compiler-0.6.0-cp310-cp310-manylinux_2_24_x86_64.whl", hash = "sha256:3cba505cb102d9f53bdb89550a126809501cb8e23aab86376bc5c62e05c425fb"}, + {file = "concrete_compiler-0.6.0-cp38-cp38-macosx_10_15_x86_64.whl", hash = "sha256:379170f54543d6a12c5f3785e75df2f1ed26383818abe10f5978325c36a2f451"}, + {file = "concrete_compiler-0.6.0-cp38-cp38-manylinux_2_24_x86_64.whl", hash = "sha256:069c7310ec22aa432a94451fd13873cb076083389d0c83504b3d89181c7de98c"}, + {file = "concrete_compiler-0.6.0-cp39-cp39-macosx_10_15_x86_64.whl", hash = "sha256:4d633adc8b1b5b3bebe0a152ad1bf008ad0d31484be2ea6e28242541c5603b6b"}, + {file = "concrete_compiler-0.6.0-cp39-cp39-manylinux_2_24_x86_64.whl", hash = "sha256:a7a29435c9485a4cda0ee8bafb1b9a94b64e2a845ca819d88aad38c9f9076439"}, ] coverage = [ {file = "coverage-6.3.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:9b27d894748475fa858f9597c0ee1d4829f44683f3813633aaf94b19cb5453cf"}, @@ -2559,6 +2576,10 @@ executing = [ {file = "executing-0.8.3-py2.py3-none-any.whl", hash = "sha256:d1eef132db1b83649a3905ca6dd8897f71ac6f8cac79a7e58a1a09cf137546c9"}, {file = "executing-0.8.3.tar.gz", hash = "sha256:c6554e21c6b060590a6d3be4b82fb78f8f0194d809de5ea7df1c093763311501"}, ] +fastjsonschema = [ + {file = "fastjsonschema-2.15.3-py3-none-any.whl", hash = "sha256:ddb0b1d8243e6e3abb822bd14e447a89f4ab7439342912d590444831fa00b6a0"}, + {file = "fastjsonschema-2.15.3.tar.gz", hash = "sha256:0a572f0836962d844c1fc435e200b2e4f4677e4e6611a2e3bdd01ba697c275ec"}, +] flake8 = [ {file = "flake8-4.0.1-py2.py3-none-any.whl", hash = "sha256:479b1304f72536a55948cb40a32dce8bb0ffe3501e26eaf292c7e60eb5e0428d"}, {file = "flake8-4.0.1.tar.gz", hash = "sha256:806e034dda44114815e23c16ef92f95c91e4c71100ff52813adf7132a6ad870d"}, @@ -2608,8 +2629,8 @@ invoke = [ {file = "invoke-1.7.0.tar.gz", hash = "sha256:e332e49de40463f2016315f51df42313855772be86435686156bc18f45b5cc6c"}, ] ipykernel = [ - {file = "ipykernel-6.10.0-py3-none-any.whl", hash = "sha256:86ebe63f58cb68f299e06a2add4957df0eaebc7b0864de5711accd9c532d7810"}, - {file = "ipykernel-6.10.0.tar.gz", hash = "sha256:d1c7d92daea5d9b55a33e523d4d17c09ad38e0df17a4e0ed2fa5c97f07f200ba"}, + {file = "ipykernel-6.12.1-py3-none-any.whl", hash = "sha256:d840e3bf1c4b23bf6939f78dcdae639c9f6962e41d17e1c084a18c3c7f972d3a"}, + {file = "ipykernel-6.12.1.tar.gz", hash = "sha256:0868f5561729ade444011f8ca7d3502dc9f27f7f44e20f1d5fee7e1f2b7183a1"}, ] ipython = [ {file = "ipython-8.2.0-py3-none-any.whl", hash = "sha256:1b672bfd7a48d87ab203d9af8727a3b0174a4566b4091e9447c22fb63ea32857"}, @@ -2632,8 +2653,8 @@ jedi = [ {file = "jedi-0.18.1.tar.gz", hash = "sha256:74137626a64a99c8eb6ae5832d99b3bdd7d29a3850fe2aa80a4126b2a7d949ab"}, ] jeepney = [ - {file = "jeepney-0.7.1-py3-none-any.whl", hash = "sha256:1b5a0ea5c0e7b166b2f5895b91a08c14de8915afda4407fb5022a195224958ac"}, - {file = "jeepney-0.7.1.tar.gz", hash = "sha256:fa9e232dfa0c498bd0b8a3a73b8d8a31978304dcef0515adc859d4e096f96f4f"}, + {file = "jeepney-0.8.0-py3-none-any.whl", hash = "sha256:c0a454ad016ca575060802ee4d590dd912e35c122fa04e70306de3d076cce755"}, + {file = "jeepney-0.8.0.tar.gz", hash = "sha256:5efe48d255973902f6badc3ce55e2aa6c5c3b3bc642059ef3a91247bcfcc5806"}, ] jinja2 = [ {file = "Jinja2-3.1.1-py3-none-any.whl", hash = "sha256:539835f51a74a69f41b848a9645dbdc35b4f20a3b601e2d9a7e22947b15ff119"}, @@ -2649,8 +2670,8 @@ jupyter = [ {file = "jupyter-1.0.0.zip", hash = "sha256:3e1f86076bbb7c8c207829390305a2b1fe836d471ed54be66a3b8c41e7f46cc7"}, ] jupyter-client = [ - {file = "jupyter_client-7.1.2-py3-none-any.whl", hash = "sha256:d56f1c57bef42ff31e61b1185d3348a5b2bcde7c9a05523ae4dbe5ee0871797c"}, - {file = "jupyter_client-7.1.2.tar.gz", hash = "sha256:4ea61033726c8e579edb55626d8ee2e6bf0a83158ddf3751b8dd46b2c5cd1e96"}, + {file = "jupyter_client-7.2.1-py3-none-any.whl", hash = "sha256:d10e31ac4b8364d1cb30ebcee9e5cc7b7eb5d23b76912be9ef3d4c75167fbc68"}, + {file = "jupyter_client-7.2.1.tar.gz", hash = "sha256:aa177279e93205d0681ec0e2e210da01b22c5a1464a56abd455adcac64f0de91"}, ] jupyter-console = [ {file = "jupyter_console-6.4.3-py3-none-any.whl", hash = "sha256:e630bcb682c0088dda45688ad7c2424d4a825c8acf494cb036ced03ed0424841"}, @@ -2938,8 +2959,8 @@ nbconvert = [ {file = "nbconvert-6.4.5.tar.gz", hash = "sha256:21163a8e2073c07109ca8f398836e45efdba2aacea68d6f75a8a545fef070d4e"}, ] nbformat = [ - {file = "nbformat-5.2.0-py3-none-any.whl", hash = "sha256:3e30424e8291b2188347f5c3ba5273ed3766f12f8c5137c2e456a0815f36e785"}, - {file = "nbformat-5.2.0.tar.gz", hash = "sha256:93df0b9c67221d38fb970c48f6d361819a6c388299a0ef3171bbb912edfe1324"}, + {file = "nbformat-5.3.0-py3-none-any.whl", hash = "sha256:38856d97de49e8292e2d5d8f595e9d26f02abfd87e075d450af4511870b40538"}, + {file = "nbformat-5.3.0.tar.gz", hash = "sha256:fcc5ab8cb74e20b19570b5be809e2dba9b82836fd2761a89066ad43394ba29f5"}, ] nbmake = [ {file = "nbmake-1.3.0-py3-none-any.whl", hash = "sha256:8b38089dd232142ce894a9ad3e57a7c0f0a0edb0254662a8446346a84ac4079d"}, @@ -2950,8 +2971,8 @@ nbsphinx = [ {file = "nbsphinx-0.8.7.tar.gz", hash = "sha256:ff91b5b14ceb1a9d44193b5fc3dd3617e7b8ab59c788f7710049ce5faff2750c"}, ] nest-asyncio = [ - {file = "nest_asyncio-1.5.4-py3-none-any.whl", hash = "sha256:3fdd0d6061a2bb16f21fe8a9c6a7945be83521d81a0d15cff52e9edee50101d6"}, - {file = "nest_asyncio-1.5.4.tar.gz", hash = "sha256:f969f6013a16fadb4adcf09d11a68a4f617c6049d7af7ac2c676110169a63abd"}, + {file = "nest_asyncio-1.5.5-py3-none-any.whl", hash = "sha256:b98e3ec1b246135e4642eceffa5a6c23a3ab12c82ff816a92c612d68205813b2"}, + {file = "nest_asyncio-1.5.5.tar.gz", hash = "sha256:e442291cd942698be619823a17a86a5759eabe1f8613084790de189fe9e16d65"}, ] networkx = [ {file = "networkx-2.7.1-py3-none-any.whl", hash = "sha256:011e85d277c89681e8fa661cf5ff0743443445049b0b68789ad55ef09340c6e0"}, @@ -3012,41 +3033,44 @@ pickleshare = [ {file = "pickleshare-0.7.5.tar.gz", hash = "sha256:87683d47965c1da65cdacaf31c8441d12b8044cdec9aca500cd78fc2c683afca"}, ] pillow = [ - {file = "Pillow-9.0.1-1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:a5d24e1d674dd9d72c66ad3ea9131322819ff86250b30dc5821cbafcfa0b96b4"}, - {file = "Pillow-9.0.1-1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:2632d0f846b7c7600edf53c48f8f9f1e13e62f66a6dbc15191029d950bfed976"}, - {file = "Pillow-9.0.1-1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:b9618823bd237c0d2575283f2939655f54d51b4527ec3972907a927acbcc5bfc"}, - {file = "Pillow-9.0.1-cp310-cp310-macosx_10_10_universal2.whl", hash = "sha256:9bfdb82cdfeccec50aad441afc332faf8606dfa5e8efd18a6692b5d6e79f00fd"}, - {file = "Pillow-9.0.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:5100b45a4638e3c00e4d2320d3193bdabb2d75e79793af7c3eb139e4f569f16f"}, - {file = "Pillow-9.0.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:528a2a692c65dd5cafc130de286030af251d2ee0483a5bf50c9348aefe834e8a"}, - {file = "Pillow-9.0.1-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0f29d831e2151e0b7b39981756d201f7108d3d215896212ffe2e992d06bfe049"}, - {file = "Pillow-9.0.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:855c583f268edde09474b081e3ddcd5cf3b20c12f26e0d434e1386cc5d318e7a"}, - {file = "Pillow-9.0.1-cp310-cp310-win32.whl", hash = "sha256:d9d7942b624b04b895cb95af03a23407f17646815495ce4547f0e60e0b06f58e"}, - {file = "Pillow-9.0.1-cp310-cp310-win_amd64.whl", hash = "sha256:81c4b81611e3a3cb30e59b0cf05b888c675f97e3adb2c8672c3154047980726b"}, - {file = "Pillow-9.0.1-cp37-cp37m-macosx_10_10_x86_64.whl", hash = "sha256:413ce0bbf9fc6278b2d63309dfeefe452835e1c78398efb431bab0672fe9274e"}, - {file = "Pillow-9.0.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:80fe64a6deb6fcfdf7b8386f2cf216d329be6f2781f7d90304351811fb591360"}, - {file = "Pillow-9.0.1-cp37-cp37m-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:cef9c85ccbe9bee00909758936ea841ef12035296c748aaceee535969e27d31b"}, - {file = "Pillow-9.0.1-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1d19397351f73a88904ad1aee421e800fe4bbcd1aeee6435fb62d0a05ccd1030"}, - {file = "Pillow-9.0.1-cp37-cp37m-win32.whl", hash = "sha256:d21237d0cd37acded35154e29aec853e945950321dd2ffd1a7d86fe686814669"}, - {file = "Pillow-9.0.1-cp37-cp37m-win_amd64.whl", hash = "sha256:ede5af4a2702444a832a800b8eb7f0a7a1c0eed55b644642e049c98d589e5092"}, - {file = "Pillow-9.0.1-cp38-cp38-macosx_10_10_x86_64.whl", hash = "sha256:b5b3f092fe345c03bca1e0b687dfbb39364b21ebb8ba90e3fa707374b7915204"}, - {file = "Pillow-9.0.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:335ace1a22325395c4ea88e00ba3dc89ca029bd66bd5a3c382d53e44f0ccd77e"}, - {file = "Pillow-9.0.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:db6d9fac65bd08cea7f3540b899977c6dee9edad959fa4eaf305940d9cbd861c"}, - {file = "Pillow-9.0.1-cp38-cp38-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f154d173286a5d1863637a7dcd8c3437bb557520b01bddb0be0258dcb72696b5"}, - {file = "Pillow-9.0.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:14d4b1341ac07ae07eb2cc682f459bec932a380c3b122f5540432d8977e64eae"}, - {file = "Pillow-9.0.1-cp38-cp38-win32.whl", hash = "sha256:effb7749713d5317478bb3acb3f81d9d7c7f86726d41c1facca068a04cf5bb4c"}, - {file = "Pillow-9.0.1-cp38-cp38-win_amd64.whl", hash = "sha256:7f7609a718b177bf171ac93cea9fd2ddc0e03e84d8fa4e887bdfc39671d46b00"}, - {file = "Pillow-9.0.1-cp39-cp39-macosx_10_10_x86_64.whl", hash = "sha256:80ca33961ced9c63358056bd08403ff866512038883e74f3a4bf88ad3eb66838"}, - {file = "Pillow-9.0.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:1c3c33ac69cf059bbb9d1a71eeaba76781b450bc307e2291f8a4764d779a6b28"}, - {file = "Pillow-9.0.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:12875d118f21cf35604176872447cdb57b07126750a33748bac15e77f90f1f9c"}, - {file = "Pillow-9.0.1-cp39-cp39-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:514ceac913076feefbeaf89771fd6febde78b0c4c1b23aaeab082c41c694e81b"}, - {file = "Pillow-9.0.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d3c5c79ab7dfce6d88f1ba639b77e77a17ea33a01b07b99840d6ed08031cb2a7"}, - {file = "Pillow-9.0.1-cp39-cp39-win32.whl", hash = "sha256:718856856ba31f14f13ba885ff13874be7fefc53984d2832458f12c38205f7f7"}, - {file = "Pillow-9.0.1-cp39-cp39-win_amd64.whl", hash = "sha256:f25ed6e28ddf50de7e7ea99d7a976d6a9c415f03adcaac9c41ff6ff41b6d86ac"}, - {file = "Pillow-9.0.1-pp37-pypy37_pp73-macosx_10_10_x86_64.whl", hash = "sha256:011233e0c42a4a7836498e98c1acf5e744c96a67dd5032a6f666cc1fb97eab97"}, - {file = "Pillow-9.0.1-pp37-pypy37_pp73-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:253e8a302a96df6927310a9d44e6103055e8fb96a6822f8b7f514bb7ef77de56"}, - {file = "Pillow-9.0.1-pp37-pypy37_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6295f6763749b89c994fcb6d8a7f7ce03c3992e695f89f00b741b4580b199b7e"}, - {file = "Pillow-9.0.1-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:a9f44cd7e162ac6191491d7249cceb02b8116b0f7e847ee33f739d7cb1ea1f70"}, - {file = "Pillow-9.0.1.tar.gz", hash = "sha256:6c8bc8238a7dfdaf7a75f5ec5a663f4173f8c367e5a39f87e720495e1eed75fa"}, + {file = "Pillow-9.1.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:af79d3fde1fc2e33561166d62e3b63f0cc3e47b5a3a2e5fea40d4917754734ea"}, + {file = "Pillow-9.1.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:55dd1cf09a1fd7c7b78425967aacae9b0d70125f7d3ab973fadc7b5abc3de652"}, + {file = "Pillow-9.1.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:66822d01e82506a19407d1afc104c3fcea3b81d5eb11485e593ad6b8492f995a"}, + {file = "Pillow-9.1.0-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a5eaf3b42df2bcda61c53a742ee2c6e63f777d0e085bbc6b2ab7ed57deb13db7"}, + {file = "Pillow-9.1.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:01ce45deec9df310cbbee11104bae1a2a43308dd9c317f99235b6d3080ddd66e"}, + {file = "Pillow-9.1.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:aea7ce61328e15943d7b9eaca87e81f7c62ff90f669116f857262e9da4057ba3"}, + {file = "Pillow-9.1.0-cp310-cp310-win32.whl", hash = "sha256:7a053bd4d65a3294b153bdd7724dce864a1d548416a5ef61f6d03bf149205160"}, + {file = "Pillow-9.1.0-cp310-cp310-win_amd64.whl", hash = "sha256:97bda660702a856c2c9e12ec26fc6d187631ddfd896ff685814ab21ef0597033"}, + {file = "Pillow-9.1.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:21dee8466b42912335151d24c1665fcf44dc2ee47e021d233a40c3ca5adae59c"}, + {file = "Pillow-9.1.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6b6d4050b208c8ff886fd3db6690bf04f9a48749d78b41b7a5bf24c236ab0165"}, + {file = "Pillow-9.1.0-cp37-cp37m-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5cfca31ab4c13552a0f354c87fbd7f162a4fafd25e6b521bba93a57fe6a3700a"}, + {file = "Pillow-9.1.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ed742214068efa95e9844c2d9129e209ed63f61baa4d54dbf4cf8b5e2d30ccf2"}, + {file = "Pillow-9.1.0-cp37-cp37m-win32.whl", hash = "sha256:c9efef876c21788366ea1f50ecb39d5d6f65febe25ad1d4c0b8dff98843ac244"}, + {file = "Pillow-9.1.0-cp37-cp37m-win_amd64.whl", hash = "sha256:de344bcf6e2463bb25179d74d6e7989e375f906bcec8cb86edb8b12acbc7dfef"}, + {file = "Pillow-9.1.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:17869489de2fce6c36690a0c721bd3db176194af5f39249c1ac56d0bb0fcc512"}, + {file = "Pillow-9.1.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:25023a6209a4d7c42154073144608c9a71d3512b648a2f5d4465182cb93d3477"}, + {file = "Pillow-9.1.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8782189c796eff29dbb37dd87afa4ad4d40fc90b2742704f94812851b725964b"}, + {file = "Pillow-9.1.0-cp38-cp38-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:463acf531f5d0925ca55904fa668bb3461c3ef6bc779e1d6d8a488092bdee378"}, + {file = "Pillow-9.1.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3f42364485bfdab19c1373b5cd62f7c5ab7cc052e19644862ec8f15bb8af289e"}, + {file = "Pillow-9.1.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:3fddcdb619ba04491e8f771636583a7cc5a5051cd193ff1aa1ee8616d2a692c5"}, + {file = "Pillow-9.1.0-cp38-cp38-win32.whl", hash = "sha256:4fe29a070de394e449fd88ebe1624d1e2d7ddeed4c12e0b31624561b58948d9a"}, + {file = "Pillow-9.1.0-cp38-cp38-win_amd64.whl", hash = "sha256:c24f718f9dd73bb2b31a6201e6db5ea4a61fdd1d1c200f43ee585fc6dcd21b34"}, + {file = "Pillow-9.1.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:fb89397013cf302f282f0fc998bb7abf11d49dcff72c8ecb320f76ea6e2c5717"}, + {file = "Pillow-9.1.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:c870193cce4b76713a2b29be5d8327c8ccbe0d4a49bc22968aa1e680930f5581"}, + {file = "Pillow-9.1.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:69e5ddc609230d4408277af135c5b5c8fe7a54b2bdb8ad7c5100b86b3aab04c6"}, + {file = "Pillow-9.1.0-cp39-cp39-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:35be4a9f65441d9982240e6966c1eaa1c654c4e5e931eaf580130409e31804d4"}, + {file = "Pillow-9.1.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:82283af99c1c3a5ba1da44c67296d5aad19f11c535b551a5ae55328a317ce331"}, + {file = "Pillow-9.1.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:a325ac71914c5c043fa50441b36606e64a10cd262de12f7a179620f579752ff8"}, + {file = "Pillow-9.1.0-cp39-cp39-win32.whl", hash = "sha256:a598d8830f6ef5501002ae85c7dbfcd9c27cc4efc02a1989369303ba85573e58"}, + {file = "Pillow-9.1.0-cp39-cp39-win_amd64.whl", hash = "sha256:0c51cb9edac8a5abd069fd0758ac0a8bfe52c261ee0e330f363548aca6893595"}, + {file = "Pillow-9.1.0-pp37-pypy37_pp73-macosx_10_9_x86_64.whl", hash = "sha256:a336a4f74baf67e26f3acc4d61c913e378e931817cd1e2ef4dfb79d3e051b481"}, + {file = "Pillow-9.1.0-pp37-pypy37_pp73-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:eb1b89b11256b5b6cad5e7593f9061ac4624f7651f7a8eb4dfa37caa1dfaa4d0"}, + {file = "Pillow-9.1.0-pp37-pypy37_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:255c9d69754a4c90b0ee484967fc8818c7ff8311c6dddcc43a4340e10cd1636a"}, + {file = "Pillow-9.1.0-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:5a3ecc026ea0e14d0ad7cd990ea7f48bfcb3eb4271034657dc9d06933c6629a7"}, + {file = "Pillow-9.1.0-pp38-pypy38_pp73-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c5b0ff59785d93b3437c3703e3c64c178aabada51dea2a7f2c5eccf1bcf565a3"}, + {file = "Pillow-9.1.0-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c7110ec1701b0bf8df569a7592a196c9d07c764a0a74f65471ea56816f10e2c8"}, + {file = "Pillow-9.1.0-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:8d79c6f468215d1a8415aa53d9868a6b40c4682165b8cb62a221b1baa47db458"}, + {file = "Pillow-9.1.0.tar.gz", hash = "sha256:f401ed2bbb155e1ade150ccc63db1a4f6c1909d3d378f7d1235a44e90d75fb97"}, ] pip-api = [ {file = "pip-api-0.0.29.tar.gz", hash = "sha256:f701584eb1c3e01021c846f89d629ab9373b6624f0626757774ad54fc4c29571"}, @@ -3076,12 +3100,12 @@ progress = [ {file = "progress-1.6.tar.gz", hash = "sha256:c9c86e98b5c03fa1fe11e3b67c1feda4788b8d0fe7336c2ff7d5644ccfba34cd"}, ] prometheus-client = [ - {file = "prometheus_client-0.13.1-py3-none-any.whl", hash = "sha256:357a447fd2359b0a1d2e9b311a0c5778c330cfbe186d880ad5a6b39884652316"}, - {file = "prometheus_client-0.13.1.tar.gz", hash = "sha256:ada41b891b79fca5638bd5cfe149efa86512eaa55987893becd2c6d8d0a5dfc5"}, + {file = "prometheus_client-0.14.0-py3-none-any.whl", hash = "sha256:f4aba3fdd1735852049f537c1f0ab177159b7ab76f271ecc4d2f45aa2a1d01f2"}, + {file = "prometheus_client-0.14.0.tar.gz", hash = "sha256:8f7a922dd5455ad524b6ba212ce8eb2b4b05e073f4ec7218287f88b1cac34750"}, ] prompt-toolkit = [ - {file = "prompt_toolkit-3.0.28-py3-none-any.whl", hash = "sha256:30129d870dcb0b3b6a53efdc9d0a83ea96162ffd28ffe077e94215b233dc670c"}, - {file = "prompt_toolkit-3.0.28.tar.gz", hash = "sha256:9f1cd16b1e86c2968f2519d7fb31dd9d669916f515612c269d14e9ed52b51650"}, + {file = "prompt_toolkit-3.0.29-py3-none-any.whl", hash = "sha256:62291dad495e665fca0bda814e342c69952086afb0f4094d0893d357e5c78752"}, + {file = "prompt_toolkit-3.0.29.tar.gz", hash = "sha256:bd640f60e8cecd74f0dc249713d433ace2ddc62b65ee07f96d358e0b152b6ea7"}, ] psutil = [ {file = "psutil-5.9.0-cp27-cp27m-manylinux2010_i686.whl", hash = "sha256:55ce319452e3d139e25d6c3f85a1acf12d1607ddedea5e35fb47a552c051161b"}, @@ -3444,8 +3468,8 @@ snowballstemmer = [ {file = "snowballstemmer-2.2.0.tar.gz", hash = "sha256:09b16deb8547d3412ad7b590689584cd0fe25ec8db3be37788be3810cbf19cb1"}, ] soupsieve = [ - {file = "soupsieve-2.3.1-py3-none-any.whl", hash = "sha256:1a3cca2617c6b38c0343ed661b1fa5de5637f257d4fe22bd9f1338010a1efefb"}, - {file = "soupsieve-2.3.1.tar.gz", hash = "sha256:b8d49b1cd4f037c7082a9683dfa1801aa2597fb11c3a1155b7a5b94829b4f1f9"}, + {file = "soupsieve-2.3.2-py3-none-any.whl", hash = "sha256:a714129d3021ec17ce5be346b1007300558b378332c289a1a20e7d4de6ff18a5"}, + {file = "soupsieve-2.3.2.tar.gz", hash = "sha256:0bcc6d7432153063e3df09c3ac9442af3eba488715bfcad6a4c38ccb2a523124"}, ] sphinx = [ {file = "Sphinx-4.3.0-py3-none-any.whl", hash = "sha256:7e2b30da5f39170efcd95c6270f07669d623c276521fee27ad6c380f49d2bf5b"}, @@ -3578,8 +3602,8 @@ tornado = [ {file = "tornado-6.1.tar.gz", hash = "sha256:33c6e81d7bd55b468d2e793517c909b139960b6c790a60b7991b9b6b76fb9791"}, ] tqdm = [ - {file = "tqdm-4.63.1-py2.py3-none-any.whl", hash = "sha256:6461b009d6792008d0000e1b0c7ca50195ec78c0e808a3a6b668a56a3236c3a5"}, - {file = "tqdm-4.63.1.tar.gz", hash = "sha256:4230a49119a416c88cc47d0d2d32d5d90f1a282d5e497d49801950704e49863d"}, + {file = "tqdm-4.64.0-py2.py3-none-any.whl", hash = "sha256:74a2cdefe14d11442cedf3ba4e21a3b84ff9a2dbdc6cfae2c34addb2a14a5ea6"}, + {file = "tqdm-4.64.0.tar.gz", hash = "sha256:40be55d30e200777a307a7585aee69e4eabb46b4ec6a4b4a5f2d9f11e7d5408d"}, ] traitlets = [ {file = "traitlets-5.1.1-py3-none-any.whl", hash = "sha256:2d313cc50a42cd6c277e7d7dc8d4d7fedd06a2c215f78766ae7b1a66277e0033"}, @@ -3590,8 +3614,8 @@ twine = [ {file = "twine-3.8.0.tar.gz", hash = "sha256:8efa52658e0ae770686a13b675569328f1fba9837e5de1867bfe5f46a9aefe19"}, ] types-setuptools = [ - {file = "types-setuptools-57.4.11.tar.gz", hash = "sha256:262f7406e0c7d705ad6bb4526b5b761fa500bf99eab74de85ac3592187d62935"}, - {file = "types_setuptools-57.4.11-py3-none-any.whl", hash = "sha256:fbb0647569d6fb2f6bc472402265250c0ffa53e60180d2cbfee9e84f085921f0"}, + {file = "types-setuptools-57.4.12.tar.gz", hash = "sha256:415a1c23101a05da17eb66bed5d5a865702e5a69f74c66dbf1af643dce9492ab"}, + {file = "types_setuptools-57.4.12-py3-none-any.whl", hash = "sha256:c3aa952535dedc78654459dfdee49c66974a6c67bdd8026e7e69ae39f80d590b"}, ] types-toml = [ {file = "types-toml-0.10.4.tar.gz", hash = "sha256:9340e7c1587715581bb13905b3af30b79fe68afaccfca377665d5e63b694129a"}, @@ -3675,6 +3699,6 @@ wrapt = [ {file = "wrapt-1.13.3.tar.gz", hash = "sha256:1fea9cd438686e6682271d36f3481a9f3636195578bab9ca3382e2f5f01fc185"}, ] zipp = [ - {file = "zipp-3.7.0-py3-none-any.whl", hash = "sha256:b47250dd24f92b7dd6a0a8fc5244da14608f3ca90a5efcd37a3b1642fac9a375"}, - {file = "zipp-3.7.0.tar.gz", hash = "sha256:9f50f446828eb9d45b267433fd3e9da8d801f614129124863f9c51ebceafb87d"}, + {file = "zipp-3.8.0-py3-none-any.whl", hash = "sha256:c4f6e5bbf48e74f7a38e7cc5b0480ff42b0ae5178957d564d18932525d5cf099"}, + {file = "zipp-3.8.0.tar.gz", hash = "sha256:56bf8aadb83c24db6c4b577e13de374ccfb67da2078beba1d037c17980bf43ad"}, ] diff --git a/pyproject.toml b/pyproject.toml index c3a284c81..f8845cd0d 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -45,7 +45,7 @@ pygraphviz = { version = "^1.7", optional = true } Pillow = "^9.0.0" loguru = "^0.5.3" setuptools = "*" -concrete-compiler = "^0.5.0" +concrete-compiler = "^0.6.0" torch = "^1.10.2" [tool.poetry.extras] diff --git a/tests/common/test_fhe_circuit.py b/tests/common/test_fhe_circuit.py index 0a6cb80ca..6a2c5d1a6 100644 --- a/tests/common/test_fhe_circuit.py +++ b/tests/common/test_fhe_circuit.py @@ -36,7 +36,7 @@ def test_circuit_draw(default_compilation_configuration): def test_circuit_run(default_compilation_configuration): - """Test function for `run` method of `Circuit`""" + """Test equivalence of encrypt/run/decrypt and encrypt_run_decrypt""" def f(x): return x + 42 @@ -46,5 +46,9 @@ def test_circuit_run(default_compilation_configuration): inputset = range(2 ** 3) circuit = hnp.compile_numpy_function(f, {"x": x}, inputset, default_compilation_configuration) + circuit.keygen() for x in inputset: - assert circuit.run(x) == circuit.engine.run(x) + enc_x = circuit.encrypt(x) + enc_res = circuit.run(enc_x) + res = circuit.decrypt(enc_res) + assert circuit.encrypt_run_decrypt(x) == res diff --git a/tests/conftest.py b/tests/conftest.py index ad3c6947b..3597b5c8f 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -404,7 +404,9 @@ def check_is_good_execution_impl( for i in range(1, nb_tries + 1): preprocessed_args = tuple(preprocess_input_func(val) for val in args) - last_engine_result = postprocess_output_func(fhe_circuit.run(*preprocessed_args)) + last_engine_result = postprocess_output_func( + fhe_circuit.encrypt_run_decrypt(*preprocessed_args) + ) last_function_result = postprocess_output_func(function(*preprocessed_args)) ok_execution = check_function(last_engine_result, last_function_result) diff --git a/tests/numpy/test_compile.py b/tests/numpy/test_compile.py index 53b70293e..7349ffc19 100644 --- a/tests/numpy/test_compile.py +++ b/tests/numpy/test_compile.py @@ -11,7 +11,7 @@ from concrete.common.data_types.integers import Integer, SignedInteger, Unsigned from concrete.common.debugging import draw_graph, format_operation_graph from concrete.common.extensions.multi_table import MultiLookupTable from concrete.common.extensions.table import LookupTable -from concrete.common.values import ClearTensor, EncryptedScalar, EncryptedTensor +from concrete.common.values import ClearScalar, ClearTensor, EncryptedScalar, EncryptedTensor from concrete.numpy import compile as compile_ from concrete.numpy import tracing from concrete.numpy.compile import ( @@ -790,7 +790,7 @@ def test_compile_and_run_correctness( ) args = [random.randint(low, high) for (low, high) in input_ranges] - assert compiler_engine.run(*args) == function(*args) + assert compiler_engine.encrypt_run_decrypt(*args) == function(*args) @pytest.mark.parametrize( @@ -1417,7 +1417,7 @@ def test_compile_and_run_tensor_correctness( check_is_good_execution(circuit, function, numpy_test_input) else: check_array_equality( - circuit.run(*numpy_test_input), + circuit.encrypt_run_decrypt(*numpy_test_input), numpy.array(function(*numpy_test_input), dtype=numpy.uint8), ) @@ -1486,7 +1486,7 @@ def test_compile_and_run_dot_correctness(size, input_range, default_compilation_ args = [ numpy.random.randint(low, high + 1, size=shape, dtype=numpy.uint8) for __ in range(2) ] - assert compiler_engine.run(*args) == func_to_compile(*args) + assert compiler_engine.encrypt_run_decrypt(*args) == func_to_compile(*args) @pytest.mark.parametrize( @@ -1563,7 +1563,9 @@ def test_compile_and_run_dot_correctness_with_signed_cst( args = [ numpy.random.randint(low_x, high_x + 1, size=(size,), dtype=numpy.uint8), ] - assert check_equality_modulo(compiler_engine.run(*args), function(*args), modulus) + assert check_equality_modulo( + compiler_engine.encrypt_run_decrypt(*args), function(*args), modulus + ) @pytest.mark.parametrize( @@ -1624,8 +1626,8 @@ def test_compile_and_run_constant_dot_correctness( ) args = (numpy.random.randint(low, high + 1, size=shape, dtype=numpy.uint8),) - assert left_circuit.run(*args) == left(*args) - assert right_circuit.run(*args) == right(*args) + assert left_circuit.encrypt_run_decrypt(*args) == left(*args) + assert right_circuit.encrypt_run_decrypt(*args) == right(*args) @pytest.mark.parametrize( @@ -1837,7 +1839,7 @@ def test_compile_and_run_matmul_correctness( # Stay positive for input to FHE circuit arg = numpy.clip(arg, 0, high).astype(numpy.uint8) - circuit_output = circuit.run(arg) + circuit_output = circuit.encrypt_run_decrypt(arg) func_output = func(arg) if check_mod: @@ -2046,7 +2048,58 @@ def test_compile_and_run_transpose_correctness(input_shape, default_compilation_ ) x = numpy.random.randint(0, 120, size=input_shape, dtype=numpy.uint8) expected = transpose(x) - result = compiler_engine.run(x) + result = compiler_engine.encrypt_run_decrypt(x) + assert (expected == result).all() + + +@pytest.mark.parametrize( + "input_shape", + [ + pytest.param((8,)), + ], +) +@pytest.mark.parametrize( + "loop_parallelize", + [ + pytest.param(True), + pytest.param(False), + ], +) +def test_compile_and_run_loop_parallelization( + input_shape, loop_parallelize, default_compilation_configuration +): + """Test function to make sure compilation and execution with and without loop parallelization + works properly""" + + def dot_and_add(x, y, a): + return numpy.dot(x, y) + a + + # Enable/Disable loop parallelization + compilation_configuration = deepcopy(default_compilation_configuration) + compilation_configuration.loop_parallelize = loop_parallelize + + compiler_engine = compile_numpy_function( + dot_and_add, + { + "x": EncryptedTensor(Integer(64, False), input_shape), + "y": ClearTensor(Integer(64, False), input_shape), + "a": ClearScalar(Integer(64, False)), + }, + [ + ( + numpy.random.randint(0, 2, size=input_shape), + numpy.random.randint(0, 2, size=input_shape), + numpy.random.randint(0, 2, size=()), + ) + for i in range(20) + ], + compilation_configuration, + ) + x = numpy.random.randint(0, 2, size=input_shape, dtype=numpy.uint8) + y = numpy.random.randint(0, 2, size=input_shape, dtype=numpy.uint8) + a = numpy.random.randint(0, 2, size=(), dtype=numpy.uint8) + expected = dot_and_add(x, y, a) + result = compiler_engine.encrypt_run_decrypt(x, y, a) assert (expected == result).all() @@ -2549,7 +2602,7 @@ def test_compile_and_run_correctness_with_negative_values( ) args = [random.randint(low, high) for (low, high) in input_ranges] - assert compiler_engine.run(*args) == function(*args) + assert compiler_engine.encrypt_run_decrypt(*args) == function(*args) @pytest.mark.parametrize( @@ -2623,7 +2676,9 @@ def test_compile_and_run_correctness_with_negative_results( ) args = [random.randint(low, high) for (low, high) in input_ranges] - assert check_equality_modulo(compiler_engine.run(*args), function(*args), modulus) + assert check_equality_modulo( + compiler_engine.encrypt_run_decrypt(*args), function(*args), modulus + ) @pytest.mark.parametrize( diff --git a/tests/numpy/test_compile_constant_indexing.py b/tests/numpy/test_compile_constant_indexing.py index 41fc73c64..fcc186f47 100644 --- a/tests/numpy/test_compile_constant_indexing.py +++ b/tests/numpy/test_compile_constant_indexing.py @@ -721,7 +721,7 @@ def test_constant_indexing_run_correctness( item if isinstance(item, int) else np.array(item, dtype=np.uint8) for item in test_input ) - output = circuit.run(*numpy_test_input) + output = circuit.encrypt_run_decrypt(*numpy_test_input) expected = np.array(expected_output, dtype=np.uint8) check_array_equality(output, expected) diff --git a/tests/numpy/test_compile_conv.py b/tests/numpy/test_compile_conv.py index 9cbceddf7..4c4383827 100644 --- a/tests/numpy/test_compile_conv.py +++ b/tests/numpy/test_compile_conv.py @@ -40,5 +40,5 @@ def test_compile_and_run( ) x = np.random.randint(0, 4, size=input_shape, dtype=np.uint8) expected = conv(x) - result = compiler_engine.run(x) + result = compiler_engine.encrypt_run_decrypt(x) assert (expected == result).all() diff --git a/tests/numpy/test_compile_memory_operations.py b/tests/numpy/test_compile_memory_operations.py index 68dfb1421..b743c8115 100644 --- a/tests/numpy/test_compile_memory_operations.py +++ b/tests/numpy/test_compile_memory_operations.py @@ -198,7 +198,7 @@ def test_memory_operation_run_correctness( default_compilation_configuration, ) - actual = circuit.run(numpy.array(test_input, dtype=numpy.uint8)) + actual = circuit.encrypt_run_decrypt(numpy.array(test_input, dtype=numpy.uint8)) expected = numpy.array(expected_output, dtype=numpy.uint8) check_array_equality(actual, expected) diff --git a/tests/numpy/test_compile_user_friendly_api.py b/tests/numpy/test_compile_user_friendly_api.py index 39dc92100..cc48b56f3 100644 --- a/tests/numpy/test_compile_user_friendly_api.py +++ b/tests/numpy/test_compile_user_friendly_api.py @@ -260,7 +260,7 @@ def test_np_fhe_compiler_full_compilation(default_compilation_configuration, che fhe_circuit = compiler.get_compiled_fhe_circuit() for i in range(64): - assert fhe_circuit.run(i) == function_to_compile(i) + assert fhe_circuit.encrypt_run_decrypt(i) == function_to_compile(i) def test_np_fhe_compiler_compile_on_inputset(default_compilation_configuration): @@ -277,4 +277,4 @@ def test_np_fhe_compiler_compile_on_inputset(default_compilation_configuration): circuit = compiler.compile_on_inputset(numpy.arange(64)) for i in range(64): - assert circuit.run(i) == function_to_compile(i) + assert circuit.encrypt_run_decrypt(i) == function_to_compile(i)