Documentation

Complexitylib.Models.TuringMachine.Subroutines.Counter

Counter-building TM subroutines #

Deterministic helper machines for materializing unary counters on work tapes.

The SAT-specific NP construction only needs a linear witness bound: assignment.length ≤ input.length + 1. This file defines a small machine that writes exactly |input| + 1 unary marks to a designated counter tape.

A counter tape while it is being built: cells 1..used contain unary marks, the head is at cell used + 1, and the tail from that cell onward is blank.

Equations
Instances For

    An empty tape moved one cell right has the empty unary prefix: the head is at cell 1 and every cell after is blank.

    Writing one mark at the current head and moving right extends a unary prefix by one cell.

    Writing the next unary mark preserves the left-end marker cell.

    theorem Complexity.Tape.hasUnaryPrefix_cells_ne_start {t : Tape} {used : } (h : t.HasUnaryPrefix used) (j : ) :
    j 1t.cells j Γ.start

    A unary prefix never contains after the left-end marker.

    A unary counter tape positioned at its first data cell.

    HasUnaryCounter t B means cells 1..B contain 1, cell B+1 is blank, and the head is at cell 1.

    Equations
    Instances For
      theorem Complexity.Tape.hasUnaryCounter_of_hasUnaryPrefix {t t' : Tape} {B : } (hprefix : t.HasUnaryPrefix B) (hhead : t'.head = 1) (hcells : t'.cells = t.cells) :

      Rewinding a built unary prefix to cell 1 yields the public counter shape.

      A tape holding a zero-length unary counter reads blank at its head.

      theorem Complexity.Tape.hasUnaryCounter_read_pos {t : Tape} {B : } (h : t.HasUnaryCounter B) (hB : 0 < B) :

      A tape holding a positive-length unary counter reads 1 at its head.

      Counter shape after used marks have already been consumed. The head is at the next unconsumed counter cell, previous cells are blanked, remaining marks are 1, and the first cell after the total bound is blank.

      Equations
      • One or more equations did not get rendered due to their size.
      Instances For

        A fresh unary counter is exactly a counter remainder with zero marks consumed.

        Once all counter marks are consumed, the head reads blank.

        theorem Complexity.Tape.hasCounterRemainder_read_one_of_remaining {t : Tape} {used total : } (h : t.HasCounterRemainder used total) (hlt : used < total) :

        While counter marks remain unconsumed, the head reads 1.

        A well-shaped counter remainder never reads the left-end marker.

        theorem Complexity.Tape.hasCounterRemainder_consume {t : Tape} {used total : } (h : t.HasCounterRemainder used total) (hlt : used < total) :

        Blanking the current counter mark and moving right advances the unary counter remainder by one.

        Writing back the currently read non-start symbol and idling preserves a tape. This is the basic preservation fact for non-active tapes in the counter and guessing machines.

        @[implicit_reducible]

        LinearCounterPhase has exactly the three states scan, rewind, done.

        Equations
        • One or more equations did not get rendered due to their size.
        def Complexity.TM.counterPreserveWork {n : } (wHeads : Fin nΓ) :
        Fin nΓw

        Preserve every writable work-tape symbol.

        Equations
        Instances For
          def Complexity.TM.counterIdleDirs {n : } (wHeads : Fin nΓ) :
          Fin nDir3

          Keep every work head stationary, except when bouncing off the start marker.

          Equations
          Instances For
            def Complexity.TM.counterWriteOneWork {n : } (counterIdx : Fin n) (wHeads : Fin nΓ) :
            Fin nΓw

            Write one unary mark on the counter tape and preserve every other tape.

            Equations
            Instances For
              def Complexity.TM.counterAdvanceDirs {n : } (counterIdx : Fin n) (wHeads : Fin nΓ) :
              Fin nDir3

              Advance the counter head and idle every other work head.

              Equations
              Instances For
                def Complexity.TM.counterRewindDirs {n : } (counterIdx : Fin n) (wHeads : Fin nΓ) :
                Fin nDir3

                Rewind the counter head and idle every other work head.

                Equations
                Instances For
                  def Complexity.TM.inputLengthPlusOneCounterTM {n : } (counterIdx : Fin n) :
                  TM n

                  Write a unary counter of length |input| + 1 to counterIdx.

                  Starting with the input head on and an empty counter tape, the scan phase skips the input start cell, writes one counter mark per input bit, then writes one extra mark when the input head reaches blank. The rewind phase rewinds the counter tape to cell 1 and halts.

                  The machine does not try to restore the input head; later composition layers can rewind or retarget input as needed.

                  Equations
                  • One or more equations did not get rendered due to their size.
                  Instances For
                    theorem Complexity.TM.inputLengthPlusOneCounterTM_scan_start_state {n : } (counterIdx : Fin n) (inp : Tape) (work : Fin nTape) (out : Tape) (hinp : inp.read = Γ.start) :
                    (((inputLengthPlusOneCounterTM counterIdx).step { state := LinearCounterPhase.scan, input := inp, work := work, output := out }).get ).state = LinearCounterPhase.scan

                    In the scan phase, reading on the input keeps the machine in scan.

                    theorem Complexity.TM.inputLengthPlusOneCounterTM_scan_start_initializes_counter {n : } (counterIdx : Fin n) (inp : Tape) (work : Fin nTape) (out : Tape) (hinp : inp.read = Γ.start) (hcounter : work counterIdx = Tape.init []) :
                    ((((inputLengthPlusOneCounterTM counterIdx).step { state := LinearCounterPhase.scan, input := inp, work := work, output := out }).get ).work counterIdx).HasUnaryPrefix 0

                    The start-skip step positions an initially empty counter tape at cell 1, giving the zero-length unary-prefix invariant.

                    theorem Complexity.TM.inputLengthPlusOneCounterTM_scan_blank_state {n : } (counterIdx : Fin n) (inp : Tape) (work : Fin nTape) (out : Tape) (hinp : inp.read = Γ.blank) :
                    (((inputLengthPlusOneCounterTM counterIdx).step { state := LinearCounterPhase.scan, input := inp, work := work, output := out }).get ).state = LinearCounterPhase.rewind

                    In the scan phase, reading blank on the input moves the machine to the rewind phase.

                    theorem Complexity.TM.inputLengthPlusOneCounterTM_scan_bit_state {n : } (counterIdx : Fin n) (inp : Tape) (work : Fin nTape) (out : Tape) (hstart : inp.read Γ.start) (hblank : inp.read Γ.blank) :
                    (((inputLengthPlusOneCounterTM counterIdx).step { state := LinearCounterPhase.scan, input := inp, work := work, output := out }).get ).state = LinearCounterPhase.scan

                    In the scan phase, reading an input bit (neither nor blank) keeps the machine in scan.

                    theorem Complexity.TM.inputLengthPlusOneCounterTM_scan_bit_extends_counter {n : } (counterIdx : Fin n) (inp : Tape) (work : Fin nTape) (out : Tape) {used : } (hprefix : (work counterIdx).HasUnaryPrefix used) (hstart : inp.read Γ.start) (hblank : inp.read Γ.blank) :
                    ((((inputLengthPlusOneCounterTM counterIdx).step { state := LinearCounterPhase.scan, input := inp, work := work, output := out }).get ).work counterIdx).HasUnaryPrefix (used + 1)

                    Scanning an input bit writes one unary mark and advances the counter prefix by one.

                    theorem Complexity.TM.inputLengthPlusOneCounterTM_scan_blank_extends_counter {n : } (counterIdx : Fin n) (inp : Tape) (work : Fin nTape) (out : Tape) {used : } (hprefix : (work counterIdx).HasUnaryPrefix used) (hinp : inp.read = Γ.blank) :
                    ((((inputLengthPlusOneCounterTM counterIdx).step { state := LinearCounterPhase.scan, input := inp, work := work, output := out }).get ).work counterIdx).HasUnaryPrefix (used + 1)

                    Scanning the input blank writes the final extra unary mark and enters the rewind phase.

                    theorem Complexity.TM.inputLengthPlusOneCounterTM_rewind_start_state {n : } (counterIdx : Fin n) (inp : Tape) (work : Fin nTape) (out : Tape) (hcounter : (work counterIdx).read = Γ.start) :
                    (((inputLengthPlusOneCounterTM counterIdx).step { state := LinearCounterPhase.rewind, input := inp, work := work, output := out }).get ).state = LinearCounterPhase.done

                    In the rewind phase, reading on the counter tape moves the machine to done.

                    theorem Complexity.TM.inputLengthPlusOneCounterTM_rewind_left_state {n : } (counterIdx : Fin n) (inp : Tape) (work : Fin nTape) (out : Tape) (hcounter : (work counterIdx).read Γ.start) :
                    (((inputLengthPlusOneCounterTM counterIdx).step { state := LinearCounterPhase.rewind, input := inp, work := work, output := out }).get ).state = LinearCounterPhase.rewind

                    In the rewind phase, a counter-tape read other than keeps the machine in rewind.

                    theorem Complexity.TM.inputLengthPlusOneCounterTM_toNTM_trace_one_preserves_started_blank_other_work {n : } (counterIdx : Fin n) (choice : Bool) (c : Cfg n (inputLengthPlusOneCounterTM counterIdx).Q) (i : Fin n) (hi : i counterIdx) (hwork : c.work i = (Tape.init []).move Dir3.right) :
                    ((inputLengthPlusOneCounterTM counterIdx).toNTM.trace 1 (fun (x : Fin 1) => choice) c).work i = (Tape.init []).move Dir3.right

                    One NTM trace step of the lifted counter machine leaves a non-counter work tape unchanged when that tape is the started blank tape.

                    theorem Complexity.TM.inputLengthPlusOneCounterTM_toNTM_trace_one_initializes_blank_other_work {n : } (counterIdx : Fin n) (choice : Bool) (c : Cfg n (inputLengthPlusOneCounterTM counterIdx).Q) (i : Fin n) (hi : i counterIdx) (hstate : c.state LinearCounterPhase.done) (hwork : c.work i = Tape.init []) :
                    ((inputLengthPlusOneCounterTM counterIdx).toNTM.trace 1 (fun (x : Fin 1) => choice) c).work i = (Tape.init []).move Dir3.right

                    One NTM trace step of the lifted counter machine (in a non-halted state) moves a fresh blank non-counter work tape past its marker, turning it into the started blank tape.

                    One NTM trace step of the lifted counter machine leaves a started blank output tape unchanged.

                    One NTM trace step of the lifted counter machine (in a non-halted state) moves a fresh blank output tape past its marker, turning it into the started blank tape.

                    A convenient linear upper bound for inputLengthPlusOneCounterTM.

                    Equations
                    Instances For
                      theorem Complexity.TM.inputLengthPlusOneCounterTM_hoareTime {n : } (counterIdx : Fin n) (x : List Bool) :
                      (inputLengthPlusOneCounterTM counterIdx).HoareTime (fun (inp : Tape) (work : Fin nTape) (x_1 : Tape) => inp = Tape.init (List.map Γ.ofBool x) work counterIdx = Tape.init []) (fun (x_1 : Tape) (work : Fin nTape) (x_2 : Tape) => (work counterIdx).HasUnaryCounter (x.length + 1)) (inputLengthPlusOneCounterTime x.length)

                      inputLengthPlusOneCounterTM materializes a unary counter of length |x| + 1 on the designated work tape and rewinds it to cell 1.

                      theorem Complexity.TM.inputLengthPlusOneCounterTM_started_hoareTime {n : } (counterIdx : Fin n) (x : List Bool) :
                      (inputLengthPlusOneCounterTM counterIdx).HoareTime (fun (inp : Tape) (work : Fin nTape) (x_1 : Tape) => inp = (Tape.init (List.map Γ.ofBool x)).move Dir3.right work counterIdx = (Tape.init []).move Dir3.right) (fun (x_1 : Tape) (work : Fin nTape) (x_2 : Tape) => (work counterIdx).HasUnaryCounter (x.length + 1) (work counterIdx).cells 0 = Γ.start j1, (work counterIdx).cells j Γ.start) (inputLengthPlusOneCounterTime x.length)

                      Started-tape variant of inputLengthPlusOneCounterTM_hoareTime: if the input is already positioned at cell 1 and the counter tape is the started blank tape, the machine still builds a unary counter of length |x| + 1. The postcondition also exposes the structural fact that the resulting counter tape has no markers beyond cell 0.

                      theorem Complexity.TM.inputLengthPlusOneCounterTM_started_tracksInput_hoareTime {n : } (counterIdx : Fin n) (x : List Bool) :
                      (inputLengthPlusOneCounterTM counterIdx).HoareTime (fun (inp : Tape) (work : Fin nTape) (x_1 : Tape) => inp = (Tape.init (List.map Γ.ofBool x)).move Dir3.right work counterIdx = (Tape.init []).move Dir3.right) (fun (inp : Tape) (work : Fin nTape) (x_1 : Tape) => inp.cells = (Tape.init (List.map Γ.ofBool x)).cells inp.head = x.length + 1 (work counterIdx).HasUnaryCounter (x.length + 1) (work counterIdx).cells 0 = Γ.start j1, (work counterIdx).cells j Γ.start) (inputLengthPlusOneCounterTime x.length)

                      Started-tape variant of the unary counter builder that also records the final input position. The input cells are unchanged, and the input head ends at the first blank after the scanned Boolean string.

                      theorem Complexity.TM.inputLengthPlusOneCounterTM_started_tracksInput_preserves_work_hoareTime {n : } (counterIdx passiveIdx : Fin n) (hne : passiveIdx counterIdx) (x y : List Bool) :
                      (inputLengthPlusOneCounterTM counterIdx).HoareTime (fun (inp : Tape) (work : Fin nTape) (out : Tape) => inp = (Tape.init (List.map Γ.ofBool x)).move Dir3.right work counterIdx = (Tape.init []).move Dir3.right work passiveIdx = (Tape.init (List.map Γ.ofBool y)).move Dir3.right out = (Tape.init []).move Dir3.right) (fun (inp : Tape) (work : Fin nTape) (out : Tape) => inp.cells = (Tape.init (List.map Γ.ofBool x)).cells inp.head = x.length + 1 work passiveIdx = (Tape.init (List.map Γ.ofBool y)).move Dir3.right (work counterIdx).HasUnaryCounter (x.length + 1) (work counterIdx).cells 0 = Γ.start (∀ j1, (work counterIdx).cells j Γ.start) out = (Tape.init []).move Dir3.right) (inputLengthPlusOneCounterTime x.length)

                      Started-tape variant of the unary counter builder that also records the final input position and preserves one passive started Boolean work tape exactly.

                      theorem Complexity.TM.inputLengthPlusOneCounterTM_toNTM_hoareTime {n : } (counterIdx : Fin n) (x : List Bool) :
                      (inputLengthPlusOneCounterTM counterIdx).toNTM.HoareTime (fun (inp : Tape) (work : Fin nTape) (x_1 : Tape) => inp = Tape.init (List.map Γ.ofBool x) work counterIdx = Tape.init []) (fun (x_1 : Tape) (work : Fin nTape) (x_2 : Tape) => (work counterIdx).HasUnaryCounter (x.length + 1)) (inputLengthPlusOneCounterTime x.length)

                      Nondeterministic form of inputLengthPlusOneCounterTM_hoareTime, for use inside NTM constructions after lifting the deterministic setup machine.