feat: rank successor decomposition, unit 1 of the transition (#107) - #162
feat: rank successor decomposition, unit 1 of the transition (#107)#162cameronfreer wants to merge 2 commits into
Conversation
Law-free structural split of the factor space into everything below rank n and
the layer at rank exactly n.
THE LAYER IS A BOOL-CUBE, NOT A DEPENDENT PRODUCT. `Π A : RankSupport S n,
ExactSpace A` would force every downstream conditional law to be a kernel into a
dependent product, and Mathlib has no countable dependent product of kernels:
there is no `Kernel.pi`, and the only `Π`-valued kernels are the Ionescu-Tulcea
trajectory kernels, which are ℕ-indexed chains whose source is the history
rather than a fixed common parameter. Since `ExactSpace A = ExactIndex A → Bool`
the dependent product is already a Bool-cube on `{i // (anchor i).card = n}`, so
the layer is defined directly that way.
Consequently no product kernel is needed downstream: a layer conditional law is
an ordinary `condDistrib` into a standard Borel space, and mutual conditional
independence supplies the finite products that finite-cylinder extensionality
consumes.
* `RankLayerIndex` / `RankLayerSpace` / `rankLayerMap`;
* `RelSignature.RankSupport`, `sigmaExactIndexEquiv`, and
`rankLayerMap_sigmaExactIndexEquiv` identifying each block with `exactMap A`;
* `lowerIndexSuccEquiv` / `lowerFactorSpaceSuccEquiv` — the split
`LowerFactorSpace (n+1) ≃ᵐ LowerFactorSpace n × RankLayerSpace n`;
* `lowerToBoundaryProjection`, definitionally compatible with `boundaryMap`;
* `rankSupportEquiv` / `rankLayerIndexEquiv` / `rankLayerSpaceEquiv`, with
`lowerIndexSuccEquiv_rankLayerIndexEquiv` the square against the split — NOT
definitional, since the split branches on `card < n` and the two sides' branch
conditions agree only after transporting cardinality through the image map.
`RelSignature.sigmaMap_injective` promoted from private to public rather than
copied a third time; rank is anchor cardinality, so every rank-indexed
construction needs it.
Audit 246 → 257 (both scripts). Build clean, census + axiom audit OK.
1. No injectivity wrapper. `Function.injective_id.sigma_map fun s => (σ s).injective`
is the Mathlib idiom, already used in `RelEqualityPattern`. The promoted
`sigmaMap_injective` is removed, and so are the two private duplicates in
`RelRankAlgebra` and `RelLowerFactor` — three copies down to none.
2. Structural API units 2/3 would otherwise recreate, all law-free:
* `rankLayerToExactProjection`, measurable, with
`rankLayerToExactProjection_rankLayerMap` definitional;
* naturality of that projection under `rankLayerSpaceEquiv`/`exactSpaceEquiv`;
* naturality of `lowerToBoundaryProjection` under
`lowerFactorSpaceEquiv`/`boundarySpaceEquiv`;
* `rankSupportEquiv_one`/`_mul` and `rankLayerSpaceEquiv_one`/`_mul`;
* naturality of `sigmaExactIndexEquiv`;
* the space-level successor square.
All are definitional. The space-level successor square is definitional even
though the index-level one is not: the space map is built from
`lowerIndexSuccEquiv.symm`, a `Sum.elim` that computes on constructors, so the
forward `dite` never appears.
`rankSupportEquiv` moved to the `RelSignature` namespace — it never mentions
the basis — and `card_image_sigmaMap` extracted as the shared rank-preservation
step.
3. Header corrected. "Everything else here is `rfl`" was literally false; it now
names the coordinate and projection compatibility lemmas that are definitional.
Audit 257 → 265 (both scripts; net of the removed wrapper). Build clean, census +
axiom audit OK.
|
Both items addressed in c179a8d. 1. No injectivity wrapper. You were right that nothing needed promoting. 2. Structural API. All six items added, all law-free, and all definitional:
One observation worth recording: the space-level successor square is definitional even though the index-level one is not. The space map is built from Two incidental cleanups while in there: 3. Header corrected. "Everything else here is Gates re-run on the new head: |
Unit 1 of the rank transition
n → n+1, per the design checkpoint on #107. Law-free: index types, equivalences and projections, no measure. #107 remains open.The layer is a Bool-cube, not a dependent product
This is the load-bearing choice and the reason unit 1 comes first. The obvious definition of the rank-
nlayer isΠ A : RankSupport S n, ExactSpace A. That would force every downstream conditional law to be a kernel into a dependent product, and Mathlib has no countable dependent product of kernels — noKernel.piunder that or any name; the onlyΠ-valued kernels are the Ionescu–Tulcea trajectory kernels, whose source is the historyΠ i : Iic a, X irather than a fixed common parameter.Since
ExactSpace A = ExactIndex A → Bool, the dependent product is already a Bool-cube:and that sigma index is
{i // (anchor i).card = n}. SoRankLayerIndex/RankLayerSpaceare defined directly as the Bool-cube, withsigmaExactIndexEquivrecording the bridge to the per-support view andrankLayerMap_sigmaExactIndexEquividentifying each block withexactMap A— byrfl, since both sides evaluate the same basis event at the same point.Countability and standard Borelness are then the same instances that already serve
LowerFactorSpace. Downstream, no product kernel is needed anywhere: a layer conditional law is an ordinarycondDistribinto a standard Borel space, and mutual conditional independence supplies exactly the finite products that finite-cylinder extensionality consumes.Contents
RankLayerIndex/RankLayerSpace/rankLayerMap, with measurability;RelSignature.RankSupportand the bridgesigmaExactIndexEquiv;lowerIndexSuccEquiv—LowerIndex (n+1) ≃ LowerIndex n ⊕ RankLayerIndex n, fromcard < n+1 ↔ card < n ∨ card = n— andlowerFactorSpaceSuccEquiv, the measurable splitLowerFactorSpace (n+1) ≃ᵐ LowerFactorSpace n × RankLayerSpace n.fst_lowerFactorSpaceSuccEquivandlowerFactorSpaceSuccEquiv_lowerFactorMapare bothrfl, so the split agrees with the existing rank nesting on the nose;lowerToBoundaryProjection— forA.card = n, the rank-nfactor reads the boundary atA, withlowerToBoundaryProjection_lowerFactorMapdefinitional as hoped;rankSupportEquiv/rankLayerIndexEquiv/rankLayerSpaceEquiv— the relabeling actions. LikelowerIndexEquivand unlikebasisIndexEquiv, these are automorphisms of one fixed type (the action transports anchors by an injective image map, so it preserves cardinality exactly), so the action laws are honest equalities of equivalences with no dependent transport.One square is not definitional
lowerIndexSuccEquiv_rankLayerIndexEquiv— the equivariance of the successor split — is notrfl, and the module header says so rather than leaving it looking like an oversight. The split is a case distinction oncard < nversuscard = n, hence adite, and the branch conditions on the two sides agree only after transporting anchor cardinality through the image map. Everything else in the file isrfl.One promotion
RelSignature.sigmaMap_injectivewas private inRelRankAlgebra;RelLowerFactoralready carries a private near-duplicate of it. Rather than add a third copy, this promotes the more general one (raw permutation family) to public. Rank is defined by anchor cardinality, so every rank-indexed construction needs the image map to be injective in order to see that the action preserves rank.Gates
lake build— 0 errors.scripts/check_census_and_axioms.py— census and axiom audit OK; the eleven new declarations use onlypropext,Classical.choice,Quot.sound.sorry/admit.Unit 2 (the rank-layer factorization) is next and is where the mathematical content sits; unit 3 stops for review before implementation, as agreed.