Fixed-width bit layouts #
⚠️ Unreviewed by Bolton
A machine that searches the configuration space of another machine has to hold configurations in registers and step a counter through all of them. Both want the same thing: a fixed-width bit layout, so that a register is a fixed number of cells and the enumeration is one binary counter.
Complexity.BitCodec is that layout, packaged so it can be built up field by field. Each codec
carries its width, an encoder, a decoder that is total on every bitstring, and the two facts a
caller needs: the encoding has the declared width, and decoding inverts it. The combinators —
Complexity.BitCodec.prod, Complexity.BitCodec.fn, Complexity.BitCodec.equiv — discharge
those obligations once, so a record layout is assembled rather than proved.
The decoder being total matters. The machine enumerates all bitstrings of the layout's width, not just the ones in the image, so every register value must denote something; the ones outside the image simply denote a configuration that no walk ever reaches.
So does where the head positions go. A machine reads a register by scanning it, so a head stored
as a number in its own field would be useless — to check the cell it points at, the scan would
have to turn around. Complexity.tapeCodec therefore stores the head as a marker beside each
cell: the scan learns at every cell whether the head is there, which is what makes a
Complexity.Scanner able to check a transition of the simulated machine without ever counting.
Main definitions #
Complexity.BitCodec— a fixed-width bit layoutComplexity.BitCodec.fin,.gamma,.bool,.prod,.fn,.equiv— the combinatorsComplexity.tapeCodec— a tape window, with the head marked beside the cell it is onComplexity.codeCodec— the layout of a configuration code
Main results #
Complexity.BitCodec.enc_injective— a layout distinguishes what it encodesComplexity.codeCodec_width— the width of a configuration code
A fixed-width bit layout for α: an encoder of constant width, and a decoder that is total
on every bitstring and inverts it.
- width : ℕ
The number of bits an encoded value occupies.
The encoder.
The decoder, total on every bitstring.
Encodings have the declared width.
Decoding inverts encoding.
Instances For
Leaves #
A tape symbol, in two bits.
Equations
- One or more equations did not get rendered due to their size.
Instances For
A single bit.
Equations
- One or more equations did not get rendered due to their size.
Instances For
Reading a value out of a scan #
A scan puts a register's leading bits into a table (Complexity.Scanner.bitsStep). This reads the
value they encode back out, which is how a check recovers, say, the simulated machine's state from
the parameters it was handed.
Combinators #
Transport a layout along an equivalence.
Equations
Instances For
The layout of a configuration code #
The layout of a bounded index.
Equations
Instances For
The layout of a machine state.
Equations
Instances For
Marking a head position where the scan will meet it #
A machine reads a register by scanning it, so a head position stored as a number in its own field is useless: to check the cell it points at, the scan would have to come back. Storing it as a marker beside each cell makes the head local — the scan learns, at each cell, whether the head is there.
Read the head position back off the markers. Total: with no marker, or several, it reads the head as sitting at the first cell.
Equations
Instances For
The two bits a symbol occupies.
Equations
Instances For
The width of a configuration code: a constant for the state, a pointer into the input, and the window itself.
The layout is logarithmically wide #
A configuration code is logarithmically wide. Every field is either a constant, a pointer into the input, or a piece of the window, so the whole layout fits in a logarithmic window of its own — which is what lets a machine hold two of them at once and still be a log-space machine.
Combining logarithmic bounds #
The machine's space is the largest of its registers, and each register has its own logarithmic bound; these say the family is closed under the operations the accounting needs.
A polynomial counter is logarithmically wide. The search counts rounds and codes up to
A * (n + 1) ^ B, so its counters fit in a logarithmic number of cells — which is what keeps the
whole machine inside a logarithmic window.