14 — The derived-category surface¶
What this computes¶
derived/ (Plan 43) is the bounded derived category D^b(mod A) made computable, for a
finite-dimensional A = kQ/I. It reifies morphisms Hom_{D^b}(X, Y[n]) as honest chain
maps, computes the derived Auslander–Reiten translate τ_{D^b} = ν[−1] on perfect
complexes, verifies tilting complexes and builds their endomorphism algebra End(T)
(the Rickard derived-equivalent algebra), and assembles a necessary-condition derived
fingerprint. It is a thin exact-linear-algebra layer over P37 (End/ModuleHom), P38
(Cartan/Coxeter), P39 (complexes / hyper-Hom) and P41 (Nakayama / corner-transpose) — no
new math engine, public surface only.
The whole surface is honest about a hard fact: deciding derived equivalence is not algorithmic. Everything here is a verifier or a necessary-condition invariant; nothing claims to decide equivalence.
Complex conventions (modules/complexes.py, the P39 substrate)¶
ChainComplex(terms, dmats, check=True) is homological: d_n: C_n → C_{n-1}, with
each differential matrix written rows = target C_{n-1}, columns = source C_n —
byte-identical to modules.resolution. A missing degree is the zero module; cohomological
indexing is presentation-only (C^n := C_{-n}). Construction is self-certifying: check
validates each d_n as a ModuleHom and asserts every composite d_n ∘ d_{n+1} is zero
(loud otherwise). shift(k) sends degree n to n − k and multiplies each differential
by (-1)^k; truncate, homology_dims, and homology(n) = Z_n/B_n follow. A
ChainMap(src, tgt, components, check=True) validates each component as a module map and
that every square commutes (d^tgt f_n = f_{n-1} d^src); .then(g) is left-to-right
composition. The Weibel sign for the Hom total complex is
Hom^n(X, Y) = ⊕_p Hom_A(X_p, Y_{p-n}) with (δf)_p = d^Y f_p − (-1)^n f_{p-1} d^X; the
homology dims are sign-independent (Weibel ε = -1 and ε = +1 give isomorphic cochain
complexes), and the code takes ε = -1.
Reified hyper-Hom (homs.py)¶
hyper_hom_basis(X, Y, n) returns a list of ChainMaps that is a basis of
H^n(Hom^•(X, Y)); for X perfect this is Hom_{D^b(mod A)}(X, Y[n]). The reification is
exact: a class in Hom^n(X, Y) has components f_p: X_p → Y_{p-n} landing in
Y.shift(n).term(p), and its cocycle condition is precisely the chain-map square for
X → Y[n] — so ChainMap(X, Y.shift(n), comps, check=True) passes on a cocycle and fails
on a non-cocycle. Each returned map is built from a canonical coset representative of
ker(δ^n) / im(δ^{n-1}): _coset_reps picks classes with independent_modulo, then
_reduce_mod_span subtracts only coboundary-span vectors (an RREF reduction that keeps a
cocycle a cocycle) — the free-variables-zero canonicalization adapted to a column span,
deliberately not reduce_mod_nullspace(r, transpose(B)), which would move r out of
the kernel. A self-cert closes the loop: the reified class count must equal
hyper_hom_dims(X, Y, n), else it raises.
The derived AR translate (tau.py)¶
τ_{D^b} = ν[−1] where ν = D Hom_A(−, A) is the Nakayama functor, applied termwise on
a perfect (projective) complex: each projective term ⊕P_v maps to
ν(⊕P_v) = D Hom_A(⊕P_v, A) = D(⊕Ae_v) = ⊕I_v, each differential to its ν-image via the
shared corner-transpose (_corner.py::corner_transpose — the one shared
implementation, which duality._presentation_transpose delegates to), and the whole
complex is then shifted by −1.
tau_Db_minus is the inverse, ν^{-1}[+1], on a perfect complex of injectives (the output
shape of tau_Db); the round-trip tau_Db_minus(tau_Db(X)) is certified a quasi-iso.
Two design facts:
- Happel's finite-gl.dim guard. The Serre functor / AR triangles of
D^b(mod A)exist iffgl.dim A < ∞._require_finite_gldim(A)readsglobal_dimension(A)and refuses loudly unless it is certified finite (g.exact);k[x]/(x²)is the pinned negative case.tau_Dbalso refuses a non-perfect input (resolve withprojective_modelfirst). - Basis discipline (the P39/P41 mismatch rule). The injective terms are built as
dualize(Hom_A(term, A))— exactly whatnakayama_functorproduces — so their k-basis is byte-consistent with the corner-transpose differentials; abuilders.injectivebasis is never mixed with a corner-transpose basis. Kind-tagged provenance (_term_provenance = ("injective"|"projective", …)) stops a projective complex from masquerading as injective fortau_Db_minus, and vice versa. Correctness never rests on the bookkeeping: the output self-certifies (ChainComplex(check=True)givesd∘d = 0) and is pinned against the trusted moduleτ.
The K₀ arbiter is the identity χ(τ_{D^b} X) = c · χ(X) with c = −C · C^{-ᵀ} (the
K₀-action Coxeter matrix). This is deliberately not P38's coxeter_matrix
(= −C^{-ᵀ} C, its conjugate — same characteristic polynomial, different action), and it
pins the whole termwise ν bookkeeping against the concrete module τ on kA₂/kA₃.
Tilting verifier and End(T) (tilting.py)¶
is_tilting_complex(summands) is a verifier for a given list of perfect summands — it
decides, it never searches. It returns a TiltingReport (is_tilting, rigid,
generates, window, g_matrix, det) built from two checks:
- Rigidity —
Hom_{D^b}(T, T[n]) = 0for alln ≠ 0, scanned over the exact window outside which hyper-Hom is provably the zero cochain group; the window is reported honestly in.window. - Generation of
K^b(proj A)— the K₀ g-matrix (rows = summand Euler characteristicsχ) must be square and unimodular (det = ±1).
is_tilting = rigid and generates (Rickard). end_algebra_of_complex(summands) builds
End_{D^b}(T) = ⊕_{i,j} Hom_{D^b}(T_i, T_j) as a structure-constant Algebra — the
degree-0 hyper-Hom classes composed with ChainMap.then, reduced to canonical homotopy
representatives, handed to Algebra.from_structure_constants(..., check=True) (associativity
and unit validated). corner_cartan_of_complex is the corner-Cartan of End(T) (the entry
at row i, column j is dim_k Hom_{D^b}(T_j, T_i)), whose orientation is pinned by the
T = A oracle (corner_cartan_of_complex(A) = cartan_matrix(A),
End(A_A) ≅ A). two_term_silting_from_presentation(M) returns the 2-term complex
P_1 → P_0 of M with its rigidity report — the bridge the P45 τ-tilting engine consumes
(a single object has generates = False by design; the consumer reads .rigid plus the
g-vector, not .is_tilting).
The fingerprint — what it is, and is not (fingerprint.py, block.py)¶
derived_fingerprint(A, top=4) returns a dict of necessary-condition derived
invariants: coxeter_polynomial, cartan_det, cartan_smith (the GL_n(ℤ)-equivalence
invariant factors — coarser than ℤ-congruence, and the docstring says so), the Hochschild
hh_cohomology_dims / hh_homology_dims, cyclic_dims, center_dim, and gl_dim. Every
field is wrapped by _field, which captures a QuiverlabError (including a DepthLimitError
blow-up of the generic cyclic-homology mixed complex off GF(p)) as {"error": …} — an honest
per-field non-answer, never a crash.
compare_fingerprints(fa, fb) speaks only in "distinguished" /
"not distinguished by these invariants" — never "(in)equivalent". Equal fingerprints
are a necessary, not sufficient, condition: the 8-vertex cospectral trees are the pinned
counterexample (equal Coxeter polynomial, Cartan, HH and centre, yet not derived
equivalent). A field that errored on either side is surfaced in incomparable_fields, never
silently dropped. The fingerprint is never a decider — that is the whole honest-scope
point.
block.py::derived_fingerprint_block(A, top=4) is the single-algebra derived_fingerprint
scalar compute kind (schema v1), built once so all three runners return byte-identical
blocks; its scope string states "equal values are a necessary condition for derived
equivalence, not a proof". The two-algebra compare panel is deferred to a post-release
successor (it needs a second-algebra request field — a schema change); see the
v0.2.0 GUI-deferral ledger.
The oracles¶
- Self-cert —
ChainMap(check=True)on every reified class,ChainComplex(check=True)for everyτ_{D^b}output (d∘d = 0), the class-count= hyper_hom_dimsidentity, thetau_Db_minus ∘ tau_Dbquasi-iso round-trip, the honest per-field fingerprint errors, andfrom_structure_constants(check=True)forEnd(T). - Cross-engine —
hyper_hom_basiscount= A.ext(M, N, n)on a projective-resolution source;τ_{D^b}of a non-projective module concentrated in degree 0 and isomorphic to the trusted moduleτover kA_n. - Literature — the K₀ identity above; the kA₂ APR tilt
P_1 ⊕ S_1is tilting withEnd(T)the reoriented A₂ (= A^op); D₄ vs A₄ distinguished by the Coxeter polynomial; the cospectral-trees non-distinction. - Live QPA — a probe-first battery:
TauOfComplexon aProjectiveResolutiondoes not script cleanly through libgap (the P39 Ch. 10 complex-scripting hazard), so the crosscheck falls back to the documented module-level route (τ_{D^b}homology in degree 0 vs QPADTr(M)), recording exactly what was compared — never a silent skip.
Where to look in the code¶
| concept | file | function / class |
|---|---|---|
| bounded complexes, chain maps, cones | modules/complexes.py |
ChainComplex, ChainMap, hyper_hom_dims, projective_model |
| reified hyper-Hom classes | derived/homs.py |
hyper_hom_basis |
the corner-transpose Hom_A(−, A) |
derived/_corner.py |
corner_transpose |
derived AR translate τ_{D^b} / inverse |
derived/tau.py |
tau_Db, tau_Db_minus, _require_finite_gldim |
tilting verifier, End(T), corner-Cartan |
derived/tilting.py |
is_tilting_complex, TiltingReport, end_algebra_of_complex, corner_cartan_of_complex, two_term_silting_from_presentation |
| the necessary-condition fingerprint | derived/fingerprint.py |
derived_fingerprint, compare_fingerprints |
the derived_fingerprint block |
derived/block.py |
derived_fingerprint_block |