You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
AI auto-implementation prohibited — This issue is for verification and documentation only. Do not auto-generate implementation PRs.
Background
With the DimExpr migration (#651, #653), the graph layer now supports shape-agnostic execution. A key use case is iterative tensor network algorithms (DMRG, ALS) where:
A computation graph is built incrementally across iterations
eval() is called mid-loop for convergence checks
After convergence, the entire loop is differentiated
Key insight
eval() is non-destructive — it compiles and executes the Fragment but does not consume or modify it. The TracedTensor remains connected to its graph after evaluation. This means:
Convergence checks via eval() do not break the graph
The user can continue building the graph after eval()
grad() can differentiate through the entire iterative computation
Pseudo-code to verify
let params = TracedTensor::from_tensor(/* ... */);letmut x = TracedTensor::from_tensor(/* initial value */);for _ in0..max_iter {// Build graph (each iteration extends the graph)let y = f(&x,¶ms);// Convergence check — eval() does NOT break the graphlet val = y.eval(&mut engine);ifconverged(&val){
x = y;// keep the TracedTensor, not the concrete valuebreak;}// Feed TracedTensor (not concrete Tensor) to next iteration// This keeps the graph connected
x = g(&y);}// Differentiate through the ENTIRE looplet loss = compute_loss(&x);let grad = loss.grad(¶ms);let grad_val = grad.eval(&mut engine);// grad_val contains gradients accumulated through all iterations
What to verify
Graph continuity: After y.eval(), y is still usable as a TracedTensor input to subsequent operations
Gradient correctness: loss.grad(¶ms) produces correct gradients through multiple iterations (compare with finite differences)
Graph deduplication: When both primal and gradient are evaluated, materialize_merge() deduplicates shared subexpressions via GlobalOpKey
Memory growth: Graph size grows linearly with iteration count (O(K × |f|) for K iterations)
Notes
Memory grows with each iteration (all intermediate Fragments are retained). This is the standard unrolled-through-time tradeoff.
For memory-constrained use cases, gradient checkpointing would be a future extension.
Caution
AI auto-implementation prohibited — This issue is for verification and documentation only. Do not auto-generate implementation PRs.
Background
With the DimExpr migration (#651, #653), the graph layer now supports shape-agnostic execution. A key use case is iterative tensor network algorithms (DMRG, ALS) where:
eval()is called mid-loop for convergence checksKey insight
eval()is non-destructive — it compiles and executes theFragmentbut does not consume or modify it. TheTracedTensorremains connected to its graph after evaluation. This means:eval()do not break the grapheval()grad()can differentiate through the entire iterative computationPseudo-code to verify
What to verify
y.eval(),yis still usable as aTracedTensorinput to subsequent operationsloss.grad(¶ms)produces correct gradients through multiple iterations (compare with finite differences)materialize_merge()deduplicates shared subexpressions viaGlobalOpKeyNotes
Fragments are retained). This is the standard unrolled-through-time tradeoff.DimExpr::Constvalues (const_dimpanics on symbolic values). This is a known limitation documented in feat: shape-agnostic graph with DimExpr (#651) #653.