Skip to main content

HomOps Reference

HomAxisSum

Sum an encrypted value along one axis.

AsArithmetic
RunsServer
Changes shapeYes - the summed axis is removed, or kept at size 1
Changes scaleNo
Levels spent0
RotatesNo
KeysNone

What it does

HomAxisSum reduces a ciphertext by summing across one tensor axis, like .sum(dim=...). It is add-only: no multiplication, no rotations, no key, no levels. That makes it the cheap reduction, and the usual follow-up to an element-wise multiply: multiply, then sum the axis away.
It does not reduce the ciphertext slot axis (n_axis). For slot-axis summation use HomSumSlots. HomMul with axis_sum does a multiply and a tensor-axis sum in one step.

Signature

HomAxisSum(
    dim,               # required
    keep_dim=False,
)
No set_data.

Parameters

ParameterTypeDefaultDescription
dimintrequiredThe axis to sum, indexed on the ciphertext shape.
keep_dimboolFalseIf True, the summed axis stays in the shape with size 1 instead of being removed.

Rules that depend on the value

SettingRuleIf you break it
dimMust be a valid axis of the shape.Compilation fails.
dim = n axisNot supported. Reducing the packed slot axis is a slot operation: use HomSumSlots.Compilation fails.

Requirements

None beyond a valid dim. No key, no level headroom, no set_data.

Shape effect - yes

Rule: the summed axis is removed (keep_dim=False) or kept at size 1 (keep_dim=True). All other axes are preserved.
The n axis is marked in bold:
Input shapedimkeep_dimOutput shape
(16, 32, 128)1True(16, 1, 128)
(16, 32, 128)1False(16, 128)
(num_blocks, n_slots, record_dim)2True(num_blocks, n_slots, 1)
(num_blocks, n_slots)0False(n_slots,)
The packed slot axis cannot be the reduction axis; use HomSumSlots for that.

Scale effect - no

Summation is addition; the scale carries through unchanged.

Level budget

Zero. No mod-switch runs and there is no with_modswitch option.

Keys

None.

Example

The reduction steps of exact search. After the database multiply, one sum collapses the record dimension; after the squarings, another collapses the blocks:
pipeline.pyPYTHON
from lattica_build.client_ops import Repeat
from lattica_build.operators import (
    HomExpand, HomConstMul, HomAxisSum, HomSquare,
)
from lattica_build.base_classes.hom_pipeline import HomomorphicPipeline
from lattica_build.operators.composite.sequential import SequentialHomOp

pipeline = HomomorphicPipeline(
    client_pre=[Repeat()],
    hom=SequentialHomOp(
        HomExpand(k=64, k_axis=1, stage_sizes=[4, 4, 4], stages_per_level=3),
        HomConstMul(dims=db.shape, with_modswitch=True),
        HomAxisSum(dim=2, keep_dim=True),    # sum record_dim
        *(HomSquare(with_modswitch=True) for _ in range(2)),
        HomAxisSum(dim=0, keep_dim=False),   # sum num_blocks
    ),
    input_shape=(N_SLOTS,),
)
Shape and scale through the reduction tail:
Stagept_shapept_scale
After the multiply(B, S, R)grown by the multiply
After HomAxisSum(dim=2, keep_dim=True)(B, S, 1)unchanged
After the squarings(B, S, 1)grown, rescaled
After HomAxisSum(dim=0)(S,)unchanged

See also