An open-source, cross-stack CKKS research framework with Python APIs, a typed PyTorch frontend, and native CPU and CUDA backends. Study program representation, cryptographic state, execution, runtime resources, and distributed systems independently or together through one inspectable value model.
python -m pip install --index-url https://download.pytorch.org/whl/cu130 "torch==2.13.0+cu130"
python -m pip install "scikit-build-core>=1.0.3" "cmake>=3.18" ninja
CMAKE_ARGS="-DFHELIUM_NATIVE_BACKENDS=CPU+CUDA" python -m pip install --no-binary=fhelium --no-build-isolation --no-cache-dir --verbose "fhelium==0.10.0"FHElium is under active development. APIs may change significantly between releases.
FHElium provides one hierarchical CKKS programming model with four entry levels: direct evaluator calls, tuned key and arithmetic schedules, mixed-dialect JIT Program objects, and GPU-rank partitioning. Every level reaches the same CkksEngine, core Ciphertext values, and exact CKKS state invariants.
import torch
import fhelium as fh
from fhelium.experimental import jit
def matrix_vector_quadratic(x, weight, bias, size, repeats):
result = x * torch.diagonal(weight).repeat(repeats)
for step in range(1, size):
diagonal = torch.diagonal(
torch.roll(weight, shifts=step, dims=1)
).repeat(repeats)
result += torch.roll(x, shifts=step, dims=-1) * diagonal
affine = result + bias.repeat(repeats)
return (affine + 0.25) * (affine - 0.5)
captured = jit.trace(
matrix_vector_quadratic,
inputs={
"x": jit.encrypted(),
"weight": jit.message(),
"bias": jit.message(),
"size": jit.static(8),
"repeats": jit.static(engine.num_slots // 8),
},
)
lowered = jit.default_pipeline().run(
captured.program, captured.workspace,
)
requirements = jit.analyze_evaluation_key_requirements(lowered.program)
evaluation_keys = fh.EvaluationKeySet(
rotations=fh.RotationKeySet({
step: engine.rotation_key(step)
for step in requirements.rotation_steps
}),
relinearization=engine.relinearization_key,
)
lowered.workspace.update({
"engine": engine,
"evaluation_keys": evaluation_keys,
})
ct_y = lowered.program.run(
ct_x, weight, bias, workspace=lowered.workspace,
)Move between these levels as the workload matures: prototype semantic tensor code, inspect the mixed-dialect program, tune the evaluator schedule, and compose rank-local values with typed collectives; all levels share the same encrypted value model. Continue to the Quickstart for direct CKKS evaluation, the JIT tutorial for capture, passes, and readiness, or the SPMD model for rank-local multi-GPU ownership and collective semantics.
Start with ordinary Python or typed PyTorch semantics, expose the encrypted graph and its CKKS mechanics, then carry the same evaluator into repeated and distributed execution. FHElium exposes the joints between layers: graph policy, ciphertext state, evaluator keys, resident artifacts, CUDA Graph capture, and rank-local placement remain independently inspectable and selectable.
Use the route builder to compare which decisions belong to authoring, graph policy, execution, and application-owned placement.
Write the evaluator beside ordinary Python, trace or import one mixed-dialect xDSL program, transform it with selected local passes, and execute only after an independent readiness check. The Program remains inspectable while its live materials, engines, keys, handlers, and caches remain in a retained workspace.
import torchimport fhelium as fhfrom fhelium.experimental import jitdef encrypted_quadratic(x, gain, bias, rotation): mixed = (x + torch.roll(x, shifts=rotation, dims=-1)) * gain return mixed * mixed + biascaptured = jit.trace( encrypted_quadratic, inputs={ "x": jit.encrypted(), "gain": jit.message(), "bias": jit.message(), "rotation": jit.static(3), },)source = captured.programworkspace = captured.workspacelowered = jit.default_pipeline().run(source, workspace)program = lowered.programworkspace = lowered.workspacefor report in lowered.reports: print(report.name, report.stats, report.diagnostics)key_plan = jit.analyze_evaluation_key_requirements(program)evaluation_keys = fh.EvaluationKeySet( rotations=fh.RotationKeySet({ step: engine.rotation_key(step) for step in key_plan.rotation_steps }), relinearization=( engine.relinearization_key if key_plan.requires_relinearization else None ),)workspace.update({ "engine": engine, "evaluation_keys": evaluation_keys,})ready = program.readiness(workspace)if not ready.runnable: raise jit.ProgramNotReadyError(ready)result = program.run(encrypted_x, 0.625, bias, workspace=workspace)requirements→Workspace bindings→readiness→Program.runThe resulting Program can be printed as textual IR, passed through another selected pipeline, or executed eagerly with bound runtime capabilities. PyTorch capture, textual import, custom passes, and backend handlers all use the same program class.
The same conventional cyclic-diagonal BSGS formulation measures both packed plaintext-matrix × ciphertext-vector (PT×CT) and ciphertext-matrix × ciphertext-vector (CT×CT) evaluation. View source