The Obligatory Contour Principle #
The categorical, strict-identity, single-tier OCP: the ban on two identical adjacent
autosegments on one tier ([Leb73], [McC86]), on a projected tier for IsCleanOn
([CJ19]). As a stringset the constraint is tier-based strictly local
(TSL₂, [HRT11]), characterised in OCP. The
fusion repair collapse is mathlib's
List.destutter (· ≠ ·) ([Gol76], [McCP95]) — a retraction onto
cleanness, input-strictly-local ([CH18]); the blocking repair block is
antigemination, a guard rather than a retraction ([McC86]).
Gradient, similarity-scaled OCP ([FPB04]) is a different object and lives in the thresholded-TSL substrate, not here.
Main definitions #
OCP.IsClean/OCP.IsCleanOn— OCP-cleanness, flat and on a projected tier.OCP.collapse— the fusion repair (OCP-merger normal form).OCP.block— the blocking repair (antigemination guard).
Main results #
collapse_eq_destutter— the fusion repair isList.destutter.collapse_clean/collapse_eq_self_iff—collapseis the retraction ontoIsClean.collapse_sublist— fusion never adds material.collapse_append—collapseis the OCP congruence: collapsing each operand before++is harmless, socollapsedescends to the OCP quotient of(List α, ++)(the quotient monoid and its presentation⟨α | a · a = a⟩live on theCore.Algebra.FreeMonoid.Destuttersubstrate; the autosegmental reading is inAutosegmental.Collapse).block_eq_self— antigemination: a rule is blocked when it would violate the OCP.
The constraint #
A tier is OCP-clean when no adjacent pair is identical. Adjacency-only, so
weaker than List.Nodup ([1, 2, 1] is clean). A reducible alias of the substrate
predicate List.IsChain (· ≠ ·), so the substrate's Monoid {l // l.IsChain (· ≠ ·)}
applies to OCP-clean tiers downstream.
Equations
- OCP.IsClean xs = List.IsChain (fun (x1 x2 : α) => x1 ≠ x2) xs
Instances For
OCP on the tier projected from xs by keeping p-elements and reading proj
(tier-relativity, [CJ19]); flat IsClean is the p = ⊤, proj = id case.
Equations
- OCP.IsCleanOn p proj xs = OCP.IsClean (List.map proj (List.filter (fun (a : α) => decide (p a)) xs))
Instances For
Equations
- OCP.decidableIsClean xs = xs.instDecidableIsChainOfDecidableRel
Equations
- OCP.decidableIsCleanOn p proj x✝ = OCP.decidableIsCleanOn._aux_1 p proj x✝
The fusion repair #
OCP-merger normal form (the fusion repair): collapse each maximal run of identical adjacent elements into one. Fusing identical autosegments returns that same autosegment, so the payload is unchanged.
Equations
- OCP.collapse xs = List.destutter (fun (x1 x2 : α) => x1 ≠ x2) xs
Instances For
collapse fuses a constant run into its single autosegment.
collapse fixes a tier iff it is OCP-clean; with collapse_clean, the retraction
onto IsClean.
Normal-form lemmas #
Fusion never adds material: the repair output is a sublist of the input.
The OCP congruence: collapse as a quotient homomorphism #
collapse descends to a homomorphism on the OCP quotient of (List α, ++): collapsing
each operand before appending is harmless. This is what makes the OCP-clean tiers under
fusion-concatenation (List.destutterConcat) the quotient (List α, ++)/OCP — bundled on
the Core.Algebra.FreeMonoid.Destutter substrate as FreeMonoid.destutterHom.
The blocking repair #
The substrate provides the OCP quotient monoid (OCP-clean tiers under fusion-concatenation,
List.destutterConcat) and its identification with the monoid presented by idempotent
autosegments ⟨α | a · a = a⟩
(Core.Algebra.FreeMonoid.Destutter). The autosegmental reading of that quotient — the
decategorification square against the categorical representation, contrasting the OCP (a
monoidal quotient) with the No-Crossing Constraint (a monoidal subcategory) — lives
downstream in Autosegmental.Collapse, which can see both Autosegmental.ncc_isMonoidal and
Autosegmental.ocp_not_isMonoidal.
Blocking ([McC86]'s antigemination): apply rule only when it would not
create an OCP violation, else leave the input untouched — a guard preventing a process,
not a retraction repairing its output.
Equations
- OCP.block rule xs = if OCP.IsClean (rule xs) then rule xs else xs