Files
ml-sdk/tests/torch/test_reduce_sum.py
zeekay 531fc57003 chore(brand): purge Zama refs across docs, README, configs — phase 1
Brand-only sweep. Touches READMEs, docs, package metadata, comments,
notebook markdown, requirements.txt files; does NOT yet touch Python
`concrete.*` imports (those are module-level dependencies requiring the
phase-2 Python module port from `concrete` → `torus`).

Substitutions applied:

  Concrete ML                  → TorusML
  concrete-ml                  → torus-ml
  Concrete-ML                  → Torus-ML
  concrete_ml                  → torus_ml
  zama-ai/concrete-ml          → luxfhe/ml-sdk
  zama-ai/concrete             → luxfhe/torus
  github.com/zama-ai           → github.com/luxfhe
  docs.zama.ai/concrete-ml     → docs.luxfhe.com/ml-sdk
  docs.zama.ai/concrete        → docs.luxfhe.com/torus
  Zama Concrete ML             → Lux TorusML
  Zama Concrete                → Lux Torus
  Zama tfhe-rs / Zama TFHE-rs  → Lux-FHE
  tfhe-rs / TFHE-rs            → Lux-FHE
  Zama fhEVM / fhEVM           → TorusEVM
  Concrete framework           → Torus framework
  Concrete compiler            → Torus compiler
  Concrete by Zama             → Torus by Lux
  the Zama team                → the Lux Industries team
  Zama's                       → Lux Industries'
  (Zama)                       → (Lux)
  CoFHE / Fhenix               → (removed)

LICENSE: original Zama copyright RETAINED per BSD-3-Clause-Clear §1-§2
requirements; Lux Industries modifications copyright added. Per §3 no
name of ZAMA used to endorse the derived work — product marketed
exclusively as TorusML.

README image URLs migrated to github.com/luxfhe/ml-sdk/assets to break
the dependency on Zama's CDN.

Hit count: 350 → 295. Residual hits are Python `from concrete.fhe import`
imports referencing the upstream Zama `concrete` PyPI package; these
require module-level port (phase 2):

  Phase 2 plan:
    1. Fork zama-ai/concrete (the Python compiler) to luxfhe/torus
    2. Rename Python module `concrete` → `torus`; PyPI publish as `torus-fhe`
    3. Update ml-sdk imports from `concrete.fhe` → `torus.fhe`, etc.
    4. Wire `torus.compiler` GPU dispatch through `luxcpp/gpu` vtbl
       (lux-private/gpu-kernels for CUDA/Metal/WebGPU/FPGA targets)
    5. Port concrete-cuda + concrete-mlir kernels to
       lux-private/gpu-kernels/{cuda,metal,wgsl}/ckks/ (matrix-vector
       mul, rescale, rotate, bootstrap for TorusML inference)

  Phase 3 plan (kernels):
    - CKKS/BGV/BFV GPU kernels in lux-private/gpu-kernels/
      (currently only TFHE PBS / keyswitch / blind-rotate exist)
    - FPGA bitstreams in lux-private/fpga/ (currently scaffold only)

Phase 1 = docs/branding sweep. PR not opened; user reviews and merges.
2026-05-29 13:53:42 -07:00

89 lines
2.8 KiB
Python

"""Tests for ReduceSum operator on a Torch model using leveled circuits."""
from functools import partial
import numpy
import pytest
from concrete.ml.pytest.torch_models import TorchSum
from concrete.ml.torch.compile import compile_torch_model
@pytest.mark.parametrize(
"data_generator",
[
pytest.param(partial(numpy.random.uniform, 0, 1), id="uniform"),
pytest.param(partial(numpy.random.normal, 0, 1), id="normal"),
pytest.param(partial(numpy.random.gamma, 1, 2), id="gamma"),
],
)
@pytest.mark.parametrize(
"keepdims", [pytest.param(keepdims, id=f"keepdims-{keepdims}") for keepdims in [True, False]]
)
# In TorusML, we consider that all inputs' first dimension should be a batch size
# even in single batch cases. This is why the following test parameters are considering axes that
# are sometimes equal to the input size's dimension, as the batch size is added within the
# test itself.
# Additionally, the axis parameter should neither be None nor contain axis 0 as this dimension is
# used for batching the inference
@pytest.mark.parametrize(
"n_bits, size, dim",
[
pytest.param(n_bits, size, dim, id=f"n_bits-{n_bits}-size-{size}-dim-{dim}")
for (n_bits, size, dim) in [
(20, (1,), (1,)),
(15, (50, 1), (1,)),
(20, (50, 1), (2,)),
(15, (10, 10, 50), (3,)),
(15, (5, 10, 10), (1, 3)),
]
],
)
def test_sum(
n_bits,
size,
dim,
keepdims,
data_generator,
default_configuration,
check_circuit_has_no_tlu,
check_r2_score,
):
"""Tests ReduceSum ONNX operator on a torch model."""
# Generate the input-set with several samples. This adds a necessary batch size
inputset = data_generator(size=(100,) + size)
# Create a Torch module that sums the elements of an array
torch_model = TorchSum(dim=dim, keepdim=keepdims)
# Compile the torch model
quantized_module = compile_torch_model(
torch_model,
inputset,
configuration=default_configuration,
n_bits=n_bits,
)
# Check if that the circuit is fully levelled
check_circuit_has_no_tlu(quantized_module.fhe_circuit)
# Take an input-set's subset as inputs
numpy_input = inputset[:5]
quantized_module.check_model_is_compiled()
# Compute the sum, in FHE or with simulation
computed_sum = quantized_module.forward(numpy_input, fhe="execute")
assert isinstance(computed_sum, numpy.ndarray)
# Compute the expected sum
expected_sum = numpy.sum(numpy_input, axis=dim, keepdims=keepdims)
assert computed_sum.shape == expected_sum.shape, (
f"Mismatch found in output shapes. Got {computed_sum.shape} but expected "
f"{expected_sum.shape}."
)
check_r2_score(expected_sum, computed_sum)