Repository navigation
Knots
Status: the value landed, the table did not. TorusKnot(p, q) exists and the
invariant heads and KnotCurve take it; KnotData is written up here and deliberately
not built.
The invariant heads took a braid. That is defensible — every knot is the closure of some braid — but it meant a knot could only be named by a presentation of it, and any knot with a closed form needed a second head to reach it:
| retired | what it was |
|---|---|
TorusKnotJones |
|
TorusKnotPolynomial |
|
TorusKnotCurve |
the points |
Both named their argument's presentation in the head, which does not scale: a figure-
eight knot or a pretzel knot would each want their own pair. And they were not even
buying speed — JonesPolynomial(TorusBraid(3,7)) and TorusKnotJones(3,7) returned the
same polynomial in the same 1–2 ms. They were a second spelling, not a fast path.
A knot is now a value in its own right, separate from any braid presenting it
(knot.ts):
type ClosedForm =
| { kind: "torus"; torus: { p: number; q: number } }
| { kind: "twist"; twist: { n: number } }
| { kind: "pretzel"; pretzel: { p: number; q: number; r: number } };
interface Knot {
braid?: Braid; // the closure it is, when a word exists
closed?: ClosedForm; // the closed form it was named by, when it was named by one
}Both fields are optional and at least one is present, because the two carry different
reach. torusBraid stops at 32 strands and needs SeifertGenus
answers for JonesPolynomial declines there
rather than answering something else. closed is a tagged union rather than a field per
family, so TwistKnot(n) and PretzelKnot(p, q, r) (the other knot families this package
added) slotted in without the record growing an optional field apiece — only the two that
also brought a closed-form Jones ever would have, and neither does.
knotOf resolves whatever names the knot — TorusKnot(p, q), TwistKnot(n),
PretzelKnot(p, q, r), FigureEightKnot(), a Braid, or a modular
The closed forms did not go away. They are still the independent check on the braid machinery — no braid, no bracket, no diagrams in them — and the tests assert that both routes through one head agree. That check got better, not worse: it now runs through the same public head rather than comparing two.
KnotData (a lookup keyed by knot name, deliberately not built) and the remaining loose
ends moved to Speculative Knots.