refactor: disallow tuple input in inputset for 1-input functions

- handle the case properly once we add tuple support in #772

closes #971
This commit is contained in:
Arthur Meyre
2021-12-01 16:38:05 +01:00
parent 09e8a97232
commit 48aaed9ee8
15 changed files with 152 additions and 132 deletions

View File

@@ -161,7 +161,13 @@ def eval_op_graph_bounds_on_inputset(
def generate_input_values_dict(input_data) -> Dict[int, Any]:
if num_input_nodes > 1:
return dict(enumerate(input_data))
return dict(enumerate(input_data)) if isinstance(input_data, tuple) else {0: input_data}
# TODO: https://github.com/zama-ai/concretefhe-internal/issues/772
# update this to support tuple in case of 1-input functions accepting tuples
assert_true(
not isinstance(input_data, tuple),
"Tuples are unsupported for single input inputset evaluation",
)
return {0: input_data}
# TODO: do we want to check coherence between the input data type and the corresponding Input ir
# node expected data type ? Not considering bit_width as they may not make sense at this stage

View File

@@ -93,22 +93,23 @@ def sanitize_compilation_configuration_and_artifacts(
def get_inputset_to_use(
function_parameters: Dict[str, BaseValue],
inputset: Union[Iterable[Tuple[Any, ...]], str],
inputset: Union[Iterable[Any], Iterable[Tuple[Any, ...]], str],
compilation_configuration: CompilationConfiguration,
) -> Iterable[Tuple[Any, ...]]:
) -> Union[Iterable[Any], Iterable[Tuple[Any, ...]]]:
"""Get the proper inputset to use for compilation.
Args:
function_parameters (Dict[str, BaseValue]): A dictionary indicating what each input of the
function is e.g. an EncryptedScalar holding a 7bits unsigned Integer
inputset (Union[Iterable[Tuple[Any, ...]], str]): The inputset over which op_graph is
evaluated. It needs to be an iterable on tuples which are of the same length than the
number of parameters in the function, and in the same order than these same parameters
inputset (Union[Iterable[Any], Iterable[Tuple[Any, ...]], str]): The inputset over which
op_graph is evaluated. It needs to be an iterable on tuples which are of the same length
than the number of parameters in the function, and in the same order than these same
parameters
compilation_configuration (CompilationConfiguration): Configuration object to use during
compilation
Returns:
Iterable[Tuple[Any, ...]]: the inputset to use.
Union[Iterable[Any], Iterable[Tuple[Any, ...]]]: the inputset to use.
"""
# Generate random inputset if it is requested and available
if isinstance(inputset, str):
@@ -265,7 +266,7 @@ def compile_numpy_function_into_op_graph(
def _measure_op_graph_bounds_and_update_internal(
op_graph: OPGraph,
function_parameters: Dict[str, BaseValue],
inputset: Iterable[Tuple[Any, ...]],
inputset: Union[Iterable[Any], Iterable[Tuple[Any, ...]]],
compilation_configuration: CompilationConfiguration,
compilation_artifacts: CompilationArtifacts,
prev_node_bounds_and_samples: Optional[Dict[IntermediateNode, Dict[str, Any]]] = None,
@@ -277,9 +278,9 @@ def _measure_op_graph_bounds_and_update_internal(
op_graph (OPGraph): the OPGraph for which to measure bounds and update node values.
function_parameters (Dict[str, BaseValue]): A dictionary indicating what each input of the
function is e.g. an EncryptedScalar holding a 7bits unsigned Integer
inputset (Iterable[Tuple[Any, ...]]): The inputset over which op_graph is evaluated. It
needs to be an iterable on tuples which are of the same length than the number of
parameters in the function, and in the same order than these same parameters
inputset (Union[Iterable[Any], Iterable[Tuple[Any, ...]]]): The inputset over which op_graph
is evaluated. It needs to be an iterable on tuples which are of the same length than the
number of parameters in the function, and in the same order than these same parameters
compilation_configuration (CompilationConfiguration): Configuration object to use
during compilation
compilation_artifacts (CompilationArtifacts): Artifacts object to fill
@@ -355,7 +356,7 @@ def _measure_op_graph_bounds_and_update_internal(
def measure_op_graph_bounds_and_update(
op_graph: OPGraph,
function_parameters: Dict[str, BaseValue],
inputset: Union[Iterable[Tuple[Any, ...]], str],
inputset: Union[Iterable[Any], Iterable[Tuple[Any, ...]], str],
compilation_configuration: Optional[CompilationConfiguration] = None,
compilation_artifacts: Optional[CompilationArtifacts] = None,
prev_node_bounds_and_samples: Optional[Dict[IntermediateNode, Dict[str, Any]]] = None,
@@ -367,9 +368,10 @@ def measure_op_graph_bounds_and_update(
op_graph (OPGraph): the OPGraph for which to measure bounds and update node values.
function_parameters (Dict[str, BaseValue]): A dictionary indicating what each input of the
function is e.g. an EncryptedScalar holding a 7bits unsigned Integer
inputset (Union[Iterable[Tuple[Any, ...]], str]): The inputset over which op_graph is
evaluated. It needs to be an iterable on tuples which are of the same length than the
number of parameters in the function, and in the same order than these same parameters
inputset (Union[Iterable[Any], Iterable[Tuple[Any, ...]], str]): The inputset over which
op_graph is evaluated. It needs to be an iterable on tuples which are of the same length
than the number of parameters in the function, and in the same order than these same
parameters
compilation_configuration (Optional[CompilationConfiguration]): Configuration object to use
during compilation
compilation_artifacts (Optional[CompilationArtifacts]): Artifacts object to fill
@@ -421,7 +423,7 @@ def measure_op_graph_bounds_and_update(
def _compile_numpy_function_into_op_graph_and_measure_bounds_internal(
function_to_compile: Callable,
function_parameters: Dict[str, BaseValue],
inputset: Iterable[Tuple[Any, ...]],
inputset: Union[Iterable[Any], Iterable[Tuple[Any, ...]]],
compilation_configuration: CompilationConfiguration,
compilation_artifacts: CompilationArtifacts,
) -> OPGraph:
@@ -431,9 +433,9 @@ def _compile_numpy_function_into_op_graph_and_measure_bounds_internal(
function_to_compile (Callable): The function to compile
function_parameters (Dict[str, BaseValue]): A dictionary indicating what each input of the
function is e.g. an EncryptedScalar holding a 7bits unsigned Integer
inputset (Iterable[Tuple[Any, ...]]): The inputset over which op_graph is evaluated. It
needs to be an iterable on tuples which are of the same length than the number of
parameters in the function, and in the same order than these same parameters
inputset (Union[Iterable[Any], Iterable[Tuple[Any, ...]]]): The inputset over which op_graph
is evaluated. It needs to be an iterable on tuples which are of the same length than the
number of parameters in the function, and in the same order than these same parameters
compilation_configuration (CompilationConfiguration): Configuration object to use
during compilation
compilation_artifacts (CompilationArtifacts): Artifacts object to fill
@@ -467,7 +469,7 @@ def _compile_numpy_function_into_op_graph_and_measure_bounds_internal(
def compile_numpy_function_into_op_graph_and_measure_bounds(
function_to_compile: Callable,
function_parameters: Dict[str, BaseValue],
inputset: Union[Iterable[Tuple[Any, ...]], str],
inputset: Union[Iterable[Any], Iterable[Tuple[Any, ...]], str],
compilation_configuration: Optional[CompilationConfiguration] = None,
compilation_artifacts: Optional[CompilationArtifacts] = None,
) -> OPGraph:
@@ -477,9 +479,9 @@ def compile_numpy_function_into_op_graph_and_measure_bounds(
function_to_compile (Callable): The function to compile
function_parameters (Dict[str, BaseValue]): A dictionary indicating what each input of the
function is e.g. an EncryptedScalar holding a 7bits unsigned Integer
inputset (Union[Iterable[Tuple[Any, ...]], str]): The inputset over which op_graph
is evaluated. It needs to be an iterable on tuples which are of the same length than
the number of parameters in the function, and in the same order than these same
inputset (Union[Iterable[Any], Iterable[Tuple[Any, ...]], str]): The inputset over which
op_graph is evaluated. It needs to be an iterable on tuples which are of the same length
than the number of parameters in the function, and in the same order than these same
parameters. Alternatively, it can be "random" but that's an unstable feature and should
not be used in production.
compilation_configuration (Optional[CompilationConfiguration]): Configuration object to use
@@ -683,7 +685,7 @@ def compile_op_graph_to_fhe_circuit(
def _compile_numpy_function_internal(
function_to_compile: Callable,
function_parameters: Dict[str, BaseValue],
inputset: Iterable[Tuple[Any, ...]],
inputset: Union[Iterable[Any], Iterable[Tuple[Any, ...]]],
compilation_configuration: CompilationConfiguration,
compilation_artifacts: CompilationArtifacts,
show_mlir: bool,
@@ -694,9 +696,9 @@ def _compile_numpy_function_internal(
function_to_compile (Callable): The function you want to compile
function_parameters (Dict[str, BaseValue]): A dictionary indicating what each input of the
function is e.g. an EncryptedScalar holding a 7bits unsigned Integer
inputset (Iterable[Tuple[Any, ...]]): The inputset over which op_graph is evaluated. It
needs to be an iterable on tuples which are of the same length than the number of
parameters in the function, and in the same order than these same parameters
inputset (Union[Iterable[Any], Iterable[Tuple[Any, ...]]]): The inputset over which op_graph
is evaluated. It needs to be an iterable on tuples which are of the same length than the
number of parameters in the function, and in the same order than these same parameters
compilation_configuration (CompilationConfiguration): Configuration object to use
during compilation
compilation_artifacts (CompilationArtifacts): Artifacts object to fill
@@ -727,7 +729,7 @@ def _compile_numpy_function_internal(
def compile_numpy_function(
function_to_compile: Callable,
function_parameters: Dict[str, BaseValue],
inputset: Union[Iterable[Tuple[Any, ...]], str],
inputset: Union[Iterable[Any], Iterable[Tuple[Any, ...]], str],
compilation_configuration: Optional[CompilationConfiguration] = None,
compilation_artifacts: Optional[CompilationArtifacts] = None,
show_mlir: bool = False,
@@ -738,9 +740,9 @@ def compile_numpy_function(
function_to_compile (Callable): The function to compile
function_parameters (Dict[str, BaseValue]): A dictionary indicating what each input of the
function is e.g. an EncryptedScalar holding a 7bits unsigned Integer
inputset (Union[Iterable[Tuple[Any, ...]], str]): The inputset over which op_graph
is evaluated. It needs to be an iterable on tuples which are of the same length than
the number of parameters in the function, and in the same order than these same
inputset (Union[Iterable[Any], Iterable[Tuple[Any, ...]], str]): The inputset over which
op_graph is evaluated. It needs to be an iterable on tuples which are of the same length
than the number of parameters in the function, and in the same order than these same
parameters. Alternatively, it can be "random" but that's an unstable feature and should
not be used in production.
compilation_configuration (Optional[CompilationConfiguration]): Configuration object to use

View File

@@ -107,7 +107,7 @@ class NPFHECompiler:
Returns:
Any: the result of the OPGraph evaluation.
"""
self._current_inputset.append(deepcopy(args))
self._current_inputset.append(deepcopy(args) if len(args) > 1 else deepcopy(args[0]))
inferred_args = {
param_name: get_base_value_for_numpy_or_python_constant_data(val)(
@@ -127,12 +127,12 @@ class NPFHECompiler:
assert self._op_graph is not None
return self._op_graph(*args)
def eval_on_inputset(self, inputset: Iterable[Union[Any, Tuple]]) -> None:
def eval_on_inputset(self, inputset: Union[Iterable[Any], Iterable[Tuple[Any, ...]]]) -> None:
"""Evaluate the underlying function on an inputset in one go, populates OPGraph and bounds.
Args:
inputset (Iterable[Union[Any, Tuple]]): The inputset on which the function should be
evaluated.
inputset (Union[Iterable[Any], Iterable[Tuple[Any, ...]]]): The inputset on which the
function should be evaluated.
"""
inputset_as_list = list(inputset)
if len(inputset_as_list) == 0:
@@ -143,7 +143,10 @@ class NPFHECompiler:
is_encrypted=is_encrypted
)
for (param_name, is_encrypted), val in zip(
self._function_parameters_encrypted_status.items(), self._current_inputset[0]
self._function_parameters_encrypted_status.items(),
inputset_as_list[0]
if len(self._function_parameters_encrypted_status) > 1
else (inputset_as_list[0],),
)
}

View File

@@ -1,7 +1,7 @@
"""Helpers for numpy inputset related functionality."""
import random
from typing import Any, Dict, Iterable, Tuple
from typing import Any, Dict, Iterable, Tuple, Union
import numpy
@@ -72,7 +72,7 @@ def _generate_random_float_tensor(dtype: Float, shape: Tuple[int, ...]) -> numpy
def _generate_random_inputset(
function_parameters: Dict[str, BaseValue],
compilation_configuration: CompilationConfiguration,
) -> Iterable[Tuple[Any, ...]]:
) -> Union[Iterable[Any], Iterable[Tuple[Any, ...]]]:
"""Generate a random inputset from function parameters.
Using this function is not a good practice since the randomly generated inputset
@@ -89,7 +89,7 @@ def _generate_random_inputset(
ValueError: if the provided function arguments cannot be used for random inputset generation
Returns:
None
Union[Iterable[Any], Iterable[Tuple[Any, ...]]]: the inputset
"""
inputset = []
@@ -116,7 +116,7 @@ def _generate_random_inputset(
f"Random inputset cannot be generated "
f"for parameters of type {parameter.dtype}"
)
inputset.append(tuple(sample))
inputset.append(tuple(sample) if len(sample) > 1 else sample[0])
return inputset

View File

@@ -117,10 +117,7 @@ class QuantizedModule:
UnsignedInteger(self.q_input.n_bits), shape=(1, *self.q_input.qvalues.shape[1:])
)
},
[
(numpy.expand_dims(arr, 0),)
for arr in self.q_input.qvalues # Super weird formatting
],
[numpy.expand_dims(arr, 0) for arr in self.q_input.qvalues], # Super weird formatting
compilation_configuration=compilation_configuration,
compilation_artifacts=compilation_artifacts,
)

View File

@@ -504,3 +504,30 @@ def test_inpuset_eval_1_input(default_compilation_configuration):
output_node = op_graph.output_nodes[0]
assert output_node.outputs[0] == EncryptedScalar(UnsignedInteger(6))
# TODO: https://github.com/zama-ai/concretefhe-internal/issues/772
# Remove once this issue is done
def test_inpuset_eval_1_input_refuse_tuple(default_compilation_configuration):
"""Test case for a function with a single parameter and passing the inputset with tuples."""
def f(x):
return x + 42
x = EncryptedScalar(UnsignedInteger(4))
inputset = [(i,) for i in range(10)]
op_graph = trace_numpy_function(f, {"x": x})
with pytest.raises(AssertionError) as excinfo:
eval_op_graph_bounds_on_inputset(
op_graph,
inputset,
compilation_configuration=default_compilation_configuration,
min_func=numpy_min_func,
max_func=numpy_max_func,
get_base_value_for_constant_data_func=get_base_value_for_numpy_or_python_constant_data,
)
assert str(excinfo.value) == "Tuples are unsupported for single input inputset evaluation"

View File

@@ -22,7 +22,7 @@ def test_artifacts_export(default_compilation_configuration):
compile_numpy_function(
function,
{"x": EncryptedScalar(UnsignedInteger(7))},
[(i,) for i in range(10)],
range(10),
default_compilation_configuration,
compilation_artifacts=artifacts,
)

View File

@@ -49,7 +49,7 @@ def test_enable_topological_optimizations(
param: EncryptedScalar(Integer(32, is_signed=False))
for param in signature(function_to_trace).parameters.keys()
},
[(numpy.array(i),) for i in range(10)],
[numpy.array(i) for i in range(10)],
default_compilation_configuration,
)
op_graph_not_optimized = compile_numpy_function_into_op_graph_and_measure_bounds(
@@ -58,7 +58,7 @@ def test_enable_topological_optimizations(
param: EncryptedScalar(Integer(32, is_signed=False))
for param in signature(function_to_trace).parameters.keys()
},
[(numpy.array(i),) for i in range(10)],
[numpy.array(i) for i in range(10)],
CompilationConfiguration(
dump_artifacts_on_unexpected_failures=False,
enable_topological_optimizations=False,

View File

@@ -18,7 +18,7 @@ def test_draw_graph_with_saving(default_compilation_configuration):
op_graph = compile_numpy_function_into_op_graph_and_measure_bounds(
function,
{"x": EncryptedScalar(Integer(7, True))},
[(i,) for i in range(-5, 5)],
range(-5, 5),
default_compilation_configuration,
)

View File

@@ -20,7 +20,7 @@ def test_format_operation_graph_with_multiple_edges(default_compilation_configur
op_graph = compile_numpy_function_into_op_graph_and_measure_bounds(
function,
{"x": EncryptedScalar(Integer(4, True))},
[(i,) for i in range(0, 10)],
range(0, 10),
default_compilation_configuration,
)
@@ -46,7 +46,7 @@ def test_format_operation_graph_with_offending_nodes(default_compilation_configu
op_graph = compile_numpy_function_into_op_graph_and_measure_bounds(
function,
{"x": EncryptedScalar(Integer(7, True))},
[(i,) for i in range(-5, 5)],
range(-5, 5),
default_compilation_configuration,
)
@@ -94,7 +94,7 @@ def test_format_operation_graph_with_fusing(default_compilation_configuration):
{
"x": EncryptedScalar(UnsignedInteger(3)),
},
[(i,) for i in range(2 ** 3)],
range(2 ** 3),
default_compilation_configuration,
)

View File

@@ -68,8 +68,8 @@ from concrete.numpy import compile_numpy_function
pytest.param(
lambda x: numpy.ones(shape=(2, 3), dtype=numpy.uint32) @ x,
{"x": EncryptedTensor(UnsignedInteger(3), shape=(3, 2))},
[(numpy.random.randint(0, 2 ** 3, size=(3, 2)),) for i in range(10)]
+ [(numpy.array([[7, 7], [7, 7], [7, 7]]),)],
[numpy.random.randint(0, 2 ** 3, size=(3, 2)) for i in range(10)]
+ [numpy.array([[7, 7], [7, 7], [7, 7]])],
NotImplementedError,
"Matrix multiplication "
"between "

View File

@@ -14,7 +14,7 @@ def test_circuit_str(default_compilation_configuration):
x = hnp.EncryptedScalar(hnp.UnsignedInteger(3))
inputset = [(i,) for i in range(2 ** 3)]
inputset = range(2 ** 3)
circuit = hnp.compile_numpy_function(f, {"x": x}, inputset, default_compilation_configuration)
assert str(circuit) == format_operation_graph(circuit.op_graph)
@@ -28,7 +28,7 @@ def test_circuit_draw(default_compilation_configuration):
x = hnp.EncryptedScalar(hnp.UnsignedInteger(3))
inputset = [(i,) for i in range(2 ** 3)]
inputset = range(2 ** 3)
circuit = hnp.compile_numpy_function(f, {"x": x}, inputset, default_compilation_configuration)
assert filecmp.cmp(circuit.draw(), draw_graph(circuit.op_graph))
@@ -43,8 +43,8 @@ def test_circuit_run(default_compilation_configuration):
x = hnp.EncryptedScalar(hnp.UnsignedInteger(3))
inputset = [(i,) for i in range(2 ** 3)]
inputset = range(2 ** 3)
circuit = hnp.compile_numpy_function(f, {"x": x}, inputset, default_compilation_configuration)
for x in inputset:
assert circuit.run(*x) == circuit.engine.run(*x)
assert circuit.run(x) == circuit.engine.run(x)

View File

@@ -24,7 +24,7 @@ from concrete.numpy.compile import (
def data_gen(args):
"""Helper to create an inputset"""
for prod in itertools.product(*args):
yield prod
yield prod if len(prod) > 1 else prod[0]
def numpy_array_data_gen(args, tensor_shapes):
@@ -720,7 +720,7 @@ def test_compile_function_multiple_outputs(
def data_gen_local(args):
for prod in itertools.product(*args):
yield tuple(numpy.array(val) for val in prod)
yield tuple(numpy.array(val) for val in prod) if len(prod) > 1 else numpy.array(prod[0])
function_parameters = {
arg_name: EncryptedScalar(Integer(64, True)) for arg_name in list_of_arg_names
@@ -839,7 +839,7 @@ def test_compile_and_run_correctness__for_prog_with_tlu(
{
"x": EncryptedTensor(UnsignedInteger(3), shape=(3, 2)),
},
[(numpy.random.randint(0, 2 ** 3, size=(3, 2)),) for _ in range(10)],
[numpy.random.randint(0, 2 ** 3, size=(3, 2)) for _ in range(10)],
(
[
[0, 7],
@@ -854,7 +854,7 @@ def test_compile_and_run_correctness__for_prog_with_tlu(
{
"x": EncryptedTensor(UnsignedInteger(3), shape=(3, 2)),
},
[(numpy.random.randint(0, 2 ** 3, size=(3, 2)),) for _ in range(10)],
[numpy.random.randint(0, 2 ** 3, size=(3, 2)) for _ in range(10)],
(
[
[0, 7],
@@ -919,7 +919,7 @@ def test_compile_and_run_correctness__for_prog_with_tlu(
{
"x": EncryptedTensor(UnsignedInteger(3), shape=(3, 2)),
},
[(numpy.random.randint(0, 2 ** 3, size=(3, 2)),) for _ in range(10)],
[numpy.random.randint(0, 2 ** 3, size=(3, 2)) for _ in range(10)],
(
[
[0, 7],
@@ -934,7 +934,7 @@ def test_compile_and_run_correctness__for_prog_with_tlu(
{
"x": EncryptedTensor(UnsignedInteger(3), shape=(3, 2)),
},
[(numpy.random.randint(0, 2 ** 3, size=(3, 2)),) for _ in range(10)],
[numpy.random.randint(0, 2 ** 3, size=(3, 2)) for _ in range(10)],
(
[
[0, 7],
@@ -949,7 +949,7 @@ def test_compile_and_run_correctness__for_prog_with_tlu(
{
"x": EncryptedTensor(UnsignedInteger(3), shape=(3, 2)),
},
[(numpy.random.randint(0, 2 ** 3, size=(3, 2)),) for _ in range(10)],
[numpy.random.randint(0, 2 ** 3, size=(3, 2)) for _ in range(10)],
(
[
[0, 7],
@@ -964,7 +964,7 @@ def test_compile_and_run_correctness__for_prog_with_tlu(
{
"x": EncryptedTensor(UnsignedInteger(3), shape=(3, 2)),
},
[(numpy.random.randint(0, 2 ** 3, size=(3, 2)),) for _ in range(10)],
[numpy.random.randint(0, 2 ** 3, size=(3, 2)) for _ in range(10)],
(
[
[4, 7],
@@ -979,7 +979,7 @@ def test_compile_and_run_correctness__for_prog_with_tlu(
{
"x": EncryptedTensor(UnsignedInteger(2), shape=(3, 2)),
},
[(numpy.random.randint(0, 2 ** 2, size=(3, 2)),) for _ in range(10)],
[numpy.random.randint(0, 2 ** 2, size=(3, 2)) for _ in range(10)],
(
[
[0, 1],
@@ -994,7 +994,7 @@ def test_compile_and_run_correctness__for_prog_with_tlu(
{
"x": EncryptedTensor(UnsignedInteger(3), shape=(3,)),
},
[(numpy.random.randint(0, 2 ** 3, size=(3,)),) for _ in range(10)],
[numpy.random.randint(0, 2 ** 3, size=(3,)) for _ in range(10)],
([2, 7, 1],),
False,
),
@@ -1003,7 +1003,7 @@ def test_compile_and_run_correctness__for_prog_with_tlu(
{
"x": EncryptedTensor(UnsignedInteger(3), shape=(3,)),
},
[(numpy.random.randint(0, 2 ** 3, size=(3,)),) for _ in range(10)],
[numpy.random.randint(0, 2 ** 3, size=(3,)) for _ in range(10)],
([2, 7, 1],),
False,
),
@@ -1012,7 +1012,7 @@ def test_compile_and_run_correctness__for_prog_with_tlu(
{
"x": EncryptedTensor(UnsignedInteger(3), shape=(3, 2)),
},
[(numpy.random.randint(0, 2 ** 3, size=(3, 2)),) for _ in range(10)],
[numpy.random.randint(0, 2 ** 3, size=(3, 2)) for _ in range(10)],
(
[
[0, 7],
@@ -1027,7 +1027,7 @@ def test_compile_and_run_correctness__for_prog_with_tlu(
{
"x": EncryptedTensor(UnsignedInteger(3), shape=(3, 2)),
},
[(numpy.random.randint(0, 2 ** 3, size=(3, 2)),) for _ in range(10)],
[numpy.random.randint(0, 2 ** 3, size=(3, 2)) for _ in range(10)],
(
[
[0, 7],
@@ -1042,7 +1042,7 @@ def test_compile_and_run_correctness__for_prog_with_tlu(
{
"x": EncryptedTensor(UnsignedInteger(3), shape=(3, 2)),
},
[(numpy.random.randint(0, 2 ** 3, size=(3, 2)),) for _ in range(10)],
[numpy.random.randint(0, 2 ** 3, size=(3, 2)) for _ in range(10)],
(
[
[0, 7],
@@ -1057,7 +1057,7 @@ def test_compile_and_run_correctness__for_prog_with_tlu(
{
"x": EncryptedTensor(UnsignedInteger(3), shape=(3, 2)),
},
[(numpy.random.randint(0, 2 ** 3, size=(3, 2)),) for _ in range(10)],
[numpy.random.randint(0, 2 ** 3, size=(3, 2)) for _ in range(10)],
(
[
[0, 7],
@@ -1195,27 +1195,27 @@ def test_compile_and_run_dot_correctness_with_signed_cst(
for i in range(2):
inputset = [
(numpy.zeros(shape, dtype=numpy.uint32),),
(numpy.ones(shape, dtype=numpy.uint32) * low_x,),
(numpy.ones(shape, dtype=numpy.uint32) * high_x,),
numpy.zeros(shape, dtype=numpy.uint32),
numpy.ones(shape, dtype=numpy.uint32) * low_x,
numpy.ones(shape, dtype=numpy.uint32) * high_x,
]
for _ in range(128):
inputset.append((numpy.random.randint(low_x, high_x + 1),))
inputset.append(numpy.random.randint(low_x, high_x + 1))
if i == 0:
def function(x):
return numpy.dot(x, constant1)
inputset.extend([(worst_x_1_1,), (worst_x_1_2,)])
inputset.extend([worst_x_1_1, worst_x_1_2])
else:
def function(x):
return numpy.dot(constant2, x)
inputset.extend([(worst_x_2_1,), (worst_x_2_2,)])
inputset.extend([worst_x_2_1, worst_x_2_2])
compiler_engine = compile_numpy_function(
function, function_parameters, inputset, default_compilation_configuration
@@ -1258,11 +1258,11 @@ def test_compile_and_run_constant_dot_correctness(
shape = (size,)
inputset = [
(numpy.zeros(shape, dtype=numpy.uint32),),
(numpy.ones(shape, dtype=numpy.uint32) * high,),
numpy.zeros(shape, dtype=numpy.uint32),
numpy.ones(shape, dtype=numpy.uint32) * high,
]
for _ in range(8):
inputset.append((numpy.random.randint(low, high + 1),))
inputset.append(numpy.random.randint(low, high + 1))
constant = numpy.random.randint(low, high + 1, size=shape)
@@ -1323,11 +1323,11 @@ def test_compile_and_run_matmul_correctness(
low, high = input_range
inputset = [
(numpy.zeros(lhs_shape, dtype=numpy.uint32),),
(numpy.ones(lhs_shape, dtype=numpy.uint32) * high,),
numpy.zeros(lhs_shape, dtype=numpy.uint32),
numpy.ones(lhs_shape, dtype=numpy.uint32) * high,
]
for _ in range(8):
inputset.append((numpy.random.randint(low, high + 1, size=lhs_shape),))
inputset.append(numpy.random.randint(low, high + 1, size=lhs_shape))
constant = numpy.random.randint(low, high + 1, size=rhs_shape)
@@ -1468,7 +1468,7 @@ def test_compile_and_run_multi_lut_correctness(default_compilation_configuration
{
"x": EncryptedTensor(UnsignedInteger(2), shape=(3, 2)),
},
[(numpy.random.randint(0, 2 ** 2, size=(3, 2)),) for _ in range(10)],
[numpy.random.randint(0, 2 ** 2, size=(3, 2)) for _ in range(10)],
default_compilation_configuration,
)
@@ -1489,7 +1489,7 @@ def test_compile_function_with_direct_tlu(default_compilation_configuration):
op_graph = compile_numpy_function_into_op_graph_and_measure_bounds(
function,
{"x": EncryptedScalar(Integer(2, is_signed=False))},
[(0,), (1,), (2,), (3,)],
range(4),
default_compilation_configuration,
)
@@ -1509,7 +1509,7 @@ def test_compile_function_with_direct_tlu_overflow(default_compilation_configura
compile_numpy_function_into_op_graph_and_measure_bounds(
function,
{"x": EncryptedScalar(Integer(3, is_signed=False))},
[(0,), (1,), (2,), (3,), (4,), (5,), (6,), (7,)],
range(8),
default_compilation_configuration,
)
@@ -1523,18 +1523,7 @@ def test_compile_function_with_direct_tlu_overflow(default_compilation_configura
{
"x": EncryptedTensor(Integer(2, is_signed=False), shape=(1,)),
},
[
(numpy.array([1]),),
(numpy.array([1]),),
(numpy.array([0]),),
(numpy.array([0]),),
(numpy.array([1]),),
(numpy.array([1]),),
(numpy.array([0]),),
(numpy.array([0]),),
(numpy.array([2]),),
(numpy.array([2]),),
],
[numpy.array([i]) for i in [1, 1, 0, 0, 1, 1, 0, 0, 2, 2]],
(
"""
@@ -1584,7 +1573,7 @@ return %9
pytest.param(
lambda x: x @ -numpy.ones(shape=(2, 3), dtype=numpy.int32),
{"x": EncryptedTensor(UnsignedInteger(3), shape=(3, 2))},
[(numpy.random.randint(0, 2 ** 3, size=(3, 2)),) for i in range(10)],
[numpy.random.randint(0, 2 ** 3, size=(3, 2)) for i in range(10)],
(
"""
@@ -1602,7 +1591,7 @@ return %2
pytest.param(
lambda x: numpy.transpose(x),
{"x": EncryptedTensor(Integer(3, is_signed=False), shape=(3, 2))},
[(numpy.random.randint(0, 2 ** 3, size=(3, 2)),) for i in range(10)],
[numpy.random.randint(0, 2 ** 3, size=(3, 2)) for i in range(10)],
(
"""
@@ -1619,7 +1608,7 @@ return %1
pytest.param(
lambda x: numpy.ravel(x),
{"x": EncryptedTensor(Integer(3, is_signed=False), shape=(3, 2))},
[(numpy.random.randint(0, 2 ** 3, size=(3, 2)),) for i in range(10)],
[numpy.random.randint(0, 2 ** 3, size=(3, 2)) for i in range(10)],
(
"""
@@ -1636,7 +1625,7 @@ return %1
pytest.param(
lambda x: numpy.reshape(x, (2, 6)),
{"x": EncryptedTensor(Integer(3, is_signed=False), shape=(3, 4))},
[(numpy.random.randint(0, 2 ** 3, size=(3, 4)),) for i in range(10)],
[numpy.random.randint(0, 2 ** 3, size=(3, 4)) for i in range(10)],
(
"""
@@ -1673,7 +1662,7 @@ def test_fail_compile(function, parameters, inputset, match, default_compilation
pytest.param(
lambda x: (x * 1.5)[0, 1],
{"x": EncryptedTensor(SignedInteger(3), shape=(2, 2))},
[(numpy.random.randint(-4, 3, size=(2, 2)),) for i in range(10)],
[numpy.random.randint(-4, 3, size=(2, 2)) for i in range(10)],
(
"""
@@ -1718,7 +1707,7 @@ def test_small_inputset_no_fail():
compile_numpy_function_into_op_graph_and_measure_bounds(
lambda x: x + 42,
{"x": EncryptedScalar(Integer(5, is_signed=False))},
[(0,), (3,)],
[0, 3],
CompilationConfiguration(dump_artifacts_on_unexpected_failures=False),
)
@@ -1729,7 +1718,7 @@ def test_small_inputset_treat_warnings_as_errors():
compile_numpy_function_into_op_graph_and_measure_bounds(
lambda x: x + 42,
{"x": EncryptedScalar(Integer(5, is_signed=False))},
[(0,), (3,)],
[0, 3],
CompilationConfiguration(
dump_artifacts_on_unexpected_failures=False,
treat_warnings_as_errors=True,

View File

@@ -340,12 +340,10 @@ def test_constant_indexing(
"""Test compile_numpy_function_into_op_graph with constant indexing"""
inputset = [
(
np.random.randint(
input_value.dtype.min_value(),
input_value.dtype.max_value() + 1,
size=input_value.shape,
),
np.random.randint(
input_value.dtype.min_value(),
input_value.dtype.max_value() + 1,
size=input_value.shape,
)
for _ in range(10)
]
@@ -518,12 +516,10 @@ def test_constant_indexing_with_numpy_integers(
"""Test compile_numpy_function_into_op_graph with constant indexing with numpy integers"""
inputset = [
(
np.random.randint(
input_value.dtype.min_value(),
input_value.dtype.max_value() + 1,
size=input_value.shape,
),
np.random.randint(
input_value.dtype.min_value(),
input_value.dtype.max_value() + 1,
size=input_value.shape,
)
for _ in range(10)
]
@@ -608,7 +604,7 @@ def test_invalid_constant_indexing_with_numpy_values(
{
"x": EncryptedTensor(UnsignedInteger(3), shape=(3,)),
},
[(np.random.randint(0, 2 ** 3, size=(3,)),) for _ in range(10)],
[np.random.randint(0, 2 ** 3, size=(3,)) for _ in range(10)],
([4, 2, 6],),
4,
),
@@ -617,7 +613,7 @@ def test_invalid_constant_indexing_with_numpy_values(
{
"x": EncryptedTensor(UnsignedInteger(3), shape=(3,)),
},
[(np.random.randint(0, 2 ** 3, size=(3,)),) for _ in range(10)],
[np.random.randint(0, 2 ** 3, size=(3,)) for _ in range(10)],
([4, 2, 6],),
6,
),
@@ -626,7 +622,7 @@ def test_invalid_constant_indexing_with_numpy_values(
{
"x": EncryptedTensor(UnsignedInteger(3), shape=(4,)),
},
[(np.random.randint(0, 2 ** 3, size=(4,)),) for _ in range(10)],
[np.random.randint(0, 2 ** 3, size=(4,)) for _ in range(10)],
([4, 2, 6, 1],),
[4, 2, 6],
),
@@ -635,7 +631,7 @@ def test_invalid_constant_indexing_with_numpy_values(
{
"x": EncryptedTensor(UnsignedInteger(3), shape=(4,)),
},
[(np.random.randint(0, 2 ** 3, size=(4,)),) for _ in range(10)],
[np.random.randint(0, 2 ** 3, size=(4,)) for _ in range(10)],
([4, 2, 6, 1],),
[6, 1],
),
@@ -644,7 +640,7 @@ def test_invalid_constant_indexing_with_numpy_values(
{
"x": EncryptedTensor(UnsignedInteger(3), shape=(4,)),
},
[(np.random.randint(0, 2 ** 3, size=(4,)),) for _ in range(10)],
[np.random.randint(0, 2 ** 3, size=(4,)) for _ in range(10)],
([4, 2, 6, 1],),
[2, 6],
),
@@ -653,7 +649,7 @@ def test_invalid_constant_indexing_with_numpy_values(
{
"x": EncryptedTensor(UnsignedInteger(3), shape=(4,)),
},
[(np.random.randint(0, 2 ** 3, size=(4,)),) for _ in range(10)],
[np.random.randint(0, 2 ** 3, size=(4,)) for _ in range(10)],
([4, 2, 6, 1],),
[4, 6],
),
@@ -662,7 +658,7 @@ def test_invalid_constant_indexing_with_numpy_values(
{
"x": EncryptedTensor(UnsignedInteger(3), shape=(4,)),
},
[(np.random.randint(0, 2 ** 3, size=(4,)),) for _ in range(10)],
[np.random.randint(0, 2 ** 3, size=(4,)) for _ in range(10)],
([4, 2, 6, 1],),
[1, 6, 2, 4],
),
@@ -671,7 +667,7 @@ def test_invalid_constant_indexing_with_numpy_values(
{
"x": EncryptedTensor(UnsignedInteger(6), shape=(3, 2)),
},
[(np.random.randint(0, 2 ** 6, size=(3, 2)),) for _ in range(10)],
[np.random.randint(0, 2 ** 6, size=(3, 2)) for _ in range(10)],
([[11, 12], [21, 22], [31, 32]],),
21,
),
@@ -680,7 +676,7 @@ def test_invalid_constant_indexing_with_numpy_values(
{
"x": EncryptedTensor(UnsignedInteger(6), shape=(3, 2)),
},
[(np.random.randint(0, 2 ** 6, size=(3, 2)),) for _ in range(10)],
[np.random.randint(0, 2 ** 6, size=(3, 2)) for _ in range(10)],
([[11, 12], [21, 22], [31, 32]],),
[[11, 12], [21, 22], [31, 32]],
),
@@ -689,7 +685,7 @@ def test_invalid_constant_indexing_with_numpy_values(
{
"x": EncryptedTensor(UnsignedInteger(6), shape=(3, 2)),
},
[(np.random.randint(0, 2 ** 6, size=(3, 2)),) for _ in range(10)],
[np.random.randint(0, 2 ** 6, size=(3, 2)) for _ in range(10)],
([[11, 12], [21, 22], [31, 32]],),
[11, 12],
marks=pytest.mark.xfail(strict=True),
@@ -699,7 +695,7 @@ def test_invalid_constant_indexing_with_numpy_values(
{
"x": EncryptedTensor(UnsignedInteger(6), shape=(3, 2)),
},
[(np.random.randint(0, 2 ** 6, size=(3, 2)),) for _ in range(10)],
[np.random.randint(0, 2 ** 6, size=(3, 2)) for _ in range(10)],
([[11, 12], [21, 22], [31, 32]],),
[11, 21, 31],
marks=pytest.mark.xfail(strict=True),
@@ -752,7 +748,7 @@ Expected Output
{
"x": EncryptedTensor(UnsignedInteger(3), shape=(3,)),
},
[(np.random.randint(0, 2 ** 3, size=(3,)),) for _ in range(10)],
[np.random.randint(0, 2 ** 3, size=(3,)) for _ in range(10)],
(
"Indexing of EncryptedTensor<uint3, shape=(3,)> with [0:1] "
"cannot be converted to MLIR yet"

View File

@@ -45,7 +45,7 @@ def test_generate_deduplicated_tables(
op_graph = hnp.compile_numpy_function_into_op_graph_and_measure_bounds(
function,
{"x": hnp.EncryptedTensor(hnp.Integer(7, False), RESNET_BIGGEST_SHAPE)},
((i * numpy.ones(RESNET_BIGGEST_SHAPE, dtype=numpy.int32),) for i in range(128)),
(i * numpy.ones(RESNET_BIGGEST_SHAPE, dtype=numpy.int32) for i in range(128)),
default_compilation_configuration,
)
@@ -72,7 +72,7 @@ def test_deduplicated_tables_correctness(default_compilation_configuration):
op_graph = hnp.compile_numpy_function_into_op_graph_and_measure_bounds(
lambda x: multi_tlu_func(x, numpy.arange(4, dtype=numpy.float64).reshape(tensor_shape)),
{"x": hnp.EncryptedTensor(hnp.Integer(2, False), tensor_shape)},
((i * numpy.ones(tensor_shape, dtype=numpy.int32),) for i in range(4)),
(i * numpy.ones(tensor_shape, dtype=numpy.int32) for i in range(4)),
default_compilation_configuration,
)