Skip to content

First polynomial graph

Create polynomial values, build a lazy expression, inspect the graph, and force concrete coefficients.

Before you start

Complete local setup. To run this program yourself, create poly_node.py from the Python example in the next section, then run:

uv run python poly_node.py

The example uses the Python backend.

Build and inspect the graph

from ren.poly import Poly
from ren.ring import RingSpec


ring = RingSpec(n=8, moduli=(17, 97))

a = Poly([1, 2, 3, 4, 0, 0, 0, 0], ring)
b = Poly([4, 3, 2, 1, 0, 0, 0, 0], ring)

result = (a + b) * 2

print("coefficients:", result.tolist())
print("node:", result.node)
coefficients: [10, 10, 10, 10, 0, 0, 0, 0]
node:  0  UNIQUE       0
 1  DEVICE       python
 2  BUFFER       [0, 1] size=8
 3  TO_RNS       [2]
 4  UNIQUE       1
 5  BUFFER       [4, 1] size=8
 6  TO_RNS       [5]
 7  ADD          [3, 6]
 8  CONST        [1] 2
 9  AS_RING      [8] coeff (n=8 q=<11b> moduli=2 dtype=u64)
10  MUL          [7, 9]

====== Summary ======
UNIQUE             2
BUFFER             2
TO_RNS             2
DEVICE             1
ADD                1
CONST              1
AS_RING            1
MUL                1

The output has two parts. coefficients shows the concrete result after realization. node shows the front-end graph before scheduling.

Read the graph from inputs to output:

  • BUFFER and TO_RNS are the two input polynomials encoded into RNS storage.
  • ADD is the lazy sum of those inputs.
  • CONST and AS_RING give the scalar 2 ring semantics.
  • MUL is still symbolic at the point the node is printed.

Force realization

The call to tolist() forces realization. In normal code, realize(), tobytes(), serialization, decryption, and JIT capture also turn lazy work into concrete buffers.

Separate graph construction from execution. Poly operations add to a Node DAG; backend work starts at a realization boundary.

Next

  • Polynomial engine explains rings, RNS storage, domains, nodes, constants, and views.
  • Execution pipeline explains how Ren schedules the graph as backend work.
  • Scheduling explains the pass order when you need to debug graph lowering.
  • Runtime explains memory planning, backend execution, copies, and JIT replay.