Documentation

DescriptiveComplexity.HeadCapture

The capture theorem for NL: FO(TC) is what a multi-head automaton recognizes #

DescriptiveComplexity.HeadAutomaton compiles a machine into a DescriptiveComplexity.TCSpec, which is the easy half. This file is the other half: every FO(TC) definable problem is recognized by a two-way multi-head automaton, so that the two notions coincide and DescriptiveComplexity.NL is captured by the machine model as well as by the logic.

The machine #

Given a specification with arity k, the machine has 2 * k + D + 1 heads:

The mode of the walk is not on a head – it cannot be, a one-element universe having only one tuple – but in the control, which is what a finite control is for.

The loop #

Written as a control graph over fragments (DescriptiveComplexity.HeadProgram.wireP), the machine is:

Guessing is where the nondeterminism lives, and it is the only place: the evaluator itself is deterministic.

The proof #

DescriptiveComplexity.HeadProgram.runs_wireP turns the machine's runs into a walk in the control graph, and the correctness is then an argument about that walk, in two directions:

The result is DescriptiveComplexity.tcDefinable_iff_automaton, and with it DescriptiveComplexity.mem_NL_iff_automaton.

Free choices and guesses #

A free choice: exit either way, moving no head. It is the only source of nondeterminism in the machines built here, together with DescriptiveComplexity.HeadProgram.guessP.

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

    One step of a guess: either walk head h to the next element, or stop.

    Equations
    • One or more equations did not get rendered due to their size.
    Instances For
      Dependency graph
      @[simp]
      theorem DescriptiveComplexity.HeadProgram.tr_chooseP {L : FirstOrder.Language} {K : ℕ} (s : chooseP.St) :
      chooseP.tr s = [{ guard := ⊤, moves := fun (x : Fin K) => HeadMove.stay, target := Sum.inr true }, { guard := ⊤, moves := fun (x : Fin K) => HeadMove.stay, target := Sum.inr false }]
      Dependency graph
      @[simp]
      theorem DescriptiveComplexity.HeadProgram.tr_guessStepP {L : FirstOrder.Language} {K : ℕ} (h : Fin K) (s : (guessStepP h).St) :
      (guessStepP h).tr s = [{ guard := ⊤, moves := setHead h (HeadMove.succ h), target := Sum.inr true }, { guard := ⊤, moves := fun (x : Fin K) => HeadMove.stay, target := Sum.inr false }]
      Dependency graph

      Guessing one head #

      The control nodes of a guess.

      • reset : GuessNode

        Putting the head on the least element.

      • loop : GuessNode

        Walking it up, for as long as the machine chooses to.

      Instances For
        Dependency graph
        Dependency graph
        Dependency graph
        Dependency graph

        The fragments of a guess.

        Equations
        Instances For
          Dependency graph

          Guessing a head: put head h on the least element and walk it up a nondeterministic number of steps, so that it may end anywhere.

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

            Guessing a block of heads #

            Guessing several heads: the heads hd lo, …, hd (lo + n - 1), in turn.

            Equations
            Instances For
              Dependency graph

              The control graph of the machine #

              The control nodes of the machine simulating a specification: which mode the walk is in, and what it is doing. r is the number of modes, and the Fin (r + 1) indices walk the list of modes, one free choice at a time.

              • pickSrc {M : Type} {r : ℕ} (i : Fin (r + 1)) : DrvNode M r

                Choosing which mode to start the walk in.

              • trySrc {M : Type} {r : ℕ} (m : M) : DrvNode M r

                Guessing a starting tuple and testing the source formula.

              • target {M : Type} {r : ℕ} (m : M) : DrvNode M r

                Testing the target formula at the current node.

              • pickCand {M : Type} {r : ℕ} (m : M) (i : Fin (r + 1)) : DrvNode M r

                Choosing which mode to step into.

              • tryCand {M : Type} {r : ℕ} (m m' : M) : DrvNode M r

                Guessing the next tuple and testing the transition formula.

              • commit {M : Type} {r : ℕ} (m m' : M) : DrvNode M r

                Copying the guessed tuple onto the current one.

              • dead {M : Type} {r : ℕ} : DrvNode M r

                Nothing more to do.

              Instances For
                Dependency graph
                Dependency graph
                def DescriptiveComplexity.HeadProgram.drvWire {M : Type} {r : ℕ} (modeAt : Fin (r + 1) → Option M) (nextIx : Fin (r + 1) → Fin (r + 1)) (i₀ : Fin (r + 1)) :
                DrvNode M r → Bool → DrvNode M r ⊕ Bool

                Where the machine goes when a fragment exits.

                Equations
                Instances For
                  Dependency graph

                  The machine of a specification #

                  The quantifier budget of a specification: the largest number of extra heads the evaluation of one of its formulas needs.

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

                    How many heads the machine of a specification has: two tuples, the evaluator's workspace, and a spare one so that there is always a head.

                    Equations
                    Instances For
                      Dependency graph
                      Dependency graph
                      noncomputable def DescriptiveComplexity.blk0 {L : FirstOrder.Language} (spec : TCSpec L) (i : Fin spec.k) :
                      Fin (specHeads spec)

                      The heads holding the current tuple.

                      Equations
                      Instances For
                        Dependency graph
                        noncomputable def DescriptiveComplexity.blk1 {L : FirstOrder.Language} (spec : TCSpec L) (i : Fin spec.k) :
                        Fin (specHeads spec)

                        The heads holding the candidate tuple.

                        Equations
                        Instances For
                          Dependency graph
                          noncomputable def DescriptiveComplexity.shd {L : FirstOrder.Language} (spec : TCSpec L) (i : ℕ) :
                          Fin (specHeads spec)

                          The head at a given index, for the evaluator's workspace.

                          Equations
                          Instances For
                            Dependency graph
                            @[simp]
                            theorem DescriptiveComplexity.blk0_val {L : FirstOrder.Language} (spec : TCSpec L) (i : Fin spec.k) :
                            ↑(blk0 spec i) = ↑i
                            Dependency graph
                            @[simp]
                            theorem DescriptiveComplexity.blk1_val {L : FirstOrder.Language} (spec : TCSpec L) (i : Fin spec.k) :
                            ↑(blk1 spec i) = spec.k + ↑i
                            Dependency graph
                            noncomputable def DescriptiveComplexity.curNode {L : FirstOrder.Language} (spec : TCSpec L) {A : Type} (x : Fin (specHeads spec) → A) (m : spec.Mode) :
                            spec.Node A

                            The node of the specification the machine is at: its mode, and the tuple on the first block of heads.

                            Equations
                            Instances For
                              Dependency graph
                              noncomputable def DescriptiveComplexity.candNode {L : FirstOrder.Language} (spec : TCSpec L) {A : Type} (x : Fin (specHeads spec) → A) (m : spec.Mode) :
                              spec.Node A

                              The node the machine is considering stepping into: the tuple on the second block of heads.

                              Equations
                              Instances For
                                Dependency graph

                                The fragments #

                                noncomputable def DescriptiveComplexity.hv0 {L : FirstOrder.Language} (spec : TCSpec L) :
                                Fin spec.k ⊕ Fin 0 → Fin (specHeads spec)

                                The variables of a formula about the current tuple live in the first block of heads.

                                Equations
                                Instances For
                                  Dependency graph
                                  noncomputable def DescriptiveComplexity.hv01 {L : FirstOrder.Language} (spec : TCSpec L) :
                                  (Fin spec.k ⊕ Fin spec.k) ⊕ Fin 0 → Fin (specHeads spec)

                                  The variables of a transition formula live in the two blocks of heads.

                                  Equations
                                  Instances For
                                    Dependency graph
                                    noncomputable def DescriptiveComplexity.evalSrcP {L : FirstOrder.Language} (spec : TCSpec L) (m : spec.Mode) :

                                    The evaluator for a source formula.

                                    Equations
                                    Instances For
                                      Dependency graph
                                      noncomputable def DescriptiveComplexity.evalTgtP {L : FirstOrder.Language} (spec : TCSpec L) (m : spec.Mode) :

                                      The evaluator for a target formula.

                                      Equations
                                      Instances For
                                        Dependency graph
                                        noncomputable def DescriptiveComplexity.evalStepP {L : FirstOrder.Language} (spec : TCSpec L) (m m' : spec.Mode) :

                                        The evaluator for a transition formula.

                                        Equations
                                        Instances For
                                          Dependency graph
                                          noncomputable def DescriptiveComplexity.commitMoves {L : FirstOrder.Language} (spec : TCSpec L) :
                                          Fin (specHeads spec) → HeadMove (specHeads spec)

                                          The moves that copy the candidate tuple onto the current one.

                                          Equations
                                          Instances For
                                            Dependency graph
                                            theorem DescriptiveComplexity.headLocal_isSrc {L : FirstOrder.Language} (spec : TCSpec L) {A : Type} [L.Structure A] [LinearOrder A] (m : spec.Mode) :
                                            HeadLocal (2 * spec.k) fun (x : Fin (specHeads spec) → A) => spec.IsSrc (curNode spec x m)
                                            Dependency graph
                                            theorem DescriptiveComplexity.headLocal_isTgt {L : FirstOrder.Language} (spec : TCSpec L) {A : Type} [L.Structure A] [LinearOrder A] (m : spec.Mode) :
                                            HeadLocal (2 * spec.k) fun (x : Fin (specHeads spec) → A) => spec.IsTgt (curNode spec x m)
                                            Dependency graph
                                            theorem DescriptiveComplexity.headLocal_step {L : FirstOrder.Language} (spec : TCSpec L) {A : Type} [L.Structure A] [LinearOrder A] (m m' : spec.Mode) :
                                            HeadLocal (2 * spec.k) fun (x : Fin (specHeads spec) → A) => spec.Step (curNode spec x m) (candNode spec x m')
                                            Dependency graph

                                            The machine #

                                            noncomputable def DescriptiveComplexity.modeCard {L : FirstOrder.Language} (spec : TCSpec L) :

                                            The number of modes.

                                            Equations
                                            Instances For
                                              Dependency graph
                                              noncomputable def DescriptiveComplexity.modeEquiv {L : FirstOrder.Language} (spec : TCSpec L) :
                                              spec.Mode ≃ Fin (modeCard spec)

                                              An enumeration of the modes.

                                              Equations
                                              Instances For
                                                Dependency graph
                                                noncomputable def DescriptiveComplexity.modeAt {L : FirstOrder.Language} (spec : TCSpec L) (i : Fin (modeCard spec + 1)) :

                                                The mode at an index of the enumeration, if any.

                                                Equations
                                                Instances For
                                                  Dependency graph
                                                  noncomputable def DescriptiveComplexity.nextIx {L : FirstOrder.Language} (spec : TCSpec L) (i : Fin (modeCard spec + 1)) :
                                                  Fin (modeCard spec + 1)

                                                  The next index of the enumeration; it stops at the last one.

                                                  Equations
                                                  Instances For
                                                    Dependency graph
                                                    noncomputable def DescriptiveComplexity.ix0 {L : FirstOrder.Language} (spec : TCSpec L) :
                                                    Fin (modeCard spec + 1)

                                                    The index the enumeration starts at.

                                                    Equations
                                                    Instances For
                                                      Dependency graph
                                                      noncomputable def DescriptiveComplexity.ixOf {L : FirstOrder.Language} (spec : TCSpec L) (m : spec.Mode) :
                                                      Fin (modeCard spec + 1)

                                                      The index of a mode in the enumeration.

                                                      Equations
                                                      Instances For
                                                        Dependency graph
                                                        Dependency graph
                                                        noncomputable def DescriptiveComplexity.drvP {L : FirstOrder.Language} (spec : TCSpec L) :

                                                        The machine of a specification: the loop described in the header, as a control graph over those fragments.

                                                        Equations
                                                        • One or more equations did not get rendered due to their size.
                                                        Instances For
                                                          Dependency graph
                                                          theorem DescriptiveComplexity.curNode_congr {L : FirstOrder.Language} (spec : TCSpec L) {A : Type} {x y : Fin (specHeads spec) → A} (h : ∀ (j : Fin (specHeads spec)), ↑j < spec.k → y j = x j) (m : spec.Mode) :
                                                          curNode spec y m = curNode spec x m
                                                          Dependency graph
                                                          theorem DescriptiveComplexity.candNode_congr {L : FirstOrder.Language} (spec : TCSpec L) {A : Type} {x y : Fin (specHeads spec) → A} (h : ∀ (j : Fin (specHeads spec)), spec.k ≤ ↑j → ↑j < 2 * spec.k → y j = x j) (m : spec.Mode) :
                                                          candNode spec y m = candNode spec x m
                                                          Dependency graph

                                                          Soundness: what the machine knows #

                                                          The wiring, arc by arc.

                                                          Dependency graph
                                                          Dependency graph
                                                          Dependency graph
                                                          Dependency graph
                                                          Dependency graph
                                                          Dependency graph
                                                          Dependency graph
                                                          Dependency graph
                                                          Dependency graph
                                                          Dependency graph
                                                          Dependency graph
                                                          Dependency graph

                                                          Completeness: the machine imitates the walk #

                                                          noncomputable def DescriptiveComplexity.putBlk0 {L : FirstOrder.Language} (spec : TCSpec L) {A : Type} (x : Fin (specHeads spec) → A) (u : Fin spec.k → A) :
                                                          Fin (specHeads spec) → A

                                                          Putting a tuple on the first block of heads.

                                                          Equations
                                                          Instances For
                                                            Dependency graph
                                                            noncomputable def DescriptiveComplexity.putBlk1 {L : FirstOrder.Language} (spec : TCSpec L) {A : Type} (x : Fin (specHeads spec) → A) (u : Fin spec.k → A) :
                                                            Fin (specHeads spec) → A

                                                            Putting a tuple on the second block of heads.

                                                            Equations
                                                            Instances For
                                                              Dependency graph
                                                              theorem DescriptiveComplexity.putBlk0_blk0 {L : FirstOrder.Language} (spec : TCSpec L) {A : Type} (x : Fin (specHeads spec) → A) (u : Fin spec.k → A) (i : Fin spec.k) :
                                                              putBlk0 spec x u (blk0 spec i) = u i
                                                              Dependency graph
                                                              theorem DescriptiveComplexity.putBlk0_of_le {L : FirstOrder.Language} (spec : TCSpec L) {A : Type} (x : Fin (specHeads spec) → A) (u : Fin spec.k → A) {j : Fin (specHeads spec)} (hj : spec.k ≤ ↑j) :
                                                              putBlk0 spec x u j = x j
                                                              Dependency graph
                                                              theorem DescriptiveComplexity.putBlk1_blk1 {L : FirstOrder.Language} (spec : TCSpec L) {A : Type} (x : Fin (specHeads spec) → A) (u : Fin spec.k → A) (i : Fin spec.k) :
                                                              putBlk1 spec x u (blk1 spec i) = u i
                                                              Dependency graph
                                                              theorem DescriptiveComplexity.putBlk1_of_lt {L : FirstOrder.Language} (spec : TCSpec L) {A : Type} (x : Fin (specHeads spec) → A) (u : Fin spec.k → A) {j : Fin (specHeads spec)} (hj : ↑j < spec.k) :
                                                              putBlk1 spec x u j = x j
                                                              Dependency graph

                                                              The capture theorem #

                                                              The machine of a specification accepts exactly what the specification does.

                                                              Dependency graph

                                                              The capture theorem #

                                                              theorem DescriptiveComplexity.tcDefinable_iff_automaton {L : FirstOrder.Language} [L.IsRelational] {P : DecisionProblem L} :
                                                              TCDefinable P ↔ ∃ (k : ℕ) (M : HeadAutomaton L k), ∀ (A : Type) [inst : L.Structure A] [inst_1 : LinearOrder A] [Finite A] [Nonempty A], P.Holds A ↔ M.Accepts A

                                                              The capture theorem for FO(TC): a problem is definable by a single transitive closure exactly when a two-way multi-head automaton recognizes it. One direction is DescriptiveComplexity.tcDefinable_of_automaton – a configuration is a node of a specification – and the other is the machine built here. Registered in the Lax archive as Lax485149.NLByAutomata.tcDefinable_iff_automaton.

                                                              Dependency graph
                                                              theorem DescriptiveComplexity.mem_NL_iff_automaton {L : FirstOrder.Language} [L.IsRelational] {P : DecisionProblem L} :
                                                              NL.Mem P ↔ ∃ (k : ℕ) (M : HeadAutomaton L k), ∀ (A : Type) [inst : L.Structure A] [inst_1 : LinearOrder A] [Finite A] [Nonempty A], P.Holds A ↔ M.Accepts A

                                                              NL is the class of the two-way multi-head automata: membership in DescriptiveComplexity.NL is recognizability by such a machine. Registered in the Lax archive as Lax485149.NLByAutomata.mem_NL_iff_automaton.

                                                              Dependency graph