12 — Visualization and worked-steps traces¶
The mathematics¶
A quiver Q is a directed graph: vertices, and arrows (directed edges, possibly
loops or parallel). An algebra kQ/I is that graph plus a list of relations
(parallel-path linear combinations). To look at it we draw the graph and print
the relations beneath. To learn from a computation — a Hochschild cohomology,
say — we record the resolution chosen, each term, each differential as a matrix
over the working field, each rank, and the resulting dimensions, then lay them out
as a short worked example. Nothing here is new mathematics; it is the same
computation the engine runs, written down so a human can read it.
How it is represented¶
Layout. viz.layout.layout(quiver, relations) returns a LayoutData: a dict
positions from each vertex to an exact (x, y) (x an integer column depth, y
a Fraction row), a tuple of EdgeRoutes (straight or parallel, with a Fraction
bend), a tuple of LoopRoutes (integer base angle), and the relation strings.
Coordinates are int/Fraction on purpose: they never touch algebra, but keeping
them exact means the float-ban gate covers viz with no exemption, and the layout is
golden-testable to the last coordinate. For the commuting square
kQ/(a*b - c*d) the positions are
1 -> (0, 0) 2 -> (1, 1/2) 3 -> (1, -1/2) 4 -> (2, 0)
Trace events. A computation records a flat list of typed events (all plain
dataclasses): a Dispatch (which resolution, and why), one ResolutionTerm per
degree (its generator count), one RankStep per degree (the differential matrix
over the field, or a one-line elision note above 400 cells, plus its rank), and —
for the Chouhy–Solotar engine and the cup/bracket operations — AmbiguityEvent,
DifferentialEvent, and LiftStep. The list is capped at 5000 events so a deep
computation cannot blow up memory.
How the computation runs¶
- Layering (
viz.layout.layer). Compute strongly-connected components (iterative Tarjan), condense them, and take the longest path on the condensation — so a cycle or loop collapses to one column and every vertex gets an integer depth. Vertices in a column are centered on half-integer rows. - Drawing (
viz.draw.draw_quiver). Circles atpositions,FancyArrowPatchfor arrows (parallel bundles fan out viaConnectionStyle.Arc3(rad=<Fraction>)),Arcfor loops (integer angle), the relations as a text block below.tikzemits the identical layout as\node/\draw, so a paper and a screen agree. - Recording (
trace.recorder.Trace).A.hochschild_cohomology(top, verbose=…, trace=…)resolves verbosity (per-call overrides the globalquiverlab.verbose, defaultTrue), records the engine-choiceDispatch, and runs the engine with the recorder; the bar engine appends aResolutionTermand aRankStepat each degree. - Rendering (
trace.writer.write_trace). Write the self-contained, JavaScript-free, print-ready HTML report to./quiverlab_traces/HHc_<hash>.html(math typeset as MathML with the LaTeX source embedded for copy/paste; export to PDF via the browser's Print → Save as PDF) plus its JSON machine recordHHc_<hash>.json, and printWorked steps: quiverlab_traces/HHc_<hash>.html (…). (PDF/TeX report output has been removed.) The resulting dimensions in every rendering are derived from the recorded ranks (HH^n = dim C^n − rank_n − rank_{n-1}), so a golden test can assert the document's claims equal the engine's own.dims. - References. The engine's
routemaps (viatrace.provenance) to Plan 06 REGISTRY keys (e.g.bar); those resolve through Plan 06'sbibliography()(.keystuple + entry-view iteration exposing.key/.formatted/.bibtex_key) into(bibtex_key, formatted)lines in the document's References section. The result itself carries the mergedtable.references = self.citations()(the family + engine key union), which Plan 07 does not modify.
A worked micro-example — HH*(k[x]/(x²)) over ℂ¶
A = truncated_polynomial(2, field=CC) has dimension 2, so the normalized bar
complex has C^n = 2 for every n. Running A.hochschild_cohomology(2) records,
per degree, the 2×2 coboundary matrix and its rank:
d^0 = [[0,0],[0,0]] rank 0
d^1 = [[0,0],[2,0]] rank 1
d^2 = [[0,0],[0,0]] rank 0
so HH^0 = 2−0−0 = 2, HH^1 = 2−1−0 = 1, HH^2 = 2−0−1 = 1: dims [2, 1, 1].
Over GF(2) the 2 becomes 0, d^1 has rank 0, and the dims are [2, 2, 2] —
the classic characteristic pathology, visible directly in the traced matrix. These
numbers were produced by running the code (they are the golden trace).
Where to look in the code¶
| concept | file | function / class |
|---|---|---|
| layered layout, exact coords | src/quiverlab/viz/layout.py |
layout, layer, LayoutData |
| matplotlib rendering | src/quiverlab/viz/draw.py |
draw_quiver, Algebra.draw |
| TikZ rendering | src/quiverlab/viz/tikz.py |
tikz_quiver, Algebra.tikz |
| event taxonomy | src/quiverlab/trace/events.py |
Dispatch, ResolutionTerm, RankStep, DifferentialEvent, LiftStep, AmbiguityEvent, ReductionStep |
| recorder + elision | src/quiverlab/trace/recorder.py |
Trace, rankstep, resolve_verbose |
| engine emission | src/quiverlab/hochschild/bar.py |
hochschild_cohomology_dims |
| renderers | src/quiverlab/trace/render_text.py / render_html.py / render_json.py |
render_text, render_html, render_json, derive_dims |
| output path | src/quiverlab/trace/writer.py |
write_trace |
| provenance + References | src/quiverlab/trace/provenance.py |
references_for, resolve_references |