Documentation

Complexitylib.Classes.P.Cobham.Internal.Extract

Reading a string out of an encoded tape — proof internals #

The completeness direction ends by reading the simulated machine's output off its encoded output tape. Once the output head has been driven back to cell 0 (see Complexitylib.Classes.P.Cobham.Internal.StepAlgebra), that tape's right half-block is the whole tape in order, two bits per cell: the first bit of a cell says whether it holds data, the second is the data bit.

So the output is recovered by two short recursions on notation, both collected here:

Main results #

Reading a single bit #

def Complexity.bitOf (z : List Bool) (p : ) :

The bit of z at position p, false past the end.

Equations
Instances For
    theorem Complexity.bitOf_eq_getElem {z : List Bool} {p : } (h : p < z.length) :
    bitOf z p = z[p]

    Within range, bitOf is the indexed bit.

    theorem Complexity.bitOf_of_le {z : List Bool} {p : } (h : z.length p) :

    Past the end there is no bit.

    theorem Complexity.bitOf_append_left {a : List Bool} {p : } (h : p < a.length) (b : List Bool) :
    bitOf (a ++ b) p = bitOf a p

    Reading inside the first part of a concatenation.

    theorem Complexity.bitOf_append_right {a : List Bool} {p : } (h : a.length p) (b : List Bool) :
    bitOf (a ++ b) p = bitOf b (p - a.length)

    Reading past the first part of a concatenation.

    theorem Complexity.bitAt_eq (r z : List Bool) :

    Cobham.bitAt reads exactly one bit, and it is bitOf.

    Every second bit #

    cellBits o z m lists the bits of z at positions o, o + 2, …, o + 2(m-1). With z a run of two-bit symbol codes, offset o picks out one bit of each symbol — which is how both halves of a coded cell are read.

    The bits of z at positions 2i + o for i < m.

    Equations
    Instances For
      @[simp]
      theorem Complexity.cellBits_length (o : ) (z : List Bool) (m : ) :
      (cellBits o z m).length = m
      theorem Complexity.cellBits_getElem? (o : ) (z : List Bool) (m i : ) :
      i < m(cellBits o z m)[i]? = some (bitOf z (2 * i + o))

      The leading run of trues #

      The output tape's "is data" bits are true on the output and false at the first blank past it, so the output's length is the length of the leading run of trues. The recursion below computes it as a ruler, clamped at the width it is run to: the guard m ≤ |previous| is what stops the run at the first false rather than restarting after it.

      The leading run of trues of z, clamped to m bits, as a ruler.

      Equations
      Instances For
        theorem Complexity.runTrue_length {z : List Bool} {n : } (htrue : i < n, bitOf z i = true) (hfalse : bitOf z n = false) (m : ) :
        (runTrue z m).length = min m n

        The run's length is where the first false is. The guard in runTrue stops the run at the first false rather than restarting after it, so the run's length is the position of the first false, clamped by the width.

        Both recursions are in the algebra #

        theorem Complexity.Cobham.cellBitsFn {n : } (o : ) {gr gz : (Fin nList Bool)List Bool} (hr : Cobham gr) (hz : Cobham gz) :
        Cobham fun (v : Fin nList Bool) => cellBits o (gz v) (gr v).length

        Every second bit is in the algebra. One limited recursion on notation: each peeled bit of the ruler appends one more bit of z, read at twice the remaining ruler's length plus the offset.

        theorem Complexity.Cobham.runTrueFn {n : } {gr gz : (Fin nList Bool)List Bool} (hr : Cobham gr) (hz : Cobham gz) :
        Cobham fun (v : Fin nList Bool) => runTrue (gz v) (gr v).length

        The leading run of trues is in the algebra. One limited recursion on notation: the run grows by one only while it has kept pace with the ruler, which is the length comparison nonemptyFn/notFn performs.