The background: the machine's mutable state, presented as a tape #
Every kit discharge takes a family of slot equations – the register mark
is set exactly at the register cells, the marker at one working-area
address, and so on. They are all facts about one object: the machine's
mutable state – its registers, its stage tracks, its markers – laid over the
permanent marks of DescriptiveComplexity.Draw.slotMark. This file is that
object, DescriptiveComplexity.Draw.TapeSt, its presentation
DescriptiveComplexity.Draw.Data.back as the rest family the pass layer
walks, and the slot equations, proved once: the discharges of
DrawRun will cite them instead of re-deriving per call site.
The split of a track's home: the four machine registers (mir, tgt,
sav, val) hold bits per element – their digit at a cell is
DescriptiveComplexity.regBit, set only at register cells – while the stage
tracks (old i, new i) and the working-area markers (wk, bot, ltp)
hold bits per cell, anywhere on the tape. The permanent mark slots
(reg, the ends, blk, name, pdd) read
DescriptiveComplexity.Draw.slotMark at register cells and are clear
elsewhere, which is what their read-back equations say.
What indexes the file is a parameter.
DescriptiveComplexity.Draw.Data.ixBack reads a background at an arbitrary
index, because a program on a clock cannot give every element of the universe a
register and nothing here needs it to: a slot depends on the register's block,
on the tuple it names, on where it sits in the layout order, and on nothing else
about the index. The state carries the index with it – the four machine
registers hold a bit per register and the stage tracks and markers a bit per
cell, so DescriptiveComplexity.Draw.TapeSt takes the index and
DescriptiveComplexity.Draw.TapeStD is the elementwise case.
DescriptiveComplexity.Draw.Data.back is that at the
diagonal – the index the universe itself, the order its own – which is what a
space-bounded program uses, and every slot equation below is stated there. The
two ends are already general
(DescriptiveComplexity.Draw.Data.ixBack_regFirst,
DescriptiveComplexity.Draw.Data.ixBack_regLast): which cell carries them is
a fact about the layout order and about nothing else.
The machine's mutable state: the four registers (bits per element), the stage tracks and markers (bits per cell). The permanent marks are not here – they never change.
- mir : I → Prop
The MIRROR register.
- tgt : I → Prop
The TARGET register.
- sav : I → Prop
The SAV register.
- val : I → Prop
The VAL register.
The current stage of each variable, a bit per cell.
The next stage of each variable, a bit per cell.
The working-cell marker, a bit per cell.
The bottom marker, a bit per cell.
The end marker of the logical interval, a bit per cell.
Instances For
Dependency graph
The machine's state at the elementwise file: one register per element of the universe, which is what a space-bounded program has.
Equations
- DescriptiveComplexity.Draw.TapeStD dt A R' P' = DescriptiveComplexity.Draw.TapeSt dt A R' P' (DescriptiveComplexity.Draw.Univ A R' P' dt.KIx dt.dd)
Instances For
Dependency graph
The tuple a control names: the coordinates it computes below dd₀, the
designated zero above – the canonical padding of every register a scan by name
stops at.
Instances For
Dependency graph
What a register file is, as the background reads it: the cells, the order they are laid out in, the block each register belongs to and the tuple it names. Those four are everything a slot depends on, and none of them asks the index to be the universe.
Bundled rather than passed one at a time because the whole evaluation layer carries it, and because a bare family of cells is what a definition can take: a register file carries proofs as well, and only the statements need those.
The address of the register an index names.
- le : I → I → Prop
The order the registers are laid out in.
The block a register belongs to.
The tuple a register names.
Instances For
Dependency graph
A layout whose registers are told apart by their marks: two registers of one and the same block, both canonically padded, whose named coordinates agree, are the same register.
This is what a navigation-by-name scan asks of its stopping condition, and it is where a layout does real work: the elementwise one has it because a register is its tag and its tuple, and a clocked program's file has it because its index carries the block and the tuple and nothing else.
Equations
- One or more equations did not get rendered due to their size.
Instances For
Dependency graph
A layout with a register for every named tuple: whatever block and whatever tuple the control names, some register carries them.
This is the second half of what a navigation-by-name scan needs – NameSep
says the name identifies at most one register, this says it identifies at
least one – and it is what a clocked program's file is built to have: its index
is the pair of a block and a tuple.
The tuples asked for are the named ones, DescriptiveComplexity.Draw.padTup
of what a control holds: a mark carries dd₀ coordinates and nothing reads a
register's tuple above them, so a file that has one register per named tuple has
every register the machine can navigate to, and is smaller than one per tuple by
the factor the padding accounts for.
Equations
Instances For
Dependency graph
The register a name picks out: the one HasName provides, chosen. A
layout that also has NameSep has only one, so this is the register of the
block and the tuple, and everything the evaluation layer reads at «the cell of
this tuple» is read here.
Chosen rather than a field, because the two properties are what a file has to prove and this adds nothing to them.
Instances For
Dependency graph
The named register is in the named block.
Dependency graph
The named register carries the named tuple, canonically padded.
Dependency graph
A register file together with its layout: the cells, the order they are laid out in, the block each register belongs to and the tuple it names, plus the two conditions that make a family of addresses a file – the cells grow with the index, and none of them is empty.
This is what the evaluation layer carries. The kits ask for the file alone
(DescriptiveComplexity.Draw.LaidFile.toIxFile) and the background for the
layout alone (DescriptiveComplexity.Draw.LaidFile.toLayout); carrying the two
together is what lets one parameter stand where
DescriptiveComplexity.RegFile stood.
The address of the register an index names.
- le : I → I → Prop
The order the registers are laid out in.
The block a register belongs to.
The tuple a register names.
Registers laid out later have strictly greater addresses.
No register's address is empty.
Instances For
Dependency graph
The layout of a laid file: what the background reads.
Instances For
Dependency graph
The file of a laid file: what the kits walk.
Instances For
Dependency graph
The laid file a space-bounded program uses: one register per element of the universe, in the universe's own order, each naming its own tag's block and its own tuple.
Equations
- One or more equations did not get rendered due to their size.
Instances For
Dependency graph
The elementwise file's layout order is linear, given that the universe's
is and that the two agree – which is the hord every diagonal statement of the
layer already carries.
Dependency graph
The state, presented as a background, at an arbitrary index for the
file: the value of each slot at each cell. The walked track of a pass is
carved out of this by DescriptiveComplexity.Draw.Prog.trackTapeAt; everything
else rides along.
What the file is indexed by is a parameter, because a clocked program cannot
give every element of the universe a register and
nothing here needs it to: a register's contents depend on its block, on the
tuple it names, and on where it sits in the layout order, and on nothing
else about the index. DescriptiveComplexity.Draw.Data.back is this at the
diagonal, which is what a space-bounded program uses.
Equations
- One or more equations did not get rendered due to their size.
- dt.ixBack lay zero one hdd st r DescriptiveComplexity.Draw.Slot.reg = DescriptiveComplexity.Draw.bitVal zero one (∃ (u : I), r = lay.cell u)
- dt.ixBack lay zero one hdd st r DescriptiveComplexity.Draw.Slot.regFirst = DescriptiveComplexity.Draw.bitVal zero one (∃ (u : I), r = lay.cell u ∧ ∀ (y : I), lay.le u y)
- dt.ixBack lay zero one hdd st r DescriptiveComplexity.Draw.Slot.regLast = DescriptiveComplexity.Draw.bitVal zero one (∃ (u : I), r = lay.cell u ∧ ∀ (y : I), lay.le y u)
- dt.ixBack lay zero one hdd st r (DescriptiveComplexity.Draw.Slot.blk b) = DescriptiveComplexity.Draw.bitVal zero one (∃ (u : I), r = lay.cell u ∧ lay.blk u = b)
- dt.ixBack lay zero one hdd st r (DescriptiveComplexity.Draw.Slot.name j) = if h : ∃ (u : I), r = lay.cell u then lay.arg h.choose (Fin.castLE hdd j) else zero
- dt.ixBack lay zero one hdd st r DescriptiveComplexity.Draw.Slot.mir = DescriptiveComplexity.Draw.bitVal zero one (DescriptiveComplexity.bitAtOf lay.cell st.mir r)
- dt.ixBack lay zero one hdd st r DescriptiveComplexity.Draw.Slot.tgt = DescriptiveComplexity.Draw.bitVal zero one (DescriptiveComplexity.bitAtOf lay.cell st.tgt r)
- dt.ixBack lay zero one hdd st r DescriptiveComplexity.Draw.Slot.sav = DescriptiveComplexity.Draw.bitVal zero one (DescriptiveComplexity.bitAtOf lay.cell st.sav r)
- dt.ixBack lay zero one hdd st r DescriptiveComplexity.Draw.Slot.val = DescriptiveComplexity.Draw.bitVal zero one (DescriptiveComplexity.bitAtOf lay.cell st.val r)
- dt.ixBack lay zero one hdd st r DescriptiveComplexity.Draw.Slot.wk = DescriptiveComplexity.Draw.bitVal zero one (st.wk r)
- dt.ixBack lay zero one hdd st r DescriptiveComplexity.Draw.Slot.bot = DescriptiveComplexity.Draw.bitVal zero one (st.bot r)
- dt.ixBack lay zero one hdd st r DescriptiveComplexity.Draw.Slot.ltp = DescriptiveComplexity.Draw.bitVal zero one (st.ltp r)
- dt.ixBack lay zero one hdd st r (DescriptiveComplexity.Draw.Slot.old i) = DescriptiveComplexity.Draw.bitVal zero one (st.old i r)
- dt.ixBack lay zero one hdd st r (DescriptiveComplexity.Draw.Slot.new i) = DescriptiveComplexity.Draw.bitVal zero one (st.new i r)
Instances For
Dependency graph
The layout a space-bounded program's file has: one register per element of the universe, in the universe's own order, each naming its own tag's block and its own tuple.
Equations
- One or more equations did not get rendered due to their size.
Instances For
Dependency graph
The elementwise file, laid out: one register per element of the
universe, in the universe's own order, each naming its own tag's block and its
own tuple. This is what a space-bounded program's register file is, read as a
DescriptiveComplexity.Draw.LaidFile, so that the runs stated at an arbitrary
file apply to it – its layout is DescriptiveComplexity.Draw.Data.diagLayout
exactly, so its background is DescriptiveComplexity.Draw.Data.back.
Equations
- One or more equations did not get rendered due to their size.
Instances For
Dependency graph
The elementwise layout order is linear, being the address order.
Dependency graph
The elementwise file names each element by itself, which is the identity
embedding of DescriptiveComplexity.ixAddr.
Dependency graph
The state, presented as a background: DescriptiveComplexity.Draw.Data.ixBack
at the layout a space-bounded program's file has.
Equations
- dt.back cell zero one hdd st r = dt.ixBack (dt.diagLayout cell) zero one hdd st r
Instances For
Dependency graph
The slot equations, at an arbitrary layout #
Everything a slot of the background is depends on the layout and nothing else,
so the equations that read one back are stated there once. The diagonal forms
below are their instances at DescriptiveComplexity.Draw.Data.diagLayout,
kept under their own names because that is what the whole evaluation layer
rewrites with.
The marker slot, at an arbitrary layout.
Dependency graph
Off the file, a state with no track set presents the blank, at an arbitrary layout.
Dependency graph
The background reads the stage tracks at one cell, at an arbitrary layout.
Dependency graph
Off the file the background is blind to every register, at an arbitrary layout.
Dependency graph
The block one-hot, at a register cell of an arbitrary layout.
Dependency graph
The padding mark, at a register cell of an arbitrary layout.
Dependency graph
A name slot, at a register cell of an arbitrary layout.
Dependency graph
The slot equations, once #
The register mark: set exactly at the register cells – the equation
every discharge's hrg is.
Dependency graph
The marker slot, read back.
Dependency graph
The bottom mark, read back.
Dependency graph
The end mark, read back.
Dependency graph
A name slot, read back: the coordinate the register's own index carries,
and the designated zero where there is no register. Stated because the
definition matches on the slot, so rw cannot reach the branch on its own.
Dependency graph
A stage track, read back.
Dependency graph
The next-stage track, read back.
Dependency graph
Off the file, a state with no track set presents the blank. Every slot of the background at a cell that is nobody's register is either a permanent mark – existentially quantified over the registers, hence false there – or a register digit, false for the same reason, or one of the five per-cell tracks, which the hypotheses ask to be clear.
This is what makes the phase that builds a file a sweep of the file's stretch and nothing more: below the stretch and above it the background the phase has to produce is already the blank the machine started from, so the two ends of the sweep are the two ends of the file.
Dependency graph
The background reads the stage tracks at one cell. Two states differing
in the old tracks alone present the same background at every cell where those
tracks agree – the other slots being marks, register digits, or per-cell tracks
the update leaves alone.
This is what a guessing phase needs: it rewrites the old tracks cell by cell,
and the congruence is what says the cells it has not reached yet still read what
they did.
Dependency graph
What a state's scratch registers do not decide #
The VAL loop threads SAV and TARGET and nothing else
(DescriptiveComplexity.Draw.Data.roundEndSt_eq), so its rounds run at
states that differ from the machinery's entry state in those two registers
alone. ScratchEq names that relation, and the lemmas below say what it
buys: every per-cell mark and track is shared, hence so is the background
at every cell of the working area – the four register slots being
DescriptiveComplexity.regBits, set at a register cell only.
Two states differing in the two scratch registers alone: every mark and every track is shared, the saved mirror and the target need not be.
Equations
Instances For
Dependency graph
Rewriting the two scratch registers is a ScratchEq.
Dependency graph
ScratchEq is symmetric.
Dependency graph
ScratchEq is transitive.
Dependency graph
ScratchEq survives writing the same scratch registers on both
sides.
Dependency graph
ScratchEq survives writing the same target on both sides.
Dependency graph
ScratchEq survives writing the same VAL register on both sides.
Dependency graph
Off the register file the background is blind to every register: the
four register slots read DescriptiveComplexity.bitAtOf, which is set at a
register cell only, so at a cell of the working area two states agree as
soon as their per-cell marks and tracks do – whatever their mirror, their
target, their saved mirror or their VAL content is. This is what lets the
control of the VAL loop's threaded states be the control of the
unthreaded ones: threading rewrites the two scratch registers, and the
rounds read their background at the working cell.
Dependency graph
ScratchEq survives writing the same save and target on both sides, at an
arbitrary file.
Dependency graph
The background at a working cell, off a ScratchEq, at an arbitrary
layout: two states differing in the two scratch registers alone present the
same background wherever no register is.
Dependency graph
The background at a working cell, off a ScratchEq.
Dependency graph
The navigation by name, at an arbitrary layout #
The three equations above are all a name scan reads, so the guard's reading is
stated at the layout too. Only the uniqueness asks anything of the layout –
DescriptiveComplexity.Draw.Layout.NameSep, that the marks tell the registers
apart – and the elementwise layout has it because a register is its tag and its
tuple.
The name guard, at a register cell of an arbitrary layout: the register is in the named block, canonically padded, and carries the coordinates the control computes.
Dependency graph
The name guard identifies one register, at a layout whose marks tell them apart.
Dependency graph
Off the file the name guard fails, at an arbitrary layout: the block one-hot is clear there, so no scan stops in the working area.
Dependency graph
A named tuple is canonically padded.
Dependency graph
A named tuple carries the control's coordinates.
Dependency graph
The register a name identifies #
Put the two halves together: on a layout whose marks tell its registers apart
(DescriptiveComplexity.Draw.Layout.NameSep) and which has a register for every
name (DescriptiveComplexity.Draw.Layout.HasName), the guard of a scan by name
holds at one register of the file and nowhere else on it. That is exactly
the pair of hypotheses DescriptiveComplexity.Draw.Prog.reaches_toCell asks
for, so a caller's scan arrives at a register it can name.
This is what replaces the address-carrying random access at a clocked program's
file: DescriptiveComplexity.Draw.SeekKit steps a marker until the walked
mirror equals a target written across the file, which needs one register per
address; a scan by name needs only the dd₀ coordinates the control already
holds.
The name guard holds at the named register.
Dependency graph
The name guard holds at exactly one address of the file: at the named register, and at no other register nor anywhere off the file. The stopping condition of a scan by name, in the shape a scan asks for.
Dependency graph
A computed name at a register says which register it is: on a layout that has a register for every name and tells them apart, the guard holds at exactly the register whose coordinates the control computes. The trips of the evaluation layer ask which cell they stopped at, and this is the answer, whatever function of the control the coordinates are.
Dependency graph
The name guard at a register says which register it is, the coordinates
read straight off the control: DescriptiveComplexity.Draw.Data.ixNameGF_iff
at the coordinate slots the copy loops use.
Dependency graph
Off the file the coordinate-loop trips' guard fails, at an arbitrary layout: the shape the evaluation layer's «the scan stopped nowhere else» arguments are written against.
Dependency graph
The permanent marks at a register cell, and the navigation by name #
The mark slots are stated existentially – “some element's cell, whose tag's
block is b” – because the background is a function of the address. At a
register cell the existential collapses, by injectivity of the
cell family, and what is left is the mark of the element
itself. Those three equations are what the navigation-by-name scans read:
DescriptiveComplexity.Draw.Data.nameG holds at exactly one cell, the
canonically padded cell of the element whose coordinates the control holds
(DescriptiveComplexity.Draw.Data.nameG_unique), and nowhere off the
register file.
The block one-hot, at a register cell.
Dependency graph
The padding mark, at a register cell.
Dependency graph
A name slot, at a register cell: the element's own coordinate.
Dependency graph
The name guard, at a register cell: the cell's element is in the named block, canonically padded, and carries the coordinates the control computes.
Dependency graph
The elementwise layout's marks tell its registers apart: a register is its tag and its tuple, so the block and the named coordinates spell it.
Dependency graph
A named tuple is the padded one: DescriptiveComplexity.Draw.padTup and
DescriptiveComplexity.Draw.pad are the same function, written once for the name
a control holds and once for the geometry.
Dependency graph
The elementwise layout has a register for every name: a register is an element, and every block and tuple names one.
Dependency graph
At the elementwise layout the named register is the obvious one: the
element whose tag is the block and whose tuple is the padded name. Chosen by
DescriptiveComplexity.Draw.Layout.reg, pinned by NameSep.
Dependency graph
The name guard identifies one cell: two register cells it holds at
are the same. This is what a navigation-by-name scan needs of its stopping
condition (DescriptiveComplexity.Draw.Prog.reaches_toCell).
Dependency graph
Off the register file the name guard fails: the block one-hot is clear there, so no scan stops in the working area.
Dependency graph
The coordinate-loop trips' guard, at a register cell.
Dependency graph
The coordinate-loop trips' guard identifies one cell.
Dependency graph
Off the register file the coordinate-loop trips' guard fails.
Dependency graph
The two ends of the file, at an arbitrary index #
What a discharge asks of the regFirst and regLast slots is that they be set
at one named cell and nowhere else, and that is a fact about the layout order
alone: antisymmetry says the extreme index is unique, and the file is injective
in nothing – the slot is read off the index, not off the address. So both are
stated at the general index, and the elementwise forms are their diagonal.
The file-top mark is the greatest index's cell.
Dependency graph
The file-bottom mark is the least index's cell.
Dependency graph
The file-top mark is the greatest element's cell: given that the
universe order is linear, the regLast slot is set exactly at the cell of
the top element – the equation every discharge's hrl is.