Documentation

DescriptiveComplexity.HeadBit

The bit of a rank, as a head program #

The fragment DescriptiveComplexity.HeadProgram.bitP: a deterministic multi-head program deciding BIT, that is, whether the bit of the rank of one head at the index given by the rank of another is set. It is what lets the multi-head automaton of DescriptiveComplexity.HeadEvalArith evaluate the bit-level logic of DescriptiveComplexity.LogTime – the third arithmetic fragment, beside DescriptiveComplexity.HeadProgram.plusP and DescriptiveComplexity.HeadProgram.timesP.

The algorithm: halve, then read the parity #

BIT(x, i) is (x / 2 ^ i) % 2 = 1, so the program halves the value i times and then asks for its parity. Both loops are the shape this development already uses: an outer loop counting the rounds, and inside it a scan that walks a candidate up the order asking, at each stop, whether the candidate is the half of the current value. That question is two additions, so the scan's probe is an addition fragment – a decider made to compute, exactly as timesP's scan reuses plusP.

The half of v is the c with c + c = v (v even) or c + (c + 1) = v (v odd), and the two are tested in that order at each candidate, so the scan stops at the first c that works and that c is v / 2 whatever the parity. The successor c + 1 is not an addition but a head: the program moves w to the successor of the candidate, which is why the overflow test comes before that move – a successor move at the greatest element is disabled, and the walk would be stuck rather than wrong.

The parity, and why it needs no guard #

After the last round the value is x / 2 ^ i, and its parity is read by a second scan: v is even exactly when some c has c + c = v, and such a c is v / 2 ≤ v, so the scan finds it if it exists. The scan therefore answers false at the first candidate that halves v, and true when it reaches the marker having found none. No test against zero is needed anywhere, which is what makes the two scans the same four nodes with different exits.

What the fragment costs #

Five working heads – the value, the round counter, the scan's candidate, the successor w, and the scan's marker – above the interface, and the addition's own three scratch heads above those; the marker is parked by the fragment itself, as plusP's is, so a caller has no discipline to keep beyond the head layout DescriptiveComplexity.HeadProgram.BitHeads. The clock is O(log n) rounds of a scan, hence O(n log n) steps – irrelevant to the space bound, which is the number of heads.

The control graph of a bit #

The control nodes of a bit: an outer loop counting the halvings, a scan looking for the half of the current value, and a second scan reading the parity of the value the outer loop leaves.

  • init : BitNode

    Copy the value onto the working head, the round counter to the least element and the scan's marker to the greatest.

  • outer : BitNode

    Has the round counter reached the index?

  • scanInit : BitNode

    It has not: start the scan at the least element.

  • probeE : BitNode

    Is the candidate twice itself the value, that is, is the value even with this half?

  • scanOver : BitNode

    It is not: is the candidate at the marker, i.e., is the scan over?

  • mkW : BitNode

    It is not: put w on the successor of the candidate.

  • probeO : BitNode

    Is the candidate plus its successor the value, that is, is the value odd with this half?

  • scanStep : BitNode

    Step the candidate.

  • commit : BitNode

    The candidate is the half: take it, and count the round.

  • parInit : BitNode

    The rounds are over: start the parity scan.

  • parProbe : BitNode

    Does the candidate halve the value, that is, is the value even?

  • parOver : BitNode

    It does not: is the parity scan over?

  • parStep : BitNode

    Step the parity scan's candidate.

Instances For
    Dependency graph
    Dependency graph
    Dependency graph

    The wiring of a bit: the outer loop outer → scan → commitouter, the scan probeEscanOvermkWprobeOscanStepprobeE, and the parity scan parProbeparOverparStepparProbe carrying the two answers.

    Equations
    Instances For
      Dependency graph
      noncomputable def DescriptiveComplexity.HeadProgram.bitInitMoves {K : } (xh y cnt tmk : Fin K) :
      Fin KHeadMove K

      The moves that start a bit: the working head copies the value, the round counter goes to the least element, and the scan's marker is parked at the greatest.

      Equations
      • One or more equations did not get rendered due to their size.
      Instances For
        Dependency graph
        noncomputable def DescriptiveComplexity.HeadProgram.bitScanInitMoves {K : } (cand : Fin K) :
        Fin KHeadMove K

        The move that starts a scan: the candidate to the least element.

        Equations
        Instances For
          Dependency graph
          noncomputable def DescriptiveComplexity.HeadProgram.bitStepMoves {K : } (cand : Fin K) :
          Fin KHeadMove K

          The move of one scan step: the candidate advances.

          Equations
          Instances For
            Dependency graph
            noncomputable def DescriptiveComplexity.HeadProgram.bitWMoves {K : } (cand w : Fin K) :
            Fin KHeadMove K

            The move that prepares the odd probe: w takes the successor of the candidate. It is guarded by the overflow test, a successor move at the greatest element being disabled.

            Equations
            Instances For
              Dependency graph
              noncomputable def DescriptiveComplexity.HeadProgram.bitCommitMoves {K : } (y cnt cand : Fin K) :
              Fin KHeadMove K

              The moves that close a round: the working head takes the half the scan found, and the round counter advances.

              Equations
              • One or more equations did not get rendered due to their size.
              Instances For
                Dependency graph
                noncomputable def DescriptiveComplexity.HeadProgram.bitFam {L : FirstOrder.Language} {K : } (ih xh y cnt cand w tmk a b mk : Fin K) :

                The fragments of a bit. The two probes are addition programs (DescriptiveComplexity.HeadProgram.plusP): probeE asks whether the candidate doubles to the value, probeO whether the candidate plus its successor does.

                Equations
                Instances For
                  Dependency graph
                  noncomputable def DescriptiveComplexity.HeadProgram.bitP {L : FirstOrder.Language} {K : } (ih xh y cnt cand w tmk a b mk : Fin K) :

                  The bit: decide whether the bit of orank (x xh) at the index orank (x ih) is set, by halving the value orank (x ih) times and reading the parity of what is left.

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

                    The head layout of a bit #

                    structure DescriptiveComplexity.HeadProgram.BitHeads {K : } (ih xh y cnt cand w tmk a b mk : Fin K) (p S m : ) :

                    The head indices a caller of a bit must respect. The two interface heads are below the caller's level p, the five working heads occupy S to S + 4 for some S ≥ p, and the addition's three scratch heads sit at m = S + 5 – so that every distinctness the construction needs is an arithmetic fact rather than a hypothesis.

                    • hih : ih < p

                      The index is interface.

                    • hxh : xh < p

                      The value is interface.

                    • hpS : p S

                      The caller's level is below the fragment's scratch.

                    • hy : y = S

                      The working value sits at S.

                    • hcnt : cnt = S + 1

                      The round counter sits at S + 1.

                    • hcand : cand = S + 2

                      The scan's candidate sits at S + 2.

                    • hw : w = S + 3

                      The candidate's successor sits at S + 3.

                    • htmk : tmk = S + 4

                      The scan's marker sits at S + 4.

                    • hm : m = S + 5

                      The working heads end where the addition's scratch begins.

                    • ha : a = m

                      The addition's running head sits at m.

                    • hb : b = m + 1

                      The addition's counter sits at m + 1.

                    • hmk : mk = m + 2

                      The addition's marker sits at m + 2.

                    Instances For
                      Dependency graph
                      theorem DescriptiveComplexity.HeadProgram.BitHeads.lt_m_y {K : } {ih xh y cnt cand w tmk a b mk : Fin K} {p S m : } (h : BitHeads ih xh y cnt cand w tmk a b mk p S m) :
                      y < m
                      Dependency graph
                      theorem DescriptiveComplexity.HeadProgram.BitHeads.lt_m_cnt {K : } {ih xh y cnt cand w tmk a b mk : Fin K} {p S m : } (h : BitHeads ih xh y cnt cand w tmk a b mk p S m) :
                      cnt < m
                      Dependency graph
                      theorem DescriptiveComplexity.HeadProgram.BitHeads.lt_m_cand {K : } {ih xh y cnt cand w tmk a b mk : Fin K} {p S m : } (h : BitHeads ih xh y cnt cand w tmk a b mk p S m) :
                      cand < m
                      Dependency graph
                      theorem DescriptiveComplexity.HeadProgram.BitHeads.lt_m_w {K : } {ih xh y cnt cand w tmk a b mk : Fin K} {p S m : } (h : BitHeads ih xh y cnt cand w tmk a b mk p S m) :
                      w < m
                      Dependency graph
                      theorem DescriptiveComplexity.HeadProgram.BitHeads.lt_m_tmk {K : } {ih xh y cnt cand w tmk a b mk : Fin K} {p S m : } (h : BitHeads ih xh y cnt cand w tmk a b mk p S m) :
                      tmk < m
                      Dependency graph
                      theorem DescriptiveComplexity.HeadProgram.BitHeads.lt_m_ih {K : } {ih xh y cnt cand w tmk a b mk : Fin K} {p S m : } (h : BitHeads ih xh y cnt cand w tmk a b mk p S m) :
                      ih < m
                      Dependency graph
                      theorem DescriptiveComplexity.HeadProgram.BitHeads.lt_m_xh {K : } {ih xh y cnt cand w tmk a b mk : Fin K} {p S m : } (h : BitHeads ih xh y cnt cand w tmk a b mk p S m) :
                      xh < m
                      Dependency graph
                      theorem DescriptiveComplexity.HeadProgram.BitHeads.le_pm {K : } {ih xh y cnt cand w tmk a b mk : Fin K} {p S m : } (h : BitHeads ih xh y cnt cand w tmk a b mk p S m) :
                      p m
                      Dependency graph
                      theorem DescriptiveComplexity.HeadProgram.BitHeads.plusE {K : } {ih xh y cnt cand w tmk a b mk : Fin K} {p S m : } (h : BitHeads ih xh y cnt cand w tmk a b mk p S m) :
                      PlusHeads cand cand y a b mk m

                      The even probe has the head layout an addition asks for.

                      Dependency graph
                      theorem DescriptiveComplexity.HeadProgram.BitHeads.plusO {K : } {ih xh y cnt cand w tmk a b mk : Fin K} {p S m : } (h : BitHeads ih xh y cnt cand w tmk a b mk p S m) :
                      PlusHeads cand w y a b mk m

                      The odd probe has it too.

                      Dependency graph

                      The distinctness of the working heads, read off their positions #

                      theorem DescriptiveComplexity.HeadProgram.BitHeads.ne_y_cnt {K : } {ih xh y cnt cand w tmk a b mk : Fin K} {p S m : } (h : BitHeads ih xh y cnt cand w tmk a b mk p S m) :
                      y cnt
                      Dependency graph
                      theorem DescriptiveComplexity.HeadProgram.BitHeads.ne_y_cand {K : } {ih xh y cnt cand w tmk a b mk : Fin K} {p S m : } (h : BitHeads ih xh y cnt cand w tmk a b mk p S m) :
                      y cand
                      Dependency graph
                      theorem DescriptiveComplexity.HeadProgram.BitHeads.ne_y_w {K : } {ih xh y cnt cand w tmk a b mk : Fin K} {p S m : } (h : BitHeads ih xh y cnt cand w tmk a b mk p S m) :
                      y w
                      Dependency graph
                      theorem DescriptiveComplexity.HeadProgram.BitHeads.ne_y_tmk {K : } {ih xh y cnt cand w tmk a b mk : Fin K} {p S m : } (h : BitHeads ih xh y cnt cand w tmk a b mk p S m) :
                      y tmk
                      Dependency graph
                      theorem DescriptiveComplexity.HeadProgram.BitHeads.ne_cnt_cand {K : } {ih xh y cnt cand w tmk a b mk : Fin K} {p S m : } (h : BitHeads ih xh y cnt cand w tmk a b mk p S m) :
                      cnt cand
                      Dependency graph
                      theorem DescriptiveComplexity.HeadProgram.BitHeads.ne_cnt_w {K : } {ih xh y cnt cand w tmk a b mk : Fin K} {p S m : } (h : BitHeads ih xh y cnt cand w tmk a b mk p S m) :
                      cnt w
                      Dependency graph
                      theorem DescriptiveComplexity.HeadProgram.BitHeads.ne_cnt_tmk {K : } {ih xh y cnt cand w tmk a b mk : Fin K} {p S m : } (h : BitHeads ih xh y cnt cand w tmk a b mk p S m) :
                      cnt tmk
                      Dependency graph
                      theorem DescriptiveComplexity.HeadProgram.BitHeads.ne_cand_w {K : } {ih xh y cnt cand w tmk a b mk : Fin K} {p S m : } (h : BitHeads ih xh y cnt cand w tmk a b mk p S m) :
                      cand w
                      Dependency graph
                      theorem DescriptiveComplexity.HeadProgram.BitHeads.ne_cand_tmk {K : } {ih xh y cnt cand w tmk a b mk : Fin K} {p S m : } (h : BitHeads ih xh y cnt cand w tmk a b mk p S m) :
                      cand tmk
                      Dependency graph
                      theorem DescriptiveComplexity.HeadProgram.BitHeads.ne_w_tmk {K : } {ih xh y cnt cand w tmk a b mk : Fin K} {p S m : } (h : BitHeads ih xh y cnt cand w tmk a b mk p S m) :
                      w tmk
                      Dependency graph
                      theorem DescriptiveComplexity.HeadProgram.BitHeads.ne_int {K : } {ih xh y cnt cand w tmk a b mk : Fin K} {p S m : } (h : BitHeads ih xh y cnt cand w tmk a b mk p S m) {q : Fin K} (hq : q < p) :
                      q y q cnt q cand q w q tmk

                      An interface head is none of the working ones.

                      Dependency graph

                      What the fragments of a bit run #

                      noncomputable def DescriptiveComplexity.HeadProgram.bitFamRel {K : } {A : Type} [LinearOrder A] (ih xh y cnt cand w tmk : Fin K) (m : ) :
                      BitNode(Fin KA)Bool(Fin KA)Prop

                      The relations the fragments of a bit run, at the level m that protects the working heads and leaves the addition's scratch heads free.

                      Equations
                      • One or more equations did not get rendered due to their size.
                      Instances For
                        Dependency graph
                        theorem DescriptiveComplexity.HeadProgram.runs_bitFam {L : FirstOrder.Language} {K : } {A : Type} [L.Structure A] [LinearOrder A] [Finite A] {ih xh y cnt cand w tmk a b mk : Fin K} {p S m : } (hh : BitHeads ih xh y cnt cand w tmk a b mk p S m) (hmK : m K) (c : BitNode) :
                        (bitFam ih xh y cnt cand w tmk a b mk c).Runs A m (bitFamRel ih xh y cnt cand w tmk m c)
                        Dependency graph
                        theorem DescriptiveComplexity.HeadProgram.headLocal2_bitFamRel {K : } {A : Type} [LinearOrder A] {ih xh y cnt cand w tmk a b mk : Fin K} {p S m : } (hh : BitHeads ih xh y cnt cand w tmk a b mk p S m) (c : BitNode) :
                        HeadLocal2 m (bitFamRel ih xh y cnt cand w tmk m c)
                        Dependency graph
                        theorem DescriptiveComplexity.HeadProgram.deterministic_bitP {L : FirstOrder.Language} {K : } {A : Type} [L.Structure A] [LinearOrder A] (ih xh y cnt cand w tmk a b mk : Fin K) :
                        (bitP ih xh y cnt cand w tmk a b mk).Deterministic A

                        A bit is deterministic: every node of its control graph is – the two probes because an addition is.

                        Dependency graph

                        The invariant of the control walk #

                        def DescriptiveComplexity.HeadProgram.BitBase {K : } {A : Type} [LinearOrder A] (ih xh y cnt cand w tmk : Fin K) (m : ) (x z : Fin KA) :

                        The invariant of both loops: the working head carries the value halved once per round counted, the counter has not passed the index, the marker is parked at the greatest element, and nothing else below the protection level has moved.

                        Equations
                        • One or more equations did not get rendered due to their size.
                        Instances For
                          Dependency graph
                          def DescriptiveComplexity.HeadProgram.NoHalf {K : } {A : Type} [LinearOrder A] (y cand : Fin K) (z : Fin KA) :

                          The invariant of the halving scan: no candidate below the current one is the half of the value, on either parity.

                          Equations
                          • One or more equations did not get rendered due to their size.
                          Instances For
                            Dependency graph
                            def DescriptiveComplexity.HeadProgram.NoEven {K : } {A : Type} [LinearOrder A] (y cand : Fin K) (z : Fin KA) :

                            The invariant of the parity scan: no candidate below the current one halves the value.

                            Equations
                            Instances For
                              Dependency graph
                              def DescriptiveComplexity.HeadProgram.BitInv {K : } {A : Type} [LinearOrder A] (ih xh y cnt cand w tmk : Fin K) (m : ) (x : Fin KA) :
                              BitNode(Fin KA)Prop

                              The invariant of the control walk of a bit, node by node.

                              Equations
                              Instances For
                                Dependency graph
                                theorem DescriptiveComplexity.HeadProgram.NoHalf.congr {K : } {A : Type} [LinearOrder A] {y cand : Fin K} {z z' : Fin KA} (h : NoHalf y cand z) (hy : z' y = z y) (hc : z' cand = z cand) :
                                NoHalf y cand z'

                                The scan invariants only look at the value and the candidate.

                                Dependency graph
                                theorem DescriptiveComplexity.HeadProgram.NoEven.congr {K : } {A : Type} [LinearOrder A] {y cand : Fin K} {z z' : Fin KA} (h : NoEven y cand z) (hy : z' y = z y) (hc : z' cand = z cand) :
                                NoEven y cand z'
                                Dependency graph
                                theorem DescriptiveComplexity.HeadProgram.BitBase.int {K : } {A : Type} [LinearOrder A] {ih xh y cnt cand w tmk a b mk : Fin K} {p S m : } (hh : BitHeads ih xh y cnt cand w tmk a b mk p S m) {x z : Fin KA} (hb : BitBase ih xh y cnt cand w tmk m x z) {q : Fin K} (hq : q < p) :
                                z q = x q

                                The interface heads are untouched all along the walk.

                                Dependency graph
                                theorem DescriptiveComplexity.HeadProgram.BitBase.congr {K : } {A : Type} [LinearOrder A] {ih xh y cnt cand w tmk a b mk : Fin K} {p S m : } {x z z' : Fin KA} (hh : BitHeads ih xh y cnt cand w tmk a b mk p S m) (hb : BitBase ih xh y cnt cand w tmk m x z) (hz : HeadAgree m z z') :
                                BitBase ih xh y cnt cand w tmk m x z'

                                The invariant survives a fragment that moves nothing below the protection level.

                                Dependency graph

                                Reading the moves #

                                theorem DescriptiveComplexity.HeadProgram.holds_bitInitMoves {K : } {A : Type} [LinearOrder A] {ih xh y cnt cand w tmk a b mk : Fin K} {p S m : } {x z : Fin KA} (hh : BitHeads ih xh y cnt cand w tmk a b mk p S m) (hmv : ∀ (q : Fin K), q < m(bitInitMoves xh y cnt tmk q).Holds x q (z q)) :
                                z y = x xh (∀ (e : A), z cnt e) (∀ (e : A), e z tmk) ∀ (q : Fin K), q < mq yq cntq tmkz q = x q
                                Dependency graph
                                theorem DescriptiveComplexity.HeadProgram.holds_bitScanInitMoves {K : } {A : Type} [LinearOrder A] {ih xh y cnt cand w tmk a b mk : Fin K} {p S m : } {x z : Fin KA} (hh : BitHeads ih xh y cnt cand w tmk a b mk p S m) (hmv : ∀ (q : Fin K), q < m(bitScanInitMoves cand q).Holds x q (z q)) :
                                (∀ (e : A), z cand e) ∀ (q : Fin K), q < mq candz q = x q
                                Dependency graph
                                theorem DescriptiveComplexity.HeadProgram.holds_bitStepMoves {K : } {A : Type} [LinearOrder A] {ih xh y cnt cand w tmk a b mk : Fin K} {p S m : } {x z : Fin KA} (hh : BitHeads ih xh y cnt cand w tmk a b mk p S m) (hmv : ∀ (q : Fin K), q < m(bitStepMoves cand q).Holds x q (z q)) :
                                x cand z cand ∀ (q : Fin K), q < mq candz q = x q
                                Dependency graph
                                theorem DescriptiveComplexity.HeadProgram.holds_bitWMoves {K : } {A : Type} [LinearOrder A] {ih xh y cnt cand w tmk a b mk : Fin K} {p S m : } {x z : Fin KA} (hh : BitHeads ih xh y cnt cand w tmk a b mk p S m) (hmv : ∀ (q : Fin K), q < m(bitWMoves cand w q).Holds x q (z q)) :
                                x cand z w ∀ (q : Fin K), q < mq wz q = x q
                                Dependency graph
                                theorem DescriptiveComplexity.HeadProgram.holds_bitCommitMoves {K : } {A : Type} [LinearOrder A] {ih xh y cnt cand w tmk a b mk : Fin K} {p S m : } {x z : Fin KA} (hh : BitHeads ih xh y cnt cand w tmk a b mk p S m) (hmv : ∀ (q : Fin K), q < m(bitCommitMoves y cnt cand q).Holds x q (z q)) :
                                z y = x cand x cnt z cnt ∀ (q : Fin K), q < mq yq cntz q = x q
                                Dependency graph

                                Soundness: the invariant of the control walk #

                                theorem DescriptiveComplexity.HeadProgram.bitInv_of_walk {K : } {A : Type} [LinearOrder A] [Finite A] {ih xh y cnt cand w tmk a b mk : Fin K} {p S m : } (hh : BitHeads ih xh y cnt cand w tmk a b mk p S m) (x : Fin KA) (u : BitNode × (Fin KA)) :
                                Relation.ReflTransGen (wireStep (bitFamRel ih xh y cnt cand w tmk m) bitWire) (BitNode.init, x) uBitInv ih xh y cnt cand w tmk m x u.1 u.2

                                The invariant holds all along the control walk: this is the whole soundness argument, the two exits being read off it.

                                Dependency graph

                                Completeness: building the walks #

                                theorem DescriptiveComplexity.HeadProgram.walk_scan_step {K : } {A : Type} [LinearOrder A] [Finite A] {ih xh y cnt cand w tmk a b mk : Fin K} {p S m : } (hh : BitHeads ih xh y cnt cand w tmk a b mk p S m) {z : Fin KA} (hlt : orank (z cand) + orank (z cand) + 1 < orank (z y)) (htop : ∀ (e : A), e z tmk) :
                                ∃ (z' : Fin KA), DescriptiveComplexity.HeadProgram.BWalk✝ ih xh y cnt cand w tmk m (BitNode.probeE, z) (BitNode.probeE, z') orank (z' cand) = orank (z cand) + 1 ∀ (q : Fin K), q < mq candq wz' q = z q

                                One turn of the halving scan: a candidate strictly below the half is rejected by both probes, so the scan steps on.

                                Dependency graph
                                theorem DescriptiveComplexity.HeadProgram.walk_scan {K : } {A : Type} [LinearOrder A] [Finite A] {ih xh y cnt cand w tmk a b mk : Fin K} {p S m : } (hh : BitHeads ih xh y cnt cand w tmk a b mk p S m) {z : Fin KA} (hmin : ∀ (e : A), z cand e) (htop : ∀ (e : A), e z tmk) (t : ) :
                                t orank (z y) / 2∃ (z' : Fin KA), DescriptiveComplexity.HeadProgram.BWalk✝ ih xh y cnt cand w tmk m (BitNode.probeE, z) (BitNode.probeE, z') orank (z' cand) = t ∀ (q : Fin K), q < mq candq wz' q = z q

                                The halving scan reaches the half: the candidate walks up to v / 2, every earlier candidate being rejected.

                                Dependency graph
                                theorem DescriptiveComplexity.HeadProgram.walk_commit {K : } {A : Type} [LinearOrder A] [Finite A] {ih xh y cnt cand w tmk a b mk : Fin K} {p S m : } (hh : BitHeads ih xh y cnt cand w tmk a b mk p S m) {z : Fin KA} (hcandh : orank (z cand) = orank (z y) / 2) (htop : ∀ (e : A), e z tmk) :
                                ∃ (z' : Fin KA), DescriptiveComplexity.HeadProgram.BWalk✝ ih xh y cnt cand w tmk m (BitNode.probeE, z) (BitNode.commit, z') ∀ (q : Fin K), q < mq wz' q = z q

                                The scan commits: at the half, one of the two probes succeeds and the round is closed.

                                Dependency graph
                                theorem DescriptiveComplexity.HeadProgram.walk_outer {K : } {A : Type} [LinearOrder A] [Finite A] {ih xh y cnt cand w tmk a b mk : Fin K} {p S m : } (hh : BitHeads ih xh y cnt cand w tmk a b mk p S m) (x : Fin KA) (t : ) :
                                t orank (x ih)∃ (z : Fin KA), DescriptiveComplexity.HeadProgram.BWalk✝ ih xh y cnt cand w tmk m (BitNode.init, x) (BitNode.outer, z) orank (z cnt) = t orank (z y) = orank (x xh) / 2 ^ t (∀ (e : A), e z tmk) ∀ (q : Fin K), q < mq yq cntq candq wq tmkz q = x q

                                The outer loop runs: after t rounds the working head carries the value halved t times, and the counter has counted them.

                                Dependency graph
                                theorem DescriptiveComplexity.HeadProgram.walk_par_step {K : } {A : Type} [LinearOrder A] [Finite A] {ih xh y cnt cand w tmk a b mk : Fin K} {p S m : } (_hh : BitHeads ih xh y cnt cand w tmk a b mk p S m) {z : Fin KA} (hprobe : orank (z cand) + orank (z cand) orank (z y)) (hlt : orank (z cand) < orank (z tmk)) :
                                ∃ (z' : Fin KA), DescriptiveComplexity.HeadProgram.BWalk✝ ih xh y cnt cand w tmk m (BitNode.parProbe, z) (BitNode.parProbe, z') orank (z' cand) = orank (z cand) + 1 ∀ (q : Fin K), q < mq candz' q = z q

                                One turn of the parity scan: a candidate that does not halve the value, and is not at the marker, steps on.

                                Dependency graph
                                theorem DescriptiveComplexity.HeadProgram.walk_par {K : } {A : Type} [LinearOrder A] [Finite A] {ih xh y cnt cand w tmk a b mk : Fin K} {p S m : } (hh : BitHeads ih xh y cnt cand w tmk a b mk p S m) {z : Fin KA} (hmin : ∀ (e : A), z cand e) (t : ) :
                                t orank (z tmk)(∀ d < t, d + d orank (z y))∃ (z' : Fin KA), DescriptiveComplexity.HeadProgram.BWalk✝ ih xh y cnt cand w tmk m (BitNode.parProbe, z) (BitNode.parProbe, z') orank (z' cand) = t ∀ (q : Fin K), q < mq candz' q = z q

                                The parity scan walks: as long as no candidate below has halved the value, the scan reaches every index up to the marker.

                                Dependency graph

                                What a bit decides #

                                theorem DescriptiveComplexity.HeadProgram.decides_bitP {L : FirstOrder.Language} {K : } {A : Type} [L.Structure A] [LinearOrder A] [Finite A] {ih xh y cnt cand w tmk a b mk : Fin K} {p S m : } (hh : BitHeads ih xh y cnt cand w tmk a b mk p S m) (hmK : m K) :
                                (bitP ih xh y cnt cand w tmk a b mk).Decides A p fun (x : Fin KA) => (orank (x xh)).testBit (orank (x ih)) = true

                                The bit fragment decides the bit, with no side condition: the marker is parked by the fragment itself, the halvings are exact, and the parity scan is exhaustive.

                                Dependency graph