Subdivision specifications on the CLOSED length orthant #
SubdivisionGraph.Spec carries length_pos : ∀ edge, 0 < length edge, so a
certificate written against it is valid only on the interior of the length
orthant. Every equal-genus contraction of the core therefore has to be
treated as a separate certificate target. This module introduces the
degenerate variant, whose lengths may vanish, so that a contraction target is
a face of a cone a certificate already covers rather than a new case.
The one thing that is not just "drop the field" #
Dropping length_pos from Spec and keeping Spec.graph verbatim gives the
wrong graph. A slot of length 0 emits no unit steps and no interior
vertices, so Spec.graph would delete it and leave its two endpoints as
distinct vertices. Metric degeneration contracts: a segment of length
zero identifies its endpoints. Deletion drops the genus by one per deleted
slot; contraction preserves it. A degenerate spec must therefore carry the
vertex identification explicitly, as an idempotent representative map rep.
Why no vertex weights are needed #
Write z for the number of zero slots. The graph below has
∑ length edges and #(image rep) + ∑ (length - 1) vertices, so
genus = #positiveSlots - #(image rep) + 1 .
Genus equals the core's p - n + 1 exactly when #(image rep) + z = n,
which is the field forest below. For the canonical representative map
generated by the zero slots, this is precisely the graphic-matroid statement
that the zero set is a forest. For an arbitrary bare DegSpec, however, the
cardinality equation alone does not prevent an unrelated extra
identification from balancing a redundant zero edge. Consumer interfaces
that mean an honest contraction must therefore require exact generation by
the zero slots or use a canonical union-find representative. Genus
preservation itself still follows from the displayed cardinality equation,
so no vertex weight is needed.
What is not defined here #
No rank, no winnable, no Riemann--Roch on a degenerate object. A DegSpec
has a graph : CFGraph and nothing else; all semantics remain on CFGraph.
The two bridges are
Subdivision data on the closed length orthant.
length may vanish. rep names the vertex identification produced by
collapsing the zero slots; forest is the genus-preserving cardinality
condition. Honest closed-face authoring interfaces use the canonical
union-find representative rather than treating an arbitrary rep as a
contraction.
- core : ExplicitPotential.Core n p
The ordered core whose slots are subdivided when positive and contracted when their lengths vanish.
The natural-number length of each slot; zero denotes contraction of its endpoints.
Canonical representative of a core vertex after collapsing zero slots.
- rep_zero (e : Fin p) : self.length e = 0 → self.rep (self.core.tail e) = self.rep (self.core.head e)
A vanishing slot identifies its two endpoints: this is contraction, not deletion.
- rep_loopless (e : Fin p) : 0 < self.length e → self.rep (self.core.tail e) ≠ self.rep (self.core.head e)
A surviving slot is not a loop after the contraction.
The Euler-characteristic equation for genus preservation. When
repis the canonical quotient generated by the zero slots, this is exactly the assertion that those slots form a forest; seegenus_graph.
Instances For
The vertex and step types #
The left vertex of a unit step, using the tail core class at the initial step.
Equations
- d.stepLeft e o = if hzero : ↑o = 0 then d.coreVertex (d.core.tail e) else d.interiorVertex e ⟨↑o - 1, ⋯⟩
Instances For
The degenerate subdivision graph. Zero slots emit nothing; their
endpoints have already been identified by rep.
Equations
- One or more equations did not get rendered due to their size.
Instances For
Path positions #
The chip-position trichotomy. On a Spec a certificate may get away with a
two-case split (offset = 0 versus offset > 0, the latter always interior)
whenever the offset is strictly below the slot length — a bound that
usually comes from length_pos. On the closed orthant the third case,
offset = length, is reachable and must be present.
Decode a slot position as its tail, interior, or head vertex; a zero-length slot has a single contracted endpoint.
Equations
- d.pathVertex e k = if hzero : ↑k = 0 then d.coreVertex (d.core.tail e) else if hlast : ↑k = d.length e then d.coreVertex (d.core.head e) else d.interiorVertex e ⟨↑k - 1, ⋯⟩
Instances For
A path position clamped into range. On a slot the certificate actually uses this is the identity; it exists so that a generic statement can name a position on every slot without carrying a bound for the slots it ignores.
Instances For
The path vertex at a clamped position, total in the natural number k.
This is the form a row proof should use throughout. pathVertex is indexed by
Fin (length e + 1), so naming a position costs a bound proof at every
occurrence; on the closed orthant those bounds are exactly the ones that stop
being free. pathAt carries none: positions beyond the end of the slot are
clamped to the head, which is where a chip pushed off the end belongs.
It lives here rather than beside its first consumer because the two consumers
sit on independent branches of the tower: ramp scripts read chips off it, and
Certificate/ScaleQReduced.lean walks along it.
Equations
- d.pathAt e k = d.pathVertex e (d.clampPos e k)
Instances For
Multiplicities #
Fibre regrouping #
The transferable half of a symbolic certificate. Every quantity a
SlopeScript-style certificate computes at a core vertex is an
endpoint-indicator sum over slots. On the contracted core such a sum is the
sum, over the members of one collapsed class, of the uncontracted sums —
so a row's per-core-vertex lemmas are reusable at every face by addition
instead of being reproved per face.
A vanishing slot contributes nothing to a contracted endpoint sum, because its two endpoints lie in the same class and its two endpoint contributions are equal and opposite. This is why a certificate's per-slot data may be summed over all slots of the uncontracted core, zero ones included.
The face-equals-contraction-target correspondence #
Matching data identifying a DegSpec with the strictly positive Spec
on its contracted core. All four maps are pure index bookkeeping; no lengths
change. Slot reorientation is deliberately not included: it is already
supplied by SubdivisionGraph.Spec.Relabeling, which composes with the
LaplacianEquiv produced here.
Which uncontracted core vertex represents each target vertex.
- vtx_inj : Function.Injective self.vtx
Which uncontracted slot each target slot is.
- slot_inj : Function.Injective self.slot
Instances For
Core-vertex half of the vertex bijection.
Instances For
Interior half of the vertex bijection.
Instances For
Vertex bijection of the correspondence.
Equations
- c.vertexEquiv = (Equiv.ofBijective c.classMap ⋯).sumCongr (Equiv.ofBijective c.interiorMap ⋯)
Instances For
The bijection from unit steps in the positive contracted presentation to surviving unit steps in the closed presentation, preserving offsets.
Equations
- c.stepEquiv = Equiv.ofBijective c.stepMap ⋯
Instances For
The correspondence. A face of the closed orthant whose zero set is a forest carries the same Laplacian as the strictly positive subdivision of the contracted core.
Equations
- c.laplacianEquiv = { toEquiv := c.vertexEquiv, num_edges_eq := ⋯ }
Instances For
The graph isomorphism from the positive contracted-core subdivision to the closed-face graph, preserving edge multiplicities.
Equations
- c.graphIso = { vertexEquiv := c.vertexEquiv, map_num_edges := ⋯ }
Instances For
The translation lemma: strictly positive lengths #
At a strictly positive length vector the forest field forces rep to be
the identity: there are no zero slots, so rep has n values, hence is
surjective, hence bijective, hence — being idempotent — the identity.
The identity matching, exhibiting a strictly positive DegSpec as its own
Spec.
Equations
Instances For
Translation lemma. Whatever a certificate proves about the degenerate
graph at a strictly positive length vector, it proves about the genuine
SubdivisionGraph.Spec subdivision there.
Equations
- d.laplacianEquivToSpec hpos = (d.toSpecContraction hpos).laplacianEquiv
Instances For
Core-supported divisors on a face #
Push arbitrary core weights to contracted core classes. A class carries the sum of its members' weights and subdivision-interior vertices carry zero.
Equations
- d.coreClassDivisor weight (Sum.inl c) = ∑ v : Fin n with d.rep v = ↑c, weight v
- d.coreClassDivisor weight (Sum.inr _interior) = 0
Instances For
Nonnegative source weights remain effective after classes are merged.
A chip survives contraction. If the weights are nonnegative and c
carries one, then the sum over c's contracted class is at least one: the
other members of the class can only add.
This is the one fact every guarding row needs about its own chip vertices, and
it was written out by hand — the same Finset.single_le_sum argument — in each
of them. It is stated at the class sum rather than at coreClassDivisor
because a row whose divisor carries interior chips as well (GenusFiveRow05,
GenusFiveRow08, GenusFiveRow10) reduces to a class sum of a combined
weight, not to a bare coreClassDivisor.
The coreClassDivisor reading of one_le_classSum_of_chip. This is the
form Guarding.GuardingSet.one_le_divisor_of_chip is a corollary of.
Contracting core classes preserves the total core weight.