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:
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:
BUFFERandTO_RNSare the two input polynomials encoded into RNS storage.ADDis the lazy sum of those inputs.CONSTandAS_RINGgive the scalar2ring semantics.MULis 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.