Documentation

DescriptiveComplexity.HeadProgram

Programs: two-way multi-head automata, written with guarded transitions #

DescriptiveComplexity.HeadAutomaton is the machine model of the logarithmic-space level, and it is stated the way a finished machine wants to be stated: a fixed list of tests, and a transition table indexed by every outcome those tests may have. That presentation is exactly wrong for building a machine, where one wants to write one transition at a time, each carrying its own guard, and to paste machines together.

This file is the assembly language. A DescriptiveComplexity.HeadProgram is the same model with the transitions presented individually –

– and two compilations back into the finished form: toAutomaton, which enables every transition whose guard holds, and toAutomatonPri, which enables the first one, so that the compiled table has at most one entry per reading and DescriptiveComplexity.HeadAutomaton.IsDeterministic holds on the nose. Programs whose guards are mutually exclusive (DescriptiveComplexity.HeadProgram.Deterministic) run the same way under both.

What a program is proved to do #

Two exits rather than one is what makes programs composable: a fragment can be used as a test by another fragment. The specification of a fragment is DescriptiveComplexity.HeadProgram.Runs: a relation R x b y describing which exits b, with which head positions y, are reachable from the entry at head positions x. It has two halves, and they are not symmetric –

The scratch heads are the point of the number m carried by Runs: heads below m are the fragment's protected interface, heads from m on are workspace. DescriptiveComplexity.HeadAgree and DescriptiveComplexity.HeadLocal2 say "agrees on the interface" and "depends only on the interface".

Composition #

Everything is built from four pieces:

wireP subsumes sequencing, branching and looping, and DescriptiveComplexity.HeadProgram.runs_wireP reduces the runs of the assembled program to a walk in the control graph whose steps are the runs of the fragments. Every later construction – the formula evaluator, and the drivers that turn a DescriptiveComplexity.TCSpec into a machine – is a control graph over fragments, and its correctness proof is an argument about that walk, never about states.

The engine room is DescriptiveComplexity.HeadProgram.Embeds: a fragment sitting inside a larger program, with the two lemmas that a run of the fragment is a run of the program, and – the one that does the work – that a run of the program which starts inside the fragment either is still inside it or has left it through one of its exits.

Agreement on an interface #

def DescriptiveComplexity.HeadAgree {K : } (m : ) {A : Type} (x y : Fin KA) :

Two head assignments agree on the first m heads: the interface a fragment must preserve, the rest being scratch.

Equations
Instances For
    Dependency graph
    theorem DescriptiveComplexity.HeadAgree.refl {K m : } {A : Type} (x : Fin KA) :
    HeadAgree m x x
    Dependency graph
    theorem DescriptiveComplexity.HeadAgree.symm {K m : } {A : Type} {x y : Fin KA} (h : HeadAgree m x y) :
    HeadAgree m y x
    Dependency graph
    theorem DescriptiveComplexity.HeadAgree.trans {K m : } {A : Type} {x y z : Fin KA} (h : HeadAgree m x y) (h' : HeadAgree m y z) :
    HeadAgree m x z
    Dependency graph
    theorem DescriptiveComplexity.HeadAgree.mono {K m : } {A : Type} {x y : Fin KA} {m' : } (hm : m' m) (h : HeadAgree m x y) :
    HeadAgree m' x y

    Agreement on more heads is agreement on fewer.

    Dependency graph
    def DescriptiveComplexity.HeadLocal {K : } (m : ) {A : Type} (P : (Fin KA)Prop) :

    A property of the heads depends only on the first m of them.

    Equations
    Instances For
      Dependency graph
      def DescriptiveComplexity.HeadLocal2 {K : } (m : ) {A : Type} (R : (Fin KA)Bool(Fin KA)Prop) :

      A relation between two head assignments and an exit depends only on the first m heads of each.

      Equations
      Instances For
        Dependency graph
        theorem DescriptiveComplexity.HeadLocal.mono {K m m' : } {A : Type} {P : (Fin KA)Prop} (hm : m' m) (h : HeadLocal m' P) :

        Depending on fewer heads is depending on more.

        Dependency graph

        Guarded transitions #

        A guarded transition: a quantifier-free guard on the current head positions, a move for every head, and where to go – another state, or an exit.

        Instances For
          Dependency graph
          def DescriptiveComplexity.HeadTrans.retarget {L : FirstOrder.Language} {K : } {S S' : Type} (f : S BoolS' Bool) (t : HeadTrans L K S) :
          HeadTrans L K S'

          Rewiring a transition, for pasting a fragment into a larger program.

          Equations
          Instances For
            Dependency graph
            @[simp]
            theorem DescriptiveComplexity.HeadTrans.retarget_guard {L : FirstOrder.Language} {K : } {S S' : Type} (f : S BoolS' Bool) (t : HeadTrans L K S) :
            Dependency graph
            @[simp]
            theorem DescriptiveComplexity.HeadTrans.retarget_moves {L : FirstOrder.Language} {K : } {S S' : Type} (f : S BoolS' Bool) (t : HeadTrans L K S) :
            Dependency graph
            @[simp]
            theorem DescriptiveComplexity.HeadTrans.retarget_target {L : FirstOrder.Language} {K : } {S S' : Type} (f : S BoolS' Bool) (t : HeadTrans L K S) :
            Dependency graph

            Programs #

            A program: a two-way K-head automaton with its transitions presented one at a time, each with its own quantifier-free guard, and with two exits.

            Instances For
              Dependency graph
              @[reducible, inline]

              Where a run can be: at a state, or at one of the two exits.

              Equations
              Instances For
                Dependency graph
                @[reducible, inline]

                A configuration: a site together with the head positions.

                Equations
                Instances For
                  Dependency graph

                  One step: some transition of the current state whose guard holds, with each head moving as it prescribes.

                  Equations
                  Instances For
                    Dependency graph
                    @[reducible, inline]

                    Reachability: the reflexive-transitive closure of a step.

                    Equations
                    Instances For
                      Dependency graph
                      theorem DescriptiveComplexity.HeadProgram.not_step_exit {L : FirstOrder.Language} {K : } {F : HeadProgram L K} {A : Type} [L.Structure A] [LinearOrder A] {b : Bool} {y : Fin KA} {d : F.Conf A} :

                      Nothing happens at an exit: it has no transitions.

                      Dependency graph
                      theorem DescriptiveComplexity.HeadProgram.reach_exit {L : FirstOrder.Language} {K : } {F : HeadProgram L K} {A : Type} [L.Structure A] [LinearOrder A] {b : Bool} {y : Fin KA} {d : F.Conf A} (h : F.Reach (Sum.inr b, y) d) :

                      A run that has reached an exit stays there.

                      Dependency graph
                      theorem DescriptiveComplexity.HeadProgram.step_iff {L : FirstOrder.Language} {K : } {F : HeadProgram L K} {A : Type} [L.Structure A] [LinearOrder A] {s : F.St} {x : Fin KA} {d : F.Conf A} :
                      F.Step (Sum.inl s, x) d tF.tr s, t.guard.Realize x d.1 = t.target ∀ (j : Fin K), (t.moves j).Holds x j (d.2 j)

                      The step relation, at a state, spelled out.

                      Dependency graph
                      theorem DescriptiveComplexity.HeadProgram.step_of_mem {L : FirstOrder.Language} {K : } {F : HeadProgram L K} {A : Type} [L.Structure A] [LinearOrder A] {s : F.St} {x : Fin KA} {t : HeadTrans L K F.St} (ht : t F.tr s) (hg : t.guard.Realize x) {d : F.Conf A} (htar : d.1 = t.target) (hmv : ∀ (j : Fin K), (t.moves j).Holds x j (d.2 j)) :

                      Taking a named transition is a step.

                      Dependency graph

                      What a fragment does #

                      structure DescriptiveComplexity.HeadProgram.Runs {L : FirstOrder.Language} {K : } (F : HeadProgram L K) (A : Type) [L.Structure A] [LinearOrder A] (m : ) (R : (Fin KA)Bool(Fin KA)Prop) :

                      The specification of a fragment: R x b y describes the exits reachable from the entry at head positions x. Soundness is exact – every reachable exit is R-related – while completeness is up to the scratch heads, those from m on.

                      Instances For
                        Dependency graph
                        theorem DescriptiveComplexity.HeadProgram.Runs.weaken {L : FirstOrder.Language} {K : } {A : Type} [L.Structure A] [LinearOrder A] {F : HeadProgram L K} {m m' : } {R : (Fin KA)Bool(Fin KA)Prop} (h : F.Runs A m R) (hle : m' m) :
                        F.Runs A m' R

                        Leaving more heads dirty is allowed: a fragment protecting m heads protects any smaller interface.

                        Dependency graph
                        def DescriptiveComplexity.HeadProgram.Decides {L : FirstOrder.Language} {K : } (F : HeadProgram L K) (A : Type) [L.Structure A] [LinearOrder A] (m : ) (P : (Fin KA)Prop) :

                        A fragment that decides a property: it exits true exactly where the property holds, and gives the interface heads back unchanged.

                        Equations
                        Instances For
                          Dependency graph
                          theorem DescriptiveComplexity.HeadProgram.Decides.runs {L : FirstOrder.Language} {K : } {A : Type} [L.Structure A] [LinearOrder A] {F : HeadProgram L K} {m : } {P : (Fin KA)Prop} (h : F.Decides A m P) :
                          F.Runs A m fun (x : Fin KA) (b : Bool) (y : Fin KA) => (b = true P x) HeadAgree m x y
                          Dependency graph
                          theorem DescriptiveComplexity.HeadProgram.headLocal2_decides {K : } {A : Type} {m : } {P : (Fin KA)Prop} (hP : HeadLocal m P) :
                          HeadLocal2 m fun (x : Fin KA) (b : Bool) (y : Fin KA) => (b = true P x) HeadAgree m x y

                          The relation a decider runs is local when the property is.

                          Dependency graph

                          Fragments inside programs #

                          def DescriptiveComplexity.HeadProgram.esite {L : FirstOrder.Language} {K : } {F P : HeadProgram L K} (e : F.StP.St) (xt : BoolP.Site) :
                          F.SiteP.Site

                          Where a site of the fragment sits in the larger program.

                          Equations
                          Instances For
                            Dependency graph
                            def DescriptiveComplexity.HeadProgram.Embeds {L : FirstOrder.Language} {K : } (F P : HeadProgram L K) (e : F.StP.St) (xt : BoolP.Site) :

                            The fragment F sits inside P at e, its exits wired to xt: the transitions of P at an embedded state are exactly those of F, retargeted.

                            Equations
                            Instances For
                              Dependency graph
                              theorem DescriptiveComplexity.HeadProgram.Embeds.step {L : FirstOrder.Language} {K : } {A : Type} [L.Structure A] [LinearOrder A] {F P : HeadProgram L K} {e : F.StP.St} {xt : BoolP.Site} (h : F.Embeds P e xt) {c d : F.Conf A} (hcd : F.Step c d) :
                              P.Step (esite e xt c.1, c.2) (esite e xt d.1, d.2)

                              A step of the fragment is a step of the program.

                              Dependency graph
                              theorem DescriptiveComplexity.HeadProgram.Embeds.reach {L : FirstOrder.Language} {K : } {A : Type} [L.Structure A] [LinearOrder A] {F P : HeadProgram L K} {e : F.StP.St} {xt : BoolP.Site} (h : F.Embeds P e xt) {c d : F.Conf A} (hcd : F.Reach c d) :
                              P.Reach (esite e xt c.1, c.2) (esite e xt d.1, d.2)

                              A run of the fragment is a run of the program.

                              Dependency graph
                              theorem DescriptiveComplexity.HeadProgram.Embeds.reach_cases {L : FirstOrder.Language} {K : } {A : Type} [L.Structure A] [LinearOrder A] {F P : HeadProgram L K} {e : F.StP.St} {xt : BoolP.Site} (h : F.Embeds P e xt) {s : F.St} {u : Fin KA} {d : P.Conf A} (hd : P.Reach (Sum.inl (e s), u) d) :
                              (∃ (s' : F.St) (w : Fin KA), d = (Sum.inl (e s'), w) F.Reach (Sum.inl s, u) (Sum.inl s', w)) ∃ (b : Bool) (w : Fin KA), F.Reach (Sum.inl s, u) (Sum.inr b, w) P.Reach (xt b, w) d

                              The decomposition lemma: a run of the program that starts inside the fragment either is still inside it, or has left it through one of its exits – in which case the program's run splits at that exit.

                              Dependency graph
                              theorem DescriptiveComplexity.HeadProgram.Embeds.exit_cases {L : FirstOrder.Language} {K : } {A : Type} [L.Structure A] [LinearOrder A] {F P : HeadProgram L K} {e : F.StP.St} {xt : BoolP.Site} (h : F.Embeds P e xt) {s : F.St} {u : Fin KA} {b' : Bool} {y : Fin KA} (hd : P.Reach (Sum.inl (e s), u) (Sum.inr b', y)) :
                              ∃ (b : Bool) (w : Fin KA), F.Reach (Sum.inl s, u) (Sum.inr b, w) P.Reach (xt b, w) (Sum.inr b', y)

                              A run of the program from the fragment's entry to an exit of the program must leave the fragment through one of its own exits.

                              Dependency graph

                              Determinism #

                              A program is deterministic when the transitions available at a state never disagree: any two whose guards hold at the same head positions have the same target and the same moves.

                              Equations
                              • One or more equations did not get rendered due to their size.
                              Instances For
                                Dependency graph
                                theorem DescriptiveComplexity.HeadProgram.Deterministic.functional {L : FirstOrder.Language} {K : } {A : Type} [L.Structure A] [LinearOrder A] {F : HeadProgram L K} (h : F.Deterministic A) {c d d' : F.Conf A} (hd : F.Step c d) (hd' : F.Step c d') :
                                d = d'

                                A deterministic program has a functional step relation: at most one successor per configuration.

                                Dependency graph

                                The pieces: exiting, testing, moving #

                                Exit at once, with the given answer.

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

                                  Test a quantifier-free formula: exit true where it holds and false where it does not, without moving a head.

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

                                    Move the heads and exit true.

                                    Equations
                                    Instances For
                                      Dependency graph
                                      theorem DescriptiveComplexity.HeadProgram.Runs.mono {L : FirstOrder.Language} {K : } {A : Type} [L.Structure A] [LinearOrder A] {m : } {F : HeadProgram L K} {R R' : (Fin KA)Bool(Fin KA)Prop} (h : F.Runs A m R) (hsound : ∀ (x : Fin KA) (b : Bool) (y : Fin KA), R x b yR' x b y) (hcomplete : ∀ (x : Fin KA) (b : Bool) (y : Fin KA), R' x b y∃ (y' : Fin KA), HeadAgree m y y' R x b y') :
                                      F.Runs A m R'

                                      Weakening what a fragment is known to run: any relation implied by R and whose outcomes R already realizes up to the scratch heads.

                                      Dependency graph
                                      theorem DescriptiveComplexity.HeadProgram.reach_exit_flat {L : FirstOrder.Language} {K : } {A : Type} [L.Structure A] [LinearOrder A] {F : HeadProgram L K} (hflat : tF.tr F.entry, ∃ (b : Bool), t.target = Sum.inr b) {x : Fin KA} {b : Bool} {y : Fin KA} :
                                      F.Reach (Sum.inl F.entry, x) (Sum.inr b, y) tF.tr F.entry, t.guard.Realize x t.target = Sum.inr b ∀ (j : Fin K), (t.moves j).Holds x j (y j)

                                      A flat fragment – one whose every transition out of the entry goes straight to an exit – runs exactly one step.

                                      Dependency graph

                                      The transition tables of the pieces #

                                      @[simp]
                                      theorem DescriptiveComplexity.HeadProgram.tr_exitP {L : FirstOrder.Language} {K : } (b : Bool) (s : (exitP b).St) :
                                      (exitP b).tr s = [{ guard := , moves := fun (x : Fin K) => HeadMove.stay, target := Sum.inr b }]
                                      Dependency graph
                                      @[simp]
                                      theorem DescriptiveComplexity.HeadProgram.tr_leafP {L : FirstOrder.Language} {K : } (φ : (L.sum FirstOrder.Language.order).Formula (Fin K)) ( : FirstOrder.Language.BoundedFormula.IsQF φ) (s : (leafP φ ).St) :
                                      (leafP φ ).tr s = [{ guard := φ, moves := fun (x : Fin K) => HeadMove.stay, target := Sum.inr true }, { guard := FirstOrder.Language.BoundedFormula.not φ, moves := fun (x : Fin K) => HeadMove.stay, target := Sum.inr false }]
                                      Dependency graph
                                      @[simp]
                                      theorem DescriptiveComplexity.HeadProgram.tr_moveP {L : FirstOrder.Language} {K : } (mvs : Fin KHeadMove K) (s : (moveP mvs).St) :
                                      (moveP mvs).tr s = [{ guard := , moves := mvs, target := Sum.inr true }]
                                      Dependency graph
                                      theorem DescriptiveComplexity.HeadProgram.runs_exitP {L : FirstOrder.Language} {K : } {A : Type} [L.Structure A] [LinearOrder A] {m : } (b : Bool) :
                                      (exitP b).Runs A m fun (x : Fin KA) (b' : Bool) (y : Fin KA) => b' = b y = x
                                      Dependency graph
                                      Dependency graph
                                      theorem DescriptiveComplexity.HeadProgram.runs_moveP {L : FirstOrder.Language} {K : } {A : Type} [L.Structure A] [LinearOrder A] {m : } (mvs : Fin KHeadMove K) :
                                      (moveP mvs).Runs A m fun (x : Fin KA) (b : Bool) (y : Fin KA) => b = true ∀ (j : Fin K), (mvs j).Holds x j (y j)
                                      Dependency graph
                                      Dependency graph
                                      Dependency graph
                                      Dependency graph

                                      Wiring fragments into a control graph #

                                      def DescriptiveComplexity.HeadProgram.wireTo {L : FirstOrder.Language} {K : } {C : Type} (Fam : CHeadProgram L K) (w : CBoolC Bool) (c : C) (b : Bool) :
                                      (c : C) × (Fam c).St Bool

                                      Where a run goes when the fragment at control node c exits with b: to the entry of the fragment at the next control node, or out of the program.

                                      Equations
                                      Instances For
                                        Dependency graph
                                        def DescriptiveComplexity.HeadProgram.wireP {L : FirstOrder.Language} {K : } {C : Type} [Finite C] (Fam : CHeadProgram L K) (w : CBoolC Bool) (c₀ : C) :

                                        The control graph combinator: run the fragment at the current control node, and on its exit follow the wiring w – to another control node, or out. Sequencing, branching and looping are all instances.

                                        Equations
                                        • One or more equations did not get rendered due to their size.
                                        Instances For
                                          Dependency graph
                                          theorem DescriptiveComplexity.HeadProgram.embeds_wireP {L : FirstOrder.Language} {K : } {C : Type} [Finite C] (Fam : CHeadProgram L K) (w : CBoolC Bool) (c₀ c : C) :
                                          (Fam c).Embeds (wireP Fam w c₀) (fun (s : (Fam c).St) => c, s) (wireTo Fam w c)

                                          Each fragment sits in the assembled program at its own control node.

                                          Dependency graph
                                          def DescriptiveComplexity.HeadProgram.wireStep {K : } {C A : Type} (R : C(Fin KA)Bool(Fin KA)Prop) (w : CBoolC Bool) (u v : C × (Fin KA)) :

                                          One step of the control walk: the fragment at u.1 runs from u.2 to some exit, which the wiring sends on to the next control node.

                                          Equations
                                          Instances For
                                            Dependency graph
                                            def DescriptiveComplexity.HeadProgram.wireExit {K : } {C A : Type} (R : C(Fin KA)Bool(Fin KA)Prop) (w : CBoolC Bool) (u : C × (Fin KA)) (b' : Bool) (y : Fin KA) :

                                            How the control walk leaves the program.

                                            Equations
                                            Instances For
                                              Dependency graph
                                              theorem DescriptiveComplexity.HeadProgram.runs_wireP {L : FirstOrder.Language} {K : } {C : Type} [Finite C] (Fam : CHeadProgram L K) (w : CBoolC Bool) {A : Type} [L.Structure A] [LinearOrder A] {m : } {R : C(Fin KA)Bool(Fin KA)Prop} (hR : ∀ (c : C), (Fam c).Runs A m (R c)) (hloc : ∀ (c : C), HeadLocal2 m (R c)) (c₀ : C) :
                                              (wireP Fam w c₀).Runs A m fun (x : Fin KA) (b : Bool) (y : Fin KA) => ∃ (u : C × (Fin KA)), Relation.ReflTransGen (wireStep R w) (c₀, x) u wireExit R w u b y

                                              What an assembled program runs is the control walk: its exits are those reached by walking the control graph, each step being a run of the fragment sitting at that node. This is the lemma every later construction is proved with.

                                              Dependency graph
                                              theorem DescriptiveComplexity.HeadProgram.deterministic_wireP {L : FirstOrder.Language} {K : } {C : Type} [Finite C] (Fam : CHeadProgram L K) (w : CBoolC Bool) {A : Type} [L.Structure A] [LinearOrder A] (c₀ : C) (h : ∀ (c : C), (Fam c).Deterministic A) :
                                              (wireP Fam w c₀).Deterministic A

                                              An assembled program is deterministic as soon as its fragments are.

                                              Dependency graph

                                              Compiling a program into an automaton #

                                              @[reducible, inline]

                                              The tests a compiled program reads: the guard of each of its transitions.

                                              Equations
                                              Instances For
                                                Dependency graph

                                                The entry a transition contributes to the compiled transition table.

                                                Equations
                                                Instances For
                                                  Dependency graph

                                                  The transitions of a state that a reading enables, by index.

                                                  Equations
                                                  Instances For
                                                    Dependency graph

                                                    The compiled automaton. At pri := false every transition whose guard holds is enabled – the nondeterministic reading of a program. At pri := true only the first one is, so that the table has at most one entry per reading and DescriptiveComplexity.HeadAutomaton.IsDeterministic holds whatever the guards are.

                                                    Equations
                                                    • One or more equations did not get rendered due to their size.
                                                    Instances For
                                                      Dependency graph
                                                      @[simp]
                                                      theorem DescriptiveComplexity.HeadProgram.trans_compile_inl {L : FirstOrder.Language} {K : } (F : HeadProgram L K) (pri : Bool) (s : F.St) (r : F.TestOfBool) :
                                                      (F.compile pri).trans (Sum.inl s) r = List.map (fun (i : Fin (F.tr s).length) => F.entryOf s, i) (if pri = true then List.take 1 (F.enabled s r) else F.enabled s r)
                                                      Dependency graph
                                                      @[simp]
                                                      Dependency graph
                                                      theorem DescriptiveComplexity.HeadProgram.step_iff_index {L : FirstOrder.Language} {K : } (F : HeadProgram L K) {A : Type} [L.Structure A] [LinearOrder A] {s : F.St} {x : Fin KA} {d : F.Conf A} :
                                                      F.Step (Sum.inl s, x) d ∃ (i : Fin (F.tr s).length), ((F.tr s).get i).guard.Realize x d.1 = ((F.tr s).get i).target ∀ (j : Fin K), (((F.tr s).get i).moves j).Holds x j (d.2 j)

                                                      The step relation of a program, indexed by transitions rather than by membership: the form the compiled table has.

                                                      Dependency graph
                                                      theorem DescriptiveComplexity.HeadProgram.step_compile {L : FirstOrder.Language} {K : } (F : HeadProgram L K) {A : Type} [L.Structure A] [LinearOrder A] (pri : Bool) {s : F.St} {x : Fin KA} {d : F.Conf A} :
                                                      (F.compile pri).Step (Sum.inl s, x) d iif pri = true then List.take 1 (F.enabled s ((F.compile pri).reading x)) else F.enabled s ((F.compile pri).reading x), d.1 = ((F.tr s).get i).target ∀ (j : Fin K), (((F.tr s).get i).moves j).Holds x j (d.2 j)

                                                      The step relation of a compiled automaton, in terms of the enabled transitions of the program.

                                                      Dependency graph
                                                      theorem DescriptiveComplexity.HeadProgram.not_step_compile_exit {L : FirstOrder.Language} {K : } (F : HeadProgram L K) {A : Type} [L.Structure A] [LinearOrder A] (pri : Bool) {b : Bool} {x : Fin KA} {d : F.Conf A} :
                                                      ¬(F.compile pri).Step (Sum.inr b, x) d

                                                      Nothing steps out of an exit of a compiled automaton.

                                                      Dependency graph
                                                      theorem DescriptiveComplexity.HeadProgram.mem_enabled_iff {L : FirstOrder.Language} {K : } (F : HeadProgram L K) {A : Type} [L.Structure A] [LinearOrder A] (pri : Bool) (s : F.St) (x : Fin KA) (i : Fin (F.tr s).length) :
                                                      i F.enabled s ((F.compile pri).reading x) ((F.tr s).get i).guard.Realize x

                                                      An index is enabled exactly when its guard holds.

                                                      Dependency graph

                                                      The compiled automaton runs the program, in the nondeterministic reading.

                                                      Dependency graph

                                                      The deterministic compilation has at most one transition per reading.

                                                      Dependency graph
                                                      theorem DescriptiveComplexity.HeadProgram.step_compile_true {L : FirstOrder.Language} {K : } (F : HeadProgram L K) {A : Type} [L.Structure A] [LinearOrder A] (hdet : F.Deterministic A) (c d : F.Conf A) :
                                                      (F.compile true).Step c d F.Step c d

                                                      A deterministic program runs the same way under the deterministic compilation: taking the first enabled transition is taking the only one.

                                                      Dependency graph
                                                      theorem DescriptiveComplexity.HeadProgram.reach_compile {L : FirstOrder.Language} {K : } (F : HeadProgram L K) {A : Type} [L.Structure A] [LinearOrder A] (pri : Bool) (hstep : ∀ (c d : F.Conf A), (F.compile pri).Step c d F.Step c d) {c d : F.Conf A} :

                                                      A run of the program is a run of the compiled automaton, and back.

                                                      Dependency graph
                                                      theorem DescriptiveComplexity.HeadProgram.accepts_compile {L : FirstOrder.Language} {K : } (F : HeadProgram L K) {A : Type} [L.Structure A] [LinearOrder A] (pri : Bool) (hstep : ∀ (c d : F.Conf A), (F.compile pri).Step c d F.Step c d) :
                                                      (F.compile pri).Accepts A ∃ (x : Fin KA) (y : Fin KA), (∀ (j : Fin K) (a : A), x j a) F.Reach (Sum.inl F.entry, x) (Sum.inr true, y)

                                                      A compiled program is accepted exactly when its true exit is reachable from the entry with every head on the least element.

                                                      Dependency graph
                                                      theorem DescriptiveComplexity.HeadProgram.accepts_compile_false {L : FirstOrder.Language} {K : } (F : HeadProgram L K) {A : Type} [L.Structure A] [LinearOrder A] :
                                                      (F.compile false).Accepts A ∃ (x : Fin KA) (y : Fin KA), (∀ (j : Fin K) (a : A), x j a) F.Reach (Sum.inl F.entry, x) (Sum.inr true, y)

                                                      The nondeterministic compilation accepts exactly what the program reaches.

                                                      Dependency graph
                                                      theorem DescriptiveComplexity.HeadProgram.accepts_compile_true {L : FirstOrder.Language} {K : } (F : HeadProgram L K) {A : Type} [L.Structure A] [LinearOrder A] (hdet : F.Deterministic A) :
                                                      (F.compile true).Accepts A ∃ (x : Fin KA) (y : Fin KA), (∀ (j : Fin K) (a : A), x j a) F.Reach (Sum.inl F.entry, x) (Sum.inr true, y)

                                                      The deterministic compilation of a deterministic program accepts exactly what the program reaches.

                                                      Dependency graph