The compressed-block budget along a consumption route #
Unary push/pop stretches of a chosen consumption route may be compressed into one index block. Crossing a binary node ends the current stretch and starts another one. Thus the number of maximal binary-free chunks is one plus the number of binary barriers on the route.
barrierOwners already charges every barrier to a distinct terminal in the off-route child.
The missing final charge is a terminal in the child followed by the route. Adding this owner
makes the bound sharp: the number of chunks, rather than merely the number of barriers, is at
most the terminal yield length.
A terminal position that stays inside the branch followed by a consumption route.
Equations
- route.binaryLeft.followedOwner = IndexedGrammar.NFParse.ConsumeRoute.embedLeft u v route.followedOwner
- route.binaryRight.followedOwner = IndexedGrammar.NFParse.ConsumeRoute.embedRight u v route.followedOwner
- IndexedGrammar.NFParse.ConsumeRoute.popHere.followedOwner = ⟨0, ⋯⟩
- route.popTail.followedOwner = route.followedOwner
- route.push.followedOwner = route.followedOwner
Instances For
The on-route terminal owner is disjoint from every off-route barrier owner.
The terminal followed by the route together with all off-route charges is duplicate-free.
There is room for both every binary barrier and the final followed branch in the yield.
Number of maximal binary-free chunks on a consumption route. Unary constructors stay in the current chunk; each binary constructor starts exactly one further chunk.
Equations
- route.binaryLeft.noBinaryChunkCount = route.noBinaryChunkCount + 1
- route.binaryRight.noBinaryChunkCount = route.noBinaryChunkCount + 1
- IndexedGrammar.NFParse.ConsumeRoute.popHere.noBinaryChunkCount = 1
- route.popTail.noBinaryChunkCount = route.noBinaryChunkCount
- route.push.noBinaryChunkCount = route.noBinaryChunkCount
Instances For
Chunk count is precisely one plus the existing barrier count.
A route is one maximal chunk exactly when it is binary-free.
The number of compressed blocks needed by the maximal binary-free decomposition is bounded
by the terminal yield. This is the index-payload inequality needed by ScheduleInvariant.
Prefix truncation of a chosen consumption route #
Follow the same branch choices only as far as a shallower inherited occurrence. This is a structural truncation, not a fresh classical choice of route, so it preserves the absence of binary barriers.
Equations
- One or more equations did not get rendered due to their size.
- inner.binaryLeft.truncate j hjk = (inner.truncate j hjk).binaryLeft
- inner.binaryRight.truncate j hjk = (inner.truncate j hjk).binaryRight
- inner.push.truncate j hjk = (inner.truncate (j + 1) ⋯).push
Instances For
Truncating a binary-free route to a shallower occurrence remains binary-free.
Truncation keeps an initial segment of the original route's barrier charges. In particular, it neither invents a binary barrier nor changes the owner assigned to a barrier it retains.
Consequently truncation cannot increase the number of maximal binary-free chunks.
If a structural truncation is unsafe for unary compression, the original route has at least one binary-barrier owner.
Equivalently, an unsafe truncation certifies that the original route needs at least two maximal binary-free chunks.
Stack depths at which a productive parse event can end a compressed unary block.
Terminal leaves and binary forks contribute the current depth. A pop shifts every deeper event one position away from the root, while a push removes the freshly pushed position.
Equations
- (IndexedGrammar.NFParse.binary hr hlhs hc hrhs left right).eventDepths = insert 0 (left.eventDepths ∪ right.eventDepths)
- (IndexedGrammar.NFParse.pop hr hlhs hc hrhs rest).eventDepths = Finset.image Nat.succ rest.eventDepths
- (IndexedGrammar.NFParse.push hr hlhs hc hrhs rest).eventDepths = Finset.image Nat.pred rest.eventDepths
- (IndexedGrammar.NFParse.terminal hr hlhs hc hrhs).eventDepths = {0}
Instances For
Embed a terminal position of a pending task's yield into the complete input word.
Instances For
The task's ordinary owner is the embedding of the first terminal in its yield.
Absolute input owners for all compressed blocks in the maximal binary-free decomposition of a chosen consumption route belonging to this task.
Equations
- task.routeBlockOwners route = List.map task.embedYieldOwner (route.followedOwner :: route.barrierOwners)
Instances For
Block owners belonging to one task are pairwise distinct.
A task's compressed blocks fit within its own yield interval.
In particular, the local block-owner count satisfies the global input-length budget used by
ScheduleInvariant.indexCount_le.
The yield interval of left lies completely before the yield interval of right.
Instances For
Owners embedded from disjointly ordered task intervals cannot coincide.
Compressed-block owner lists from disjoint pending-task intervals are disjoint.
Consequently concatenating the compressed blocks of two ordered task intervals preserves the global no-duplicate ownership invariant.
Persistent ownership of inherited block partitions #
A block list together with one pairwise-distinct owner in an ambient finite budget for each block. The carrier is independent of how a child refines its local event cuts, so ancestor owners can persist unchanged throughout the runner.
Instances For
Equations
Instances For
Add a fresh owner in front of an existing aligned block list.
Equations
Instances For
Retain ownership for the first n blocks.
Equations
Instances For
Retain ownership for the blocks after the first n.
Equations
Instances For
Ownership carriers are disjoint when their concrete owner lists are disjoint.
Instances For
Concatenate two aligned carriers whose owner sets are disjoint.
Equations
Instances For
The prefix and suffix inherited from one carrier have disjoint owner sets.
Distinct finite owners give the required ambient block-count bound.
Transient-index accounting #
Arithmetic form used by the transient compressed-token scheduler. Tasks still inject into
the n terminal positions. Persistent indices together with the one currently transient index
fit in two copies of those positions, and every open frame is charged to a persistent index.
Accounting carried by every compressed-runner edge #
Does a physical work symbol carry one pending-task or emitted-terminal payload?
Equations
Instances For
Does a physical work symbol close one currently open scheduler frame?
Instances For
Physical task/terminal payload count of one concrete configuration.
Equations
Instances For
Physical compressed-index count of one concrete configuration.
Equations
Instances For
Physical open-frame count, measured by closing delimiters.
Equations
Instances For
Exact count formulas for runner configurations #
Marking the rightmost index changes no count computed from a mark-insensitive predicate.
Returning a frame preserves task and index counts and removes exactly its closing marker.
Accounting for one concrete compressed-runner configuration. Every count is computed from
the physical word itself; event-depth invariants prove the count bounds, while shape_bound
records the delimiter layout.
Instances For
Package explicit bounds on the three physical count functions.
The accounting inequalities turn a local witness into the physical work-tape bound.
The initial work word has one task payload and no indices or frames.
The final work word has no task, index, or frame payload.
Composite reachability with an event-depth accounting witness on the initial configuration
and on both endpoints of every edge. This shape composes at exact Config endpoints and prevents
a runner proof from silently passing through an unbounded intermediate configuration.
Equations
- One or more equations did not get rendered due to their size.
Instances For
The last configuration of an accounted trace retains an accounting witness, including in the reflexive case.
Forget accounting annotations and retain ordinary composite reachability.
Every accounted compressed trace is a bounded composite trace at the desired linear bound.
Binary-free block continuations #
Strengthening of consumeRoute_popContinuation_noBinary: after the whole compressed block
through occurrence k is popped, consumption by the residual parse at position j is exactly
consumption by the original parse at position k + 1 + j. Thus an atomic multi-flag pop can
continue against lower compressed blocks without losing the live/plain boundary information.
Visible prefixes represented by compressed blocks #
A compressed visible-stack layout. flags is partitioned by the nonempty lists in
blocks; every block is represented by one relation token which denotes exactly that concrete
flag list. Gaps may contain ordinary control symbols (including close) but neither another
index nor $. The third and fourth word indices differ only by marking every selected token
used.
- nil {T : Type} {g : IndexedGrammar T} [Fintype g.nt] (tail : List (WorkSym g)) : BlockLayout g [] [] tail tail
- cons {T : Type} {g : IndexedGrammar T} [Fintype g.nt] {block flags : List g.flag} {blocks : List (List g.flag)} {beta tail tail' : List (WorkSym g)} {R : CFlag g} {d : IndexMark} (block_ne : block ≠ []) (denotes : CFlag.Denotes g block R) (indexFree : IndexFree beta) (dollarFree : DollarFree beta) (later : flags ≠ [] → d.later = true) (rest : BlockLayout g flags blocks tail tail') : BlockLayout g (block ++ flags) (block :: blocks) (beta ++ WorkSym.index R d :: tail) (beta ++ WorkSym.index R d.markUsed :: tail')
Instances For
The concrete visible prefix is exactly the flattening of its block partition.
Every member of the partition is a nonempty concrete flag block.
Every relation stored by the layout retains a concrete denotation witness.
Re-selecting an all-used block layout is physically idempotent.
Insert an ordinary control prefix into the gap before the first selected block.
A layout with no concrete flags has no blocks. The nonempty-block invariant is essential:
without it flatten blocks = [] would not force blocks = [].
Taking the concrete number of flags covered by the first n blocks ends exactly at their
physical block boundary.
Restrict a layout to its first n whole blocks. The remaining selected tokens become part
of the intermediate word. Unlike a flagwise split, this operation can never cut through the
concrete denotation of one compressed relation.
A concrete flag position is aligned to the compressed layout when it is the total length of some whole-block prefix. The explicit block count is the physical index-token budget at that boundary.
- blockCount : ℕ
Instances For
Every prefix measured in whole blocks determines an aligned concrete boundary.
Equations
- IndexedGrammar.Aho.BlockLayout.Boundary.ofBlockCount blocks blockCount h = { blockCount := blockCount, blockCount_le := h, flagCount_eq := ⋯ }
Instances For
The initial concrete position is always a block boundary.
Equations
- IndexedGrammar.Aho.BlockLayout.Boundary.start blocks = { blockCount := 0, blockCount_le := ⋯, flagCount_eq := ⋯ }
Instances For
The end of the concrete visible prefix is a block boundary.
Equations
- IndexedGrammar.Aho.BlockLayout.Boundary.finish blocks = { blockCount := blocks.length, blockCount_le := ⋯, flagCount_eq := ⋯ }
Instances For
Prefixing one concrete block shifts every old boundary by that block's length.
Equations
- IndexedGrammar.Aho.BlockLayout.Boundary.cons block boundary = { blockCount := boundary.blockCount + 1, blockCount_le := ⋯, flagCount_eq := ⋯ }
Instances For
Removing a nonempty first block transports a shifted boundary to the tail partition.
Equations
- One or more equations did not get rendered due to their size.
Instances For
Every positive boundary of a partition beginning with a nonempty block lies at or below the end of that first block. This is the arithmetic fact used to show that a first block is event-free once depth zero is not productive.
A fresh singleton top block shifts every old boundary by exactly one flag.
Equations
- IndexedGrammar.Aho.BlockLayout.Boundary.singletonCons f boundary = ⋯.mp (IndexedGrammar.Aho.BlockLayout.Boundary.cons [f] boundary)
Instances For
Extending the first block by one flag shifts every positive boundary by one while keeping the same physical block count.
Equations
- One or more equations did not get rendered due to their size.
Instances For
Split at an explicitly aligned concrete flag position. The boundary witness makes it impossible for callers to request a split inside the denotation of a compressed block.
The selected physical part of a block layout consists of parallel prefixes followed by one common unselected tail.
Consequently the physical selected-index count is exactly the number of concrete blocks.
Canonical stack-depth event cuts #
Every parse has at least the cut contributed by one terminal leaf.
Root-stack position k is consumed exactly when some canonical event cut lies strictly
below it. Hence eventDepths is a finite cut profile for every consumption decision made by
the bounded scheduler.
Every canonical event depth denotes an actual cut of the current root stack.
The finite cut profile uses no more entries than all productive parse events.
There are at most 2|w|-1 distinct event cuts. This is the global bound needed when the
scheduler allocates at most one compressed index token per canonical cut.
Productive nodes are exactly the binary nodes plus terminal leaves, hence 2|w|-1.
Coherent productive-event owners #
Canonical inverse used when a push maps event depths through Nat.pred. At depth zero we
prefer the old zero event when it exists; otherwise the unique relevant preimage is one.
Equations
Instances For
The canonical push inverse is injective on actual image depths.
The natural-number code underlying a coherent productive-node ID. Binary roots own zero; left and right child codes occupy disjoint successive ranges. Unary nodes transport codes.
Equations
- One or more equations did not get rendered due to their size.
- (IndexedGrammar.NFParse.terminal hr hlhs hc hrhs).eventOwnerNat d = 0
- (IndexedGrammar.NFParse.pop hr hlhs hc hrhs rest).eventOwnerNat d = rest.eventOwnerNat (d - 1)
- (IndexedGrammar.NFParse.push hr hlhs hc hrhs rest).eventOwnerNat d = rest.eventOwnerNat (IndexedGrammar.NFParse.pushEventPreimage rest.eventDepths d)
Instances For
Every actual event code fits inside the productive-node count.
A coherent productive-node ID for a canonical event depth.
Equations
- p.eventOwner d hd = ⟨p.eventOwnerNat d, ⋯⟩
Instances For
The natural-number event codes are injective on actual event depths.
Coherent finite event IDs are injective in the represented stack depth.
Canonical physical blocks at productive-event cuts #
Successive widths represented by an increasing list of absolute cut positions.
Equations
- IndexedGrammar.NFParse.successiveWidths previous [] = []
- IndexedGrammar.NFParse.successiveWidths previous (d :: ds) = (d - previous) :: IndexedGrammar.NFParse.successiveWidths d ds
Instances For
Taking the first n widths is the same as first taking the corresponding cuts.
Every width between consecutive strictly increasing cuts is positive.
Telescoping widths stay inside any common upper bound for the absolute cuts.
Positive productive-event depths, in their unique increasing order.
Instances For
Canonical cuts are strictly increasing.
Adding the implicit initial boundary preserves strict increase.
Concrete lengths of the successive canonical event blocks.
Equations
Instances For
The total visible prefix selected by all event cuts fits in the root stack.
Canonical nonempty concrete flag blocks cut from the consumed root-stack prefix.
Equations
- p.eventBlocks = p.eventWidths.splitLengths stack
Instances For
Each physical block has exactly its positive successive width.
The generated blocks flatten to the concrete stack prefix ending at the final event cut.
Numerically, the prefix endpoints of eventBlocks are exactly eventCuts.
Assign a physical block its productive-event-depth owner: the endpoint of that block.
Equations
- p.eventBlockOwner i = (List.take (↑i + 1) p.eventBlocks).flatten.length
Instances For
Every physical block owner is an actual productive-event depth.
Different physical blocks receive different productive-event-depth owners. This is the global injection needed for the token budget; unlike one-way boundary compatibility it rules out arbitrary extra protected-child blocks.
Root-capacity owner of a canonical physical block. Unlike its raw depth endpoint, this ID
is stable under the unary transports and binary embeddings encoded by eventOwnerNat.
Equations
- p.eventBlockGlobalOwner i = Fin.cast ⋯ (p.eventOwner (p.eventBlockOwner i) ⋯)
Instances For
Canonical block owners are globally collision-free in the exact 2|w|-1 carrier.
Every productive-event depth is a whole-block prefix boundary (with depth zero represented by the empty block prefix).
The number of canonical physical blocks obeys the same 2|w|-1 bound as event cuts.
Canonical blocks come with a persistent finite ownership carrier of the exact global
2|w|-1 capacity. Descendants can retain these owners through take/drop, so protected
boundaries remain charged even when they are extra relative to the child's local event cuts.
Equations
- p.eventBlocksOwnership = { owners := List.ofFn p.eventBlockGlobalOwner, owners_length := ⋯, owners_nodup := ⋯ }