Transformation API
JAX-style composable transformations over the Alkahest kernel.
Tracing
trace(
pool: ExprPool,
*,
names: Sequence[str] | None=None,
domain: str='real'
) → Callable
Decorator that symbolically traces a Python function.
poolExprPoolThe expression pool to use for symbolic variables.
namessequence of str, optionalNames for the symbolic arguments. Inferred from the function signature when omitted.
domainstrDomain for the symbolic variables (
"real","complex"…).
- Callable
A decorator; when applied to a function it returns a
TracedFn.
>>> @alkahest.trace(p)
... def f(x, y):
... return x**2 + alkahest.sin(y)trace_fn(
fn: Callable,
pool: ExprPool,
*,
names: Sequence[str] | None=None,
domain: str='real'
) → TracedFn
Trace fn without using it as a decorator.
Equivalent to trace(pool, names=names, domain=domain)(fn).
Gradient
Note
gradhere is notsymbolic_grad.symbolic_grad()(seediff) takes anExprand variable list and returns symbolic partials.grad()below operates on aTracedFnfromtrace()and is composable withjit().
Return a new callable that computes the gradient of a TracedFn.
This is the JAX-style transform applied after trace(). It is not
symbolic_grad(), which takes an Expr and a
list of variables and returns symbolic partial expressions.
fnTracedFn or callable decorated withtrace()The function to differentiate.
wrtsequence of Expr, optionalVariables to differentiate with respect to. Defaults to all input variables of
fn.
- GradTracedFn
Callable returning
[∂f/∂wrt[0], ∂f/∂wrt[1], …]as floats at a point. Compose withjit()for LLVM-backed evaluation.
See also
symbolic_grad— partial derivatives of anExpr(noTracedFn).
JIT compilation
jit(fn: TracedFn | GradTracedFn | Callable) → CompiledTracedFn | CompiledGradTracedFn
JIT-compile a TracedFn or GradTracedFn using the LLVM backend.
fnTracedFn, GradTracedFn, or callable decorated withtrace()The forward function or its symbolic gradient to compile.
- CompiledTracedFn or CompiledGradTracedFn
Callables backed by LLVM JIT (or the Rust interpreter if
--features jitwas not enabled at build time).
Composing
Transformations stack freely:
# Compiled gradient
fast_df = alkahest.jit(alkahest.grad(f))
# Second derivative
d2f = alkahest.grad(alkahest.grad(f))
# Vectorised compiled gradient
import numpy as np
xs = np.linspace(0, 1, 1_000_000)
result = alkahest.jit(alkahest.grad(f))(xs, xs)TracedFn
class TracedFn(
expr: Expr,
pool: ExprPool,
symbols: list[Expr],
*,
names: list[str] | None=None
)
A symbolic function produced by tracing a Python callable.
The callable is invoked once with symbolic Expr arguments to
capture the computation graph. Subsequent numeric evaluations run through
the Rust interpreter or (if jit() is applied) the LLVM JIT.
exprExprThe symbolic output expression.
poolExprPoolThe expression pool that owns all nodes.
symbolslist[Expr]The symbolic input variables, one per positional argument.
Evaluate numerically.
Values may be plain Python floats or NumPy / JAX / PyTorch arrays.
When array inputs are detected, the call is automatically vectorised
via the batch path (same as numpy_eval()).
PyTree utilities
Flatten a nested structure into (leaves, treedef).
objany nested structure of Expr, list, tuple, or dict
leaveslistFlat list of
Exprleaves (in pre-order).treedefTreeDefOpaque structure descriptor; pass to
unflatten_exprs()to reconstruct the original container.
>>> leaves, td = alkahest.flatten_exprs([x**2, {"a": sin(y)}])
>>> len(leaves)
2Reconstruct a nested structure from leaves and treedef.
leaveslistFlat list of values (typically transformed
Exprobjects).treedefTreeDefStructure descriptor returned by
flatten_exprs().
The original nested structure with leaves replaced by the provided values.
Apply fn to every Expr leaf in a nested structure.
fncallableFunction
Expr → Exprapplied to each leaf.objany nested structureMay be a single
Expr, a list, tuple, or dict thereof — arbitrarily nested.
The same nested structure with every
Exprleaf replaced byfn(leaf).
>>> import alkahest
>>> p = alkahest.ExprPool()
>>> x = p.symbol("x")
>>> result = alkahest.map_exprs(lambda e: alkahest.diff(e, x).value, [x**2, alkahest.sin(x)])
>>> [str(r) for r in result]
['(2 * x)', 'cos(x)']Encodes the structure of a nested container so it can be reconstructed.
Internal representation: a flat list of node descriptors obtained by a
pre-order traversal of the tree. Leaves are represented by _Leaf()
instances.