Computation Graph Viz
Visualises a computation graph used in automatic differentiation. Nodes carry a kind — input, op, or output — and the renderer picks the shape that matches the role (rounded squares for tensor values, circles for operations). Edges encode dependencies; for an expression like z = (x + y) * sin(x) the component lays out the unfolded graph so each intermediate value sits at its topological rank.
Where DAGRenderer is the generic graph primitive (every node is a labelled circle), ComputationGraphViz is the typed-node specialisation built for teaching how autograd / backprop works at the per-node level.
Installation
npx shadcn@latest add https://craftbits.dev/r/computation-graph-viz.jsonUsage
import { ComputationGraphViz } from "@craft-bits/core";
const nodes = [
{ id: "x", kind: "input", label: "x", value: 1.5 },
{ id: "y", kind: "input", label: "y", value: 0.5 },
{ id: "add", kind: "op", label: "+", value: 2 },
{ id: "sin", kind: "op", label: "sin", value: 0.997 },
{ id: "mul", kind: "op", label: "×", value: 1.995 },
{ id: "z", kind: "output", label: "z", value: 1.995 },
] as const;
const edges = [
{ from: "x", to: "add" },
{ from: "y", to: "add" },
{ from: "x", to: "sin" },
{ from: "add", to: "mul" },
{ from: "sin", to: "mul" },
{ from: "mul", to: "z" },
] as const;
<ComputationGraphViz nodes={nodes} edges={edges} />Show backward-pass gradient labels by passing showGradients and supplying edge.label with the local derivative:
<ComputationGraphViz
nodes={nodes}
edges={[
{ from: "x", to: "add", label: "1" },
{ from: "y", to: "add", label: "1" },
{ from: "x", to: "sin", label: "cos(x)" },
{ from: "add", to: "mul", label: "sin(x)" },
{ from: "sin", to: "mul", label: "x + y" },
{ from: "mul", to: "z", label: "1" },
]}
showGradients
/>Highlight a specific path (e.g. the chain-rule branch from x to z through sin):
<ComputationGraphViz
nodes={nodes}
edges={edges}
highlightPath={["x", "sin", "mul", "z"]}
/>Understanding the component
- Typed nodes. Every node declares a
kind—"input","op", or"output"— and the renderer picks the shape that matches. Values are rounded squares, operations are circles, the output is an accent-filled circle. The reader can tell at a glance which nodes are data and which are computation. - Auto-layout via Kahn's algorithm. Each render computes one topological rank per node (longest-path layering) so dependencies always flow forward. Nodes at the same rank share a coordinate on the layout axis. Cycles throw with the unresolved ids in the message — autograd graphs are acyclic by contract.
- Forward values + backward gradients. When a node has a
value, it's drawn below the node in tabular-numbers. WhenshowGradientsis on and a node has agradient, it appears in the warning color near the node corner. Per-edgelabelstrings (typically the local derivative) render as italic warning-color labels at the edge mid-point — the same treatment as backward-edge labels inBackpropFlow. - Path highlighting. Pass
highlightPathas a sequence of node ids; the edges connecting consecutive entries pick up the accent color and the matching nodes gain an accent ring. Use it to narrate a single branch of the chain rule. - Same primitives as DAGRenderer. Arrowheads come from the shared
SvgDefsblock; the topological-layout maths is the same shape;SPRINGS.smoothdrives node entry; per-rank stagger usesSTAGGERfrom@craft-bits/core/motion. Reduced-motion users snap to the final state.
Props
| Prop | Type | Default | Description |
|---|---|---|---|
nodes | readonly { id; kind; label; value?; gradient? }[] | required | Graph nodes. kind is "input", "op", or "output". |
edges | readonly { from; to; label? }[] | required | Directed dependency edges. Must be acyclic. |
showGradients | boolean | false | Draw per-node gradients and per-edge labels in the warning color. |
highlightPath | readonly string[] | — | Sequence of node ids forming an active path. |
direction | "left-right" | "top-down" | "left-right" | Layout axis. |
className | string | — | Merged onto the outer <div> via cn(). |
Accessibility
- The figure is
role="figure"witharia-label="Computation graph visualization". - The inner
<svg>isrole="img"with anaria-labelsummarizing the nodes ("Computation graph with 6 nodes: x, y, +, sin, ×, z."). - Color is never the only signal — node shape (square vs circle) and the inner label distinguish data nodes from operation nodes, and value / gradient text appears beside each node.
- Motion respects
prefers-reduced-motion: node entries, edge draws, and the rank-stagger reveal all collapse to instant when the user has opted out.
Credits
- Extracted from:
craftingattention(app/src/lessons/primitives/viz/ComputationGraphViz.tsx). The original was tightly coupled to the project's streaming-data props — it parsedcomputation_graphdata from alatesthistory array, ran a custom DFS-driven layout per render, and rendered two bespoke modes (forward/backward) with a built-in play/pause/step/reset transport plus a hand-tuned speed select. The library version drops the streaming-data parser, the imperative play transport, and the two-mode split. Instead it accepts a plainnodes/edgespair, reuses the canonical Kahn's-algorithm layout (matchingDAGRenderer), and exposesshowGradients+highlightPathas declarative props so callers compose forward / backward / chain-rule narratives by passing different data — no internal state.