Skip to main content

HomOps Reference

HomPolyEval

Fit and evaluate a function approximation on an encrypted value.

PePolynomials
RunsServer
Changes shapeNo
Changes scaleYes - grows through the evaluation
Levels spentSeveral - grows with the degree
RotatesNo
KeysSquare key

What it does

HomPolyEval is a helper that fits a Chebyshev polynomial to a callable func at a chosen degree, then evaluates that approximation on every ciphertext element. This is how smooth nonlinearities run on encrypted data.
The evaluation uses a baby-step / giant-step schedule, so a degree-d polynomial costs far fewer multiplications than d, but it is still deep: expect it to spend several levels, more for higher degrees.
For already-computed Chebyshev coefficients, use the registered leaf HomPolyEvalBase instead.
ClassWhat it approximates
HomPolyIndicatorAn indicator: 1 near a target value, 0 elsewhere. Used to select matches in search pipelines.
HomPolyThresholdA step: 0 below a margin, 1 above it. Variants sigmoid, piecewise_linear, minimax.
Both construct polynomial approximations with their coefficients computed for you from the degree and shaping parameters.

Signature

HomPolyEval(
    func,               # required: callable to approximate on the domain
    degree,             # required: Chebyshev degree
    left=-1,
    right=1,
    tol=1e-8,
    plot=False,
    rows_budget=None,
)
The variants take the degree instead of coefficients:
HomPolyIndicator(deg, right=4, tol=1e-8, rows_budget=None)

HomPolyThreshold(deg, variant='sigmoid', margin=(0.4, 0.6),
                 tol=1e-5, out_val=1, domain_start=-1, rows_budget=None)
No set_data; this helper fits coefficients at construction. Use HomPolyEvalBase when you need to supply coefficients directly.

Parameters

ParameterTypeDefaultDescription
funccallablerequiredFunction to approximate on the configured domain.
degreeintrequiredDegree of the Chebyshev approximation fitted to func.
left, rightint-1, 1Domain passed to the fit and evaluation.
tolfloat1e-8Skip near-identity rescale factors while evaluating.
plotboolFalseShow a debug plot when fitting the approximation.
rows_budgetsequenceNoneRestricts which levels the internal mod-switches may spend, by absolute row index. See rows_budget.
HomPolyThreshold adds: variant (the curve family), margin (where the step happens), out_val (the high value), domain_start.
Rules that depend on the value
SettingRuleIf you break it
left, rightThe actual input values must lie inside [left, right]. The polynomial is only a valid approximation on its domain; values outside it produce garbage, silently.Wrong results, not an error. Check the range your previous ops can produce.
left, rightA domain other than [-1, 1] adds an affine remap step before evaluation, which can cost one extra mod-switch.-
rows_budgetAt least one listed row must be droppable at each internal mod-switch.Compilation fails if none are eligible.

Requirements

  • Input in domain. The single most important rule for this operator: whatever arrives must fit in [left, right]. This is a numerical requirement the compiler cannot check for you.
  • Square key. The internal Chebyshev multiplies are ciphertext multiplies; any pipeline with a HomPolyEval needs the square key (generated for you during key generation).
  • Level headroom. The deepest operator here. Budget several levels and verify with the compile-time simulation before deploying; see Level budget.

Shape effect - no

The output shape equals the input shape; the polynomial is applied element by element.

Scale effect - yes

Scale grows through the evaluation and is paid down by the internal mod-switches as it goes; the final scale depends on the degree and the mod-switch schedule. You don't manage this step by step. What you do is check the compiled result: the pipeline's compile-time simulation reports the output scale, and that is the number to plan the next operator around.
How scale moves through a pipeline is on Ciphertext state - Scale.

Level budget

HomPolyEval spends levels at several points inside:
PhaseLevels
Domain remap to [-1, 1]0 or 1, only when [left, right] is not [-1, 1]
The evaluation itself (baby steps, giant steps, recursion)Several; grows with the degree
The exact count for a given degree is settled at compile time; verify it with the compile-time simulation rather than estimating by hand. Optionally pin drops with rows_budget:
pipeline.pyPYTHON
HomPolyIndicator(deg=80, rows_budget=[0, 1, 3, 4, 5, 6])
How primes are organized in the chain is explained on Level budget - The chain.

Keys

Square key (relinearization key). The Chebyshev evaluation multiplies ciphertexts by ciphertexts, so every multiply is followed by a relinearization. Generated for you during key generation. No rotation key.

Example

Threshold in a search pipeline

After inner products, turn similarity scores into a 0/1 selection:
pipeline.pyPYTHON
from lattica_build.operators import HomPolyThreshold
from lattica_build.base_classes.hom_pipeline import HomomorphicPipeline
from lattica_build.operators.composite.sequential import SequentialHomOp

ROWS_BUDGET = [0, 1, 3, 4, 5, 6]

pipeline = HomomorphicPipeline(
    hom=SequentialHomOp(
        HomPolyThreshold(deg=80, variant='sigmoid', rows_budget=ROWS_BUDGET),
    ),
    input_shape=(128,),
)
The other variants differ only in the curve:
pipeline.pyPYTHON
HomPolyThreshold(deg=80, variant='piecewise_linear', rows_budget=ROWS_BUDGET)

HomPolyThreshold(deg=80, variant='minimax',
                 margin=(0.45, 0.9), out_val=1, domain_start=-0.5,
                 rows_budget=ROWS_BUDGET)

Custom coefficients

For precomputed Chebyshev coefficients, construct HomPolyEvalBase:
pipeline.pyPYTHON
import numpy as np
from lattica_build.operators import HomPolyEval, HomPolyEvalBase
import torch

# Helper: fit Chebyshev coeffs from a callable
HomPolyEval(lambda x: np.maximum(x, 0), degree=16, left=-1, right=1)

# Leaf: supply coeffs directly via HomPolyEvalBase
coefs = torch.randn(64)          # degree 63
HomPolyEvalBase(coefs, left=-2, right=2)
The inputs must genuinely lie in [-2, 2] for the result to be meaningful.

See also