Files
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

279 lines
11 KiB
Python

"""Implement DecisionTree models."""
from typing import Any, Dict, Union
import numpy
import sklearn.tree
from ..sklearn.tree_to_numpy import tree_to_numpy
from .base import BaseTreeClassifierMixin, BaseTreeEstimatorMixin, BaseTreeRegressorMixin
# pylint: disable-next=too-many-instance-attributes
class DecisionTreeClassifier(BaseTreeClassifierMixin):
"""Implements the sklearn DecisionTreeClassifier."""
sklearn_model_class = sklearn.tree.DecisionTreeClassifier
framework = "sklearn"
_is_a_public_cml_model = True
# pylint: disable-next=too-many-arguments
def __init__(
self,
criterion="gini",
splitter="best",
max_depth=None,
min_samples_split=2,
min_samples_leaf=1,
min_weight_fraction_leaf=0.0,
max_features=None,
random_state=None,
max_leaf_nodes=None,
min_impurity_decrease=0.0,
class_weight=None,
ccp_alpha: float = 0.0,
monotonic_cst=None,
n_bits: Union[int, Dict[str, int]] = 6,
):
"""Initialize the DecisionTreeClassifier.
# noqa: DAR101
"""
# Call BaseClassifier's __init__ method
super().__init__(n_bits=n_bits)
self.criterion = criterion
self.splitter = splitter
self.max_depth = max_depth
self.min_samples_split = min_samples_split
self.min_samples_leaf = min_samples_leaf
self.min_weight_fraction_leaf = min_weight_fraction_leaf
self.max_features = max_features
self.max_leaf_nodes = max_leaf_nodes
self.class_weight = class_weight
self.random_state = random_state
self.min_impurity_decrease = min_impurity_decrease
self.ccp_alpha = ccp_alpha
self.monotonic_cst = monotonic_cst
def __getattr__(self, attr: str):
# We directly expose the following methods as they are commonly used with decision trees
# and only represent their topological structure
if (
attr in ["get_depth", "get_n_leaves"]
and getattr(self, "sklearn_model", None) is not None
):
return getattr(self.sklearn_model, attr)
return super().__getattr__(attr)
def post_processing(self, y_preds: numpy.ndarray) -> numpy.ndarray:
# Here, we want to use BaseTreeEstimatorMixin's `post-processing` method as
# DecisionTreeClassifier models directly computes probabilities and therefore don't require
# to apply a sigmoid or softmax in post-processing
return BaseTreeEstimatorMixin.post_processing(self, y_preds)
def dump_dict(self) -> Dict[str, Any]:
metadata: Dict[str, Any] = {}
# TorusML
metadata["n_bits"] = self.n_bits
metadata["sklearn_model"] = self.sklearn_model
metadata["_is_fitted"] = self._is_fitted
metadata["_is_compiled"] = self._is_compiled
metadata["input_quantizers"] = self.input_quantizers
metadata["output_quantizers"] = self.output_quantizers
metadata["onnx_model_"] = self.onnx_model_
metadata["framework"] = self.framework
metadata["post_processing_params"] = self.post_processing_params
metadata["_fhe_ensembling"] = self._fhe_ensembling
# Scikit-Learn
metadata["criterion"] = self.criterion
metadata["splitter"] = self.splitter
metadata["max_depth"] = self.max_depth
metadata["min_samples_split"] = self.min_samples_split
metadata["min_samples_leaf"] = self.min_samples_leaf
metadata["min_weight_fraction_leaf"] = self.min_weight_fraction_leaf
metadata["max_features"] = self.max_features
metadata["max_leaf_nodes"] = self.max_leaf_nodes
metadata["class_weight"] = self.class_weight
metadata["random_state"] = self.random_state
metadata["min_impurity_decrease"] = self.min_impurity_decrease
metadata["ccp_alpha"] = self.ccp_alpha
metadata["monotonic_cst"] = self.monotonic_cst
return metadata
@classmethod
def load_dict(cls, metadata: Dict):
# Instantiate the model
obj = cls(n_bits=metadata["n_bits"])
# TorusML
obj.sklearn_model = metadata["sklearn_model"]
obj._is_fitted = metadata["_is_fitted"]
obj._is_compiled = metadata["_is_compiled"]
obj.input_quantizers = metadata["input_quantizers"]
obj.framework = metadata["framework"]
obj.onnx_model_ = metadata["onnx_model_"]
obj.output_quantizers = metadata["output_quantizers"]
obj._fhe_ensembling = metadata["_fhe_ensembling"]
obj._tree_inference = tree_to_numpy(
obj.sklearn_model,
numpy.zeros((len(obj.input_quantizers),))[None, ...],
framework=obj.framework,
output_n_bits=obj.n_bits["op_leaves"] if isinstance(obj.n_bits, Dict) else obj.n_bits,
fhe_ensembling=obj._fhe_ensembling,
)[0]
obj.post_processing_params = metadata["post_processing_params"]
# Scikit-Learn
obj.criterion = metadata["criterion"]
obj.splitter = metadata["splitter"]
obj.max_depth = metadata["max_depth"]
obj.min_samples_split = metadata["min_samples_split"]
obj.min_samples_leaf = metadata["min_samples_leaf"]
obj.min_weight_fraction_leaf = metadata["min_weight_fraction_leaf"]
obj.max_features = metadata["max_features"]
obj.max_leaf_nodes = metadata["max_leaf_nodes"]
obj.class_weight = metadata["class_weight"]
obj.random_state = metadata["random_state"]
obj.min_impurity_decrease = metadata["min_impurity_decrease"]
obj.ccp_alpha = metadata["ccp_alpha"]
obj.monotonic_cst = metadata["monotonic_cst"]
return obj
# pylint: disable-next=too-many-instance-attributes
class DecisionTreeRegressor(BaseTreeRegressorMixin):
"""Implements the sklearn DecisionTreeClassifier."""
sklearn_model_class = sklearn.tree.DecisionTreeRegressor
framework = "sklearn"
_is_a_public_cml_model = True
# pylint: disable-next=too-many-arguments
def __init__(
self,
criterion="squared_error",
splitter="best",
max_depth=None,
min_samples_split=2,
min_samples_leaf=1,
min_weight_fraction_leaf=0.0,
max_features=None,
random_state=None,
max_leaf_nodes=None,
min_impurity_decrease=0.0,
ccp_alpha=0.0,
monotonic_cst=None,
n_bits: Union[int, Dict[str, int]] = 6,
):
"""Initialize the DecisionTreeRegressor.
# noqa: DAR101
"""
# Call BaseTreeEstimatorMixin's __init__ method
super().__init__(n_bits=n_bits)
self.criterion = criterion
self.splitter = splitter
self.max_depth = max_depth
self.min_samples_split = min_samples_split
self.min_samples_leaf = min_samples_leaf
self.min_weight_fraction_leaf = min_weight_fraction_leaf
self.max_features = max_features
self.max_leaf_nodes = max_leaf_nodes
self.random_state = random_state
self.min_impurity_decrease = min_impurity_decrease
self.ccp_alpha = ccp_alpha
self.monotonic_cst = monotonic_cst
def __getattr__(self, attr: str):
# We directly expose the following methods as they are commonly used with decision trees
# and only represent their topological structure
if (
attr in ["get_depth", "get_n_leaves"]
and getattr(self, "sklearn_model", None) is not None
):
return getattr(self.sklearn_model, attr)
return super().__getattr__(attr)
def dump_dict(self) -> Dict[str, Any]:
metadata: Dict[str, Any] = {}
# TorusML
metadata["n_bits"] = self.n_bits
metadata["sklearn_model"] = self.sklearn_model
metadata["_is_fitted"] = self._is_fitted
metadata["_is_compiled"] = self._is_compiled
metadata["input_quantizers"] = self.input_quantizers
metadata["output_quantizers"] = self.output_quantizers
metadata["onnx_model_"] = self.onnx_model_
metadata["framework"] = self.framework
metadata["post_processing_params"] = self.post_processing_params
metadata["_fhe_ensembling"] = self._fhe_ensembling
# Scikit-Learn
metadata["criterion"] = self.criterion
metadata["splitter"] = self.splitter
metadata["max_depth"] = self.max_depth
metadata["min_samples_split"] = self.min_samples_split
metadata["min_samples_leaf"] = self.min_samples_leaf
metadata["min_weight_fraction_leaf"] = self.min_weight_fraction_leaf
metadata["max_features"] = self.max_features
metadata["max_leaf_nodes"] = self.max_leaf_nodes
metadata["random_state"] = self.random_state
metadata["min_impurity_decrease"] = self.min_impurity_decrease
metadata["ccp_alpha"] = self.ccp_alpha
metadata["monotonic_cst"] = self.monotonic_cst
return metadata
@classmethod
def load_dict(cls, metadata: Dict):
# Instantiate the model
obj = cls(n_bits=metadata["n_bits"])
# TorusML
obj.sklearn_model = metadata["sklearn_model"]
obj._is_fitted = metadata["_is_fitted"]
obj._fhe_ensembling = metadata["_fhe_ensembling"]
obj._is_compiled = metadata["_is_compiled"]
obj.input_quantizers = metadata["input_quantizers"]
obj.framework = metadata["framework"]
obj.onnx_model_ = metadata["onnx_model_"]
obj.output_quantizers = metadata["output_quantizers"]
obj._fhe_ensembling = metadata["_fhe_ensembling"]
obj._tree_inference = tree_to_numpy(
obj.sklearn_model,
numpy.zeros((len(obj.input_quantizers),))[None, ...],
framework=obj.framework,
output_n_bits=obj.n_bits["op_leaves"] if isinstance(obj.n_bits, Dict) else obj.n_bits,
fhe_ensembling=obj._fhe_ensembling,
)[0]
obj.post_processing_params = metadata["post_processing_params"]
# Scikit-Learn
obj.criterion = metadata["criterion"]
obj.splitter = metadata["splitter"]
obj.max_depth = metadata["max_depth"]
obj.min_samples_split = metadata["min_samples_split"]
obj.min_samples_leaf = metadata["min_samples_leaf"]
obj.min_weight_fraction_leaf = metadata["min_weight_fraction_leaf"]
obj.max_features = metadata["max_features"]
obj.max_leaf_nodes = metadata["max_leaf_nodes"]
obj.random_state = metadata["random_state"]
obj.min_impurity_decrease = metadata["min_impurity_decrease"]
obj.ccp_alpha = metadata["ccp_alpha"]
obj.monotonic_cst = metadata["monotonic_cst"]
return obj