Documentation

Complexitylib.Classes.NP.Internal.PairBuildTM

pairBuildTM: construct pair x y on a work tape #

The DTM pairBuildTM k yIdx pIdx assumes:

After running, work tape pIdx carries pair x y — the doubled-bits encoding of x followed by the [false, true] separator followed by y verbatim — with head positioned at cell 1, matching the convention used by the other rewindWorkTM-based subroutines.

Phase structure #

init        advance every ▷-reading tape past ▷ (one step)
copyX1      if input blank → writeSep1; else write bit to pIdx, advance pIdx
copyX2      write the same bit to pIdx, advance input *and* pIdx
writeSep1   write `false` to pIdx, advance pIdx
writeSep2   write `true`  to pIdx, advance pIdx
copyY       if y blank → rewindP1; else write y-bit to pIdx, advance y+pIdx
rewindP1    if pIdx reads ▷ → rewindP2; else move pIdx left
rewindP2    one extra right step, transition to done (leaves pIdx head=1)
done        halt

Total running time: linear in |x| + |y| (see pairBuildTM_hoareTime).

Status #

Everything in this file is fully proved (no sorry). The main contents:

Control states of pairBuildTM, one per phase of the construction: advance past (init), double each input bit onto the pair tape (copyX1/copyX2), write the [false, true] separator (writeSep1/writeSep2), copy the witness verbatim (copyY), rewind the pair tape to cell 1 (rewindP1/rewindP2), and halt (done).

Instances For
    @[implicit_reducible]
    Equations
    • One or more equations did not get rendered due to their size.
    def Complexity.TM.pairBuildTM {k : } (yIdx pIdx : Fin k) :
    TM k

    Build pair x y on work tape pIdx, reading x from the input tape and y from work tape yIdx. Requires yIdx ≠ pIdx for the construction to make sense; the definition itself is valid for any indices.

    Equations
    • One or more equations did not get rendered due to their size.
    Instances For
      theorem Complexity.TM.pairBuild_init_step_started {k : } (yIdx pIdx : Fin k) (c : Cfg k (pairBuildTM yIdx pIdx).Q) (hst : c.state = PairBuildPhase.init) (hinp : c.input.read Γ.start) (hy : (c.work yIdx).read Γ.start) (hpi0 : (c.work pIdx).head = 0) (hpic0 : (c.work pIdx).cells 0 = Γ.start) :
      ∃ (c' : Cfg k (pairBuildTM yIdx pIdx).Q), (pairBuildTM yIdx pIdx).step c = some c' c'.state = PairBuildPhase.copyX1 c'.input = c.input c'.work yIdx = c.work yIdx (c'.work pIdx).head = 1 (c'.work pIdx).cells = (c.work pIdx).cells

      Variant of the init step for phase composition: input and witness tapes may already be positioned at their first data cells, while the pair tape is still the fresh head-0 tape.

      theorem Complexity.TM.pairBuild_init_step_all_started {k : } (yIdx pIdx : Fin k) (c : Cfg k (pairBuildTM yIdx pIdx).Q) (hst : c.state = PairBuildPhase.init) (hinp : c.input.read Γ.start) (hy : (c.work yIdx).read Γ.start) (hp : (c.work pIdx).read Γ.start) :
      ∃ (c' : Cfg k (pairBuildTM yIdx pIdx).Q), (pairBuildTM yIdx pIdx).step c = some c' c'.state = PairBuildPhase.copyX1 c'.input = c.input c'.work yIdx = c.work yIdx c'.work pIdx = c.work pIdx

      Variant of the init step for fully-started phase composition: input, witness, and pair tapes may all already be positioned past .

      Running-time bound: pairBuildTM finishes in 4·|x| + 2·|y| + 10 steps.

      Breakdown:

      Equations
      Instances For
        theorem Complexity.TM.Tape.eq_init_move_right_of_binary {t : Tape} {bits : List Bool} (hhead : t.head = 1) (h0 : t.cells 0 = Γ.start) (hbits : ∀ (i : ) (h : i < bits.length), t.cells (i + 1) = Γ.ofBool bits[i]) (htail : ∀ (i : ), bits.length it.cells (i + 1) = Γ.blank) :

        A tape with head at cell 1, a start marker at cell 0, binary contents bits, and a blank tail is exactly the standard initialized tape for bits, moved right once.

        theorem Complexity.TM.pairBuildTM_hoareTime {k : } (yIdx pIdx : Fin k) (hne : yIdx pIdx) (x y : List Bool) :
        (pairBuildTM yIdx pIdx).HoareTime (fun (inp : Tape) (work : Fin kTape) (x_1 : Tape) => inp = Tape.init (List.map Γ.ofBool x) work yIdx = Tape.init (List.map Γ.ofBool y) work pIdx = Tape.init []) (fun (x_1 : Tape) (work : Fin kTape) (x_2 : Tape) => (work pIdx).head = 1 (work pIdx).cells 0 = Γ.start (∀ (i : ) (h : i < (pair x y).length), (work pIdx).cells (i + 1) = Γ.ofBool (pair x y)[i]) ∀ (i : ), (pair x y).length i(work pIdx).cells (i + 1) = Γ.blank) (pairBuildTime x.length y.length)

        pairBuildTM correctness. Given x on the input tape and y on work tape yIdx (with yIdx ≠ pIdx), pairBuildTM yIdx pIdx halts leaving work tape pIdx carrying pair x y (in the cells indexed 1..|pair x y|), blank thereafter, with head at cell 1, within pairBuildTime steps.

        theorem Complexity.TM.pairBuildTM_hoareTime_initTape_move_right {k : } (yIdx pIdx : Fin k) (hne : yIdx pIdx) (x y : List Bool) :
        (pairBuildTM yIdx pIdx).HoareTime (fun (inp : Tape) (work : Fin kTape) (x_1 : Tape) => inp = Tape.init (List.map Γ.ofBool x) work yIdx = Tape.init (List.map Γ.ofBool y) work pIdx = Tape.init []) (fun (x_1 : Tape) (work : Fin kTape) (x_2 : Tape) => work pIdx = (Tape.init (List.map Γ.ofBool (pair x y))).move Dir3.right) (pairBuildTime x.length y.length)

        A compact corollary of pairBuildTM_hoareTime: the pair tape satisfies exact equality with the standard initialized pair tape, moved to cell 1.

        theorem Complexity.TM.pairBuildTM_hoareTime_all_started_initTape_move_right {k : } (yIdx pIdx : Fin k) (hne : yIdx pIdx) (x y : List Bool) :
        (pairBuildTM yIdx pIdx).HoareTime (fun (inp : Tape) (work : Fin kTape) (x_1 : Tape) => inp = (Tape.init (List.map Γ.ofBool x)).move Dir3.right work yIdx = (Tape.init (List.map Γ.ofBool y)).move Dir3.right work pIdx = (Tape.init []).move Dir3.right) (fun (x_1 : Tape) (work : Fin kTape) (x_2 : Tape) => work pIdx = (Tape.init (List.map Γ.ofBool (pair x y))).move Dir3.right) (pairBuildTime x.length y.length)

        pairBuildTM correctness for phase composition where input, witness, and pair tapes have already passed the start marker. This is the layout produced by earlier setup phases that idle untouched tapes once from to cell 1.

        theorem Complexity.TM.pairBuildTM_toNTM_hoareTime_all_started_initTape_move_right {k : } (yIdx pIdx : Fin k) (hne : yIdx pIdx) (x y : List Bool) :
        (pairBuildTM yIdx pIdx).toNTM.HoareTime (fun (inp : Tape) (work : Fin kTape) (x_1 : Tape) => inp = (Tape.init (List.map Γ.ofBool x)).move Dir3.right work yIdx = (Tape.init (List.map Γ.ofBool y)).move Dir3.right work pIdx = (Tape.init []).move Dir3.right) (fun (x_1 : Tape) (work : Fin kTape) (x_2 : Tape) => work pIdx = (Tape.init (List.map Γ.ofBool (pair x y))).move Dir3.right) (pairBuildTime x.length y.length)

        Nondeterministic lift of pairBuildTM_hoareTime_all_started_initTape_move_right.

        theorem Complexity.TM.pairBuildTM_trace_one_preserves_output {k : } (yIdx pIdx : Fin k) (choice : Bool) (c : Cfg k (pairBuildTM yIdx pIdx).Q) (hread : c.output.read Γ.start) :
        ((pairBuildTM yIdx pIdx).toNTM.trace 1 (fun (x : Fin 1) => choice) c).output = c.output

        One pair-builder step preserves the output tape once the output head is past the start marker.

        theorem Complexity.TM.pairBuildTM_trace_preserves_output {k : } (yIdx pIdx : Fin k) (T : ) (choices : Fin TBool) (c : Cfg k (pairBuildTM yIdx pIdx).Q) (hread : c.output.read Γ.start) :
        ((pairBuildTM yIdx pIdx).toNTM.trace T choices c).output = c.output

        Pair-builder traces preserve the output tape once the output head is past the start marker.

        theorem Complexity.TM.pairBuildTM_trace_one_preserves_other_work {k : } (yIdx pIdx otherIdx : Fin k) (choice : Bool) (c : Cfg k (pairBuildTM yIdx pIdx).Q) (hy : otherIdx yIdx) (hp : otherIdx pIdx) (hread : (c.work otherIdx).read Γ.start) :
        ((pairBuildTM yIdx pIdx).toNTM.trace 1 (fun (x : Fin 1) => choice) c).work otherIdx = c.work otherIdx

        One pair-builder step preserves a non-active work tape once that tape's head is past the start marker.

        theorem Complexity.TM.pairBuildTM_trace_preserves_other_work {k : } (yIdx pIdx otherIdx : Fin k) (T : ) (choices : Fin TBool) (c : Cfg k (pairBuildTM yIdx pIdx).Q) (hy : otherIdx yIdx) (hp : otherIdx pIdx) (hread : (c.work otherIdx).read Γ.start) :
        ((pairBuildTM yIdx pIdx).toNTM.trace T choices c).work otherIdx = c.work otherIdx

        Pair-builder traces preserve a non-active work tape once that tape's head is past the start marker.

        theorem Complexity.TM.pairBuildTM_hoareTime_hasOutput {k : } (yIdx pIdx : Fin k) (hne : yIdx pIdx) (x y : List Bool) :
        (pairBuildTM yIdx pIdx).HoareTime (fun (inp : Tape) (work : Fin kTape) (x_1 : Tape) => inp = Tape.init (List.map Γ.ofBool x) work yIdx = Tape.init (List.map Γ.ofBool y) work pIdx = Tape.init []) (fun (x_1 : Tape) (work : Fin kTape) (x_2 : Tape) => (work pIdx).head = 1 (work pIdx).HasOutput (pair x y)) (pairBuildTime x.length y.length)

        A compact corollary of pairBuildTM_hoareTime: the pair tape satisfies the standard Tape.HasOutput predicate for pair x y.