Documentation

Pdl.TableauGame

The Tableau Game (Section 6.2) #

Prover and Builder positions #

Equations
Instances For
    Equations
    Instances For
      inductive ProverPos (H : History) (X : Sequent) :

      Prover should make a move.

      Instances For
        inductive BuilderPos (H : History) (X : Sequent) :

        Builder should make a move.

        Instances For
          def instDecidableEqBuilderPos.decEq {H✝ : History} {X✝ : Sequent} (x✝ x✝¹ : BuilderPos H✝ X✝) :
          Decidable (x✝ = x✝¹)
          Equations
          Instances For

            Game position where either Prover (isLeft) or Builder (isRight) should make a move.

            Equations
            Instances For
              def posOf (H : History) (X : Sequent) :

              If we reach this sequent, what is the next game position? Includes winning positions.

              Equations
              • One or more equations did not get rendered due to their size.
              Instances For
                theorem posOf_eq_inr_then_lpr {H : History} {X : Sequent} {p : BuilderPos H X} :
                posOf H X = Sum.inr p∃ (lpr : LoadedPathRepeat H X), p = BuilderPos.lpr lpr

                Moves #

                inductive Move (old new : GamePos) :

                The relation Move old next says that we can move from old to next. There are three kinds of moves.

                Instances For
                  def Move.isModal {pos newPos : GamePos} :
                  Move pos newPosProp
                  Equations
                  Instances For
                    def move (old new : GamePos) :
                    Equations
                    Instances For
                      theorem move_then_no_frep {H : History} {X : Sequent} {next : GamePos} {p : ProverPos H X BuilderPos H X} :
                      move H, X, p next¬(rep H X X.isFree = true)

                      The finite set of moves, given as a function instead of a relation. With move_of_mem_theMoves and mem_theMoves_of_move this agrees with move.

                      Equations
                      Instances For
                        theorem theMoves_iff {H : History} {X : Sequent} {p : ProverPos H X BuilderPos H X} {next : GamePos} :
                        next theMoves H, X, p (∃ (nrep : ¬flprep H X) (Xbasic : X.basic), p = Sum.inl (ProverPos.bas nrep Xbasic) ∃ (L : List Formula) (R : List Formula), X = (L, R, none) ((∃ (δs : List Program) (δ : Program) (ψ : Formula), ¬ψ.isBox (~⌈⌈δs⌉⌉δψ) L next = X :: H, (L.erase (~⌈⌈δs⌉⌉δψ), R, some (Sum.inl (~'⌊⌊δs⌋⌋δAnyFormula.normal ψ))), posOf (X :: H) (L.erase (~⌈⌈δs⌉⌉δψ), R, some (Sum.inl (~'⌊⌊δs⌋⌋δAnyFormula.normal ψ)))) ∃ (δs : List Program) (δ : Program) (ψ : Formula), ¬ψ.isBox (~⌈⌈δs⌉⌉δψ) R next = X :: H, (L, R.erase (~⌈⌈δs⌉⌉δψ), some (Sum.inr (~'⌊⌊δs⌋⌋δAnyFormula.normal ψ))), posOf (X :: H) (L, R.erase (~⌈⌈δs⌉⌉δψ), some (Sum.inr (~'⌊⌊δs⌋⌋δAnyFormula.normal ψ)))) (∃ (a : ) (ξ : AnyFormula), X = (L, R, some (Sum.inl (~'·aξ))) ((∃ (φ : Formula), ξ = AnyFormula.normal φ next = X :: H, (~φ :: projection a L, projection a R, none), posOf (X :: H) (~φ :: projection a L, projection a R, none)) (∃ (χ : LoadFormula), ξ = AnyFormula.loaded χ next = X :: H, (projection a L, projection a R, some (Sum.inl (~'χ))), posOf (X :: H) (projection a L, projection a R, some (Sum.inl (~'χ)))) next = X :: H, (List.insert (~(·aξ).unload) L, R, none), posOf (X :: H) (List.insert (~(·aξ).unload) L, R, none))) ∃ (a : ) (ξ : AnyFormula), X = (L, R, some (Sum.inr (~'·aξ))) ((∃ (φ : Formula), ξ = AnyFormula.normal φ next = X :: H, (projection a L, ~φ :: projection a R, none), posOf (X :: H) (projection a L, ~φ :: projection a R, none)) (∃ (χ : LoadFormula), ξ = AnyFormula.loaded χ next = X :: H, (projection a L, projection a R, some (Sum.inr (~'χ))), posOf (X :: H) (projection a L, projection a R, some (Sum.inr (~'χ)))) next = X :: H, (L, List.insert (~(·aξ).unload) R, none), posOf (X :: H) (L, List.insert (~(·aξ).unload) R, none))) (∃ (nrep : ¬flprep H X) (nbas : ¬X.basic), p = Sum.inl (ProverPos.nbas nrep nbas) ∃ (ltab : LocalTableau X), next = H, X, Sum.inr (BuilderPos.ltab nrep nbas ltab)) ∃ (nrep : ¬flprep H X) (nbas : ¬X.basic) (ltab : LocalTableau X), p = Sum.inr (BuilderPos.ltab nrep nbas ltab) YendNodesOf ltab, next = X :: H, Y, posOf (X :: H) Y

                        Characterization of theMoves.

                        theorem no_moves_of_rep {H : History} {X : Sequent} {pos : ProverPos H X BuilderPos H X} (h : rep H X X.isFree = true) :
                        theorem move_of_mem_theMoves {pos next : GamePos} :
                        next theMoves posmove pos next

                        The finite set given by theMoves indeed agrees with the relation move. Other direction is mem_theMoves_of_move.

                        theorem mem_theMoves_of_move {pos next : GamePos} :
                        move pos nextnext theMoves pos
                        theorem move.hist {Hist : History} {X : Sequent} {pos : ProverPos Hist X BuilderPos Hist X} {next : GamePos} (mov : move Hist, X, pos next) :
                        (∃ (newPos : ProverPos Hist X BuilderPos Hist X), next = Hist, X, newPos) ∃ (Y : Sequent) (newPos : ProverPos (X :: Hist) Y BuilderPos (X :: Hist) Y), next = X :: Hist, Y, newPos
                        theorem move.hist_suffix {Hist : History} {X : Sequent} {pos : ProverPos Hist X BuilderPos Hist X} {next : GamePos} (mov : move Hist, X, pos next) :
                        Hist <:+ next.fst
                        theorem move.trans_hist_suffix {pX pZ : GamePos} (movt : Relation.TransGen move pX pZ) :
                        pX.fst <:+ pZ.fst
                        theorem move.trans_hist {pX pY : GamePos} (movt : Relation.TransGen move pX pY) :
                        pX.fst = pY.fst pX.snd.fst = pY.snd.fst pX.snd.fst :: pX.fst <:+ pY.fst

                        Along the transitive closure of move either the history stays the same or the old sequent and history form a prefix of the new history (where "prefix" is actually "suffix" because the history has the newest element first).

                        Lemmas about double moves #

                        theorem move_twice_hist_length {A B C : GamePos} (A_B : move A B) (B_C : move B C) :

                        After two moves the history must grow.

                        @[reducible, inline]
                        abbrev movemove (a c : GamePos) :

                        Insert obligatory "We like to move it move it" joke here.

                        Equations
                        Instances For
                          theorem movemove.hist {A B C : GamePos} (A_B : move A B) (B_C : move B C) :

                          After any number of double moves the history gets extended.

                          Termination via finite FL closure #

                          See also StayingInFL.lean whereSequent.subseteq_FL is defined.

                          We are working with lists (or, by ignoring their order, multisets) and thus staying in the FL closure does not imply that there are only finitely many sequents reachable: by repeating the same formulas the length of the list may increase. To tackle this we want to use that rep is defined with setEqTo that ignores multiplicity, so that even if there are infinitely many different lists and thus sequents in principle reachable, we still cannot have an infinite chain because that would mean we must have a "set-repeat" that is not allowed.

                          theorem move_inside_FL {p next : GamePos} (mov : move p next) :

                          Given ~⌈α₁⌉…⌈αₙ⌉φ, return the list of ~⌊α₁⌋…⌊αₖ⌋⌈αₖ₊₁⌉…⌈αₙ⌉φ for all k.

                          Equations
                          • One or more equations did not get rendered due to their size.
                          • x✝.allNegLoads = []
                          Instances For

                            A list of sequents that are all FL-subsequents of the given sequent. The list defined here is not complete because there are infinitely many such other sequents. But the list is exhaustive modulo setEqTo, as will be shown later via the Seqt quotient. Defined using List.instMonad.

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

                              NOTE

                              The following do NOT hold / do NOT exist because there are in fact infinitely many FL-subsequents of a given sequent, so the list returned by all_subseteq_FL can never contain all.

                              def Sequent.all_subseteq_FL_complete (X Y : Sequent) (h : Y.subseteq_FL X) :
                                  ⟨Y,h⟩ ∈ Sequent.all_subseteq_FL X := ...
                              
                              instance Sequent.subseteq_FL_fintype {X : Sequent} :
                                  Fintype { Y // Sequent.subseteq_FL Y X } := ...
                              

                              Hence, we now use the Seqt (which is the quotient from Sequent.setEqTo) within which there are only finitely many FL-subsequents.

                              In the quotient the moves keep us inside the FL. Unused but nice to have.

                              theorem exists_mem_sublists_toFinsetEq_of_Subset {α : Type u_1} [DecidableEq α] {A B : List α} :
                              A BCB.sublists, C.toFinset = A.toFinset

                              Small helper function. Mathlib this?

                              theorem Seqt.all_subseteq_FL_spec {Xs Ys : Seqt} (Ys_in : Ys Xs.all_subseteq_FL) :
                              Equations
                              • One or more equations did not get rendered due to their size.
                              Instances For
                                Equations
                                • =
                                Instances For

                                  In the quotient for setEqTo there are only finitely many FL-subsets for a given Seqt. This means "there are only finitely many "sequents modulo setEq" that are subseteq_FL Y.

                                  theorem exist_duplicates_of_infinite_among_fintype {α : Type} {f : α} {p : αProp} (h_p : ∀ (n : ), p (f n)) (h_fin : Finite { x : α // p x }) :
                                  ∃ (k1 : ) (k2 : ), k1 k2 f k1 = f k2

                                  Helper lemma for matchesFinite: If we have enumerate infinitely many values, and all of them have a certain property, but we also know that there are only finitely many values with that property, then there must be identical values in the enumeration.

                                  Infinite chains of moves #

                                  Towards matchesFinite we here collect facts about an infinite chain g : ℕ → GamePos with move (g n) (g (n+1)) for all n, following the proof idea for the matchesFinite lemma:

                                  This section is from aristotle.harmonic.fun

                                  theorem move_then_not_flprep {H : History} {X : Sequent} {next : GamePos} {p : ProverPos H X BuilderPos H X} :
                                  move H, X, p next¬flprep H X

                                  If a move from ⟨H, X, p⟩ is possible, then X is neither a free repeat nor a loaded-path repeat in H. Note this is stronger than move_then_no_frep.

                                  theorem exists_spread_subsequence {P : Prop} (hS : ∀ (N : ), ∃ (n : ), N n P n) :
                                  ∃ (e : ), (∀ (k : ), P (e k)) ∀ (k1 k2 : ), k1 < k2e k1 + 2 e k2

                                  Helper lemma for matchesFinite: if a property of natural numbers holds arbitrarily late, then we can enumerate witnesses for it with gaps of at least two.

                                  theorem moveChain_not_flprep {g : GamePos} (g_rel : ∀ (n : ), move (g n) (g (n + 1))) (n : ) :
                                  ¬flprep (g n).fst (g n).snd.fst

                                  Because a move is possible, no position in the chain is a forbidden repeat.

                                  theorem moveChain_hist_step {g : GamePos} (g_rel : ∀ (n : ), move (g n) (g (n + 1))) (n : ) :
                                  (g (n + 1)).fst = (g n).fst (g (n + 1)).snd.fst = (g n).snd.fst (g (n + 1)).fst = (g n).snd.fst :: (g n).fst

                                  One step in the chain either keeps history and sequent (the prLocTab case) or adds the current sequent to the history.

                                  theorem moveChain_hist_accum {g : GamePos} (g_rel : ∀ (n : ), move (g n) (g (n + 1))) (m n : ) :
                                  m n∃ (pre : List Sequent), (g n).fst = pre ++ (g m).fst Ypre, ∃ (j : ), m j j < n Y = (g j).snd.fst

                                  The history only grows, and everything added to it are sequents from the chain.

                                  theorem moveChain_hist_split {g : GamePos} (g_rel : ∀ (n : ), move (g n) (g (n + 1))) {m n : } (h : m + 2 n) :
                                  ∃ (pre : List Sequent), (g n).fst = pre ++ (g m).snd.fst :: (g m).fst Ypre, ∃ (j : ), m < j j < n Y = (g j).snd.fst

                                  After at least two moves the sequent of the earlier position is in the later history, and all newer entries of that history are sequents from strictly in between.

                                  theorem moveChain_inside_FL {g : GamePos} (g_rel : ∀ (n : ), move (g n) (g (n + 1))) (n : ) :

                                  All sequents in the chain stay inside the FL closure of the first sequent.

                                  theorem moveChain_setEq_isLoaded {g : GamePos} (g_rel : ∀ (n : ), move (g n) (g (n + 1))) {m n : } (h : m + 2 n) (hs : (g m).snd.fst.setEqTo (g n).snd.fst) :

                                  A sequent in the chain that is setEqTo an earlier one must be loaded, because otherwise we would have a free repeat and the match would have ended.

                                  theorem moveChain_exists_setEq_late {g : GamePos} (g_rel : ∀ (n : ), move (g n) (g (n + 1))) (N : ) :
                                  ∃ (m : ) (n : ), N m m + 2 n (g m).snd.fst.setEqTo (g n).snd.fst

                                  Because there are only finitely many sequents modulo setEqTo inside the FL closure, arbitrarily late in the chain we find two positions with setEqTo sequents.

                                  theorem moveChain_eventually_loaded {g : GamePos} (g_rel : ∀ (n : ), move (g n) (g (n + 1))) :
                                  ∃ (N : ), ∀ (n : ), N n(g n).snd.fst.isLoaded = true

                                  From some point onwards all sequents in the chain are loaded: there are only finitely many sequents modulo setEqTo, and free ones can never come back.

                                  theorem moveChain_hist_index {g : GamePos} (g_rel : ∀ (n : ), move (g n) (g (n + 1))) {N m n : } (hN : ∀ (j : ), N j(g j).snd.fst.isLoaded = true) (hm : N m) (h : m + 2 n) :
                                  ∃ (k : Fin (List.length (g n).fst)), List.get (g n).fst k = (g m).snd.fst ik, (List.get (g n).fst i).isLoaded = true

                                  If all sequents from N onwards are loaded and N ≤ m with m + 2 ≤ n, then the sequent of position m occurs in the history of position n at an index such that all entries up to and including that index are loaded. This is what is needed for a loaded-path repeat.

                                  theorem moveChain_setEq_absurd {g : GamePos} (g_rel : ∀ (n : ), move (g n) (g (n + 1))) {N m n : } (hN : ∀ (j : ), N j(g j).snd.fst.isLoaded = true) (hm : N m) (h : m + 2 n) (hs : (g m).snd.fst.setEqTo (g n).snd.fst) :

                                  A setEqTo repeat in the loaded part of the chain is impossible: it would be a loaded-path repeat, at which the match ends.

                                  Lemma 6.11. The move relation is converse wellfounded (and thus all matches must be finite). This is similar to the proof that PDL-tableaux are finite (Lemma 4.10), relying on the finiteness of the Fischer-Ladner closure. In Lean we never needed to say 4.10 because values of the inductive type Tableau are always finite by constriction. But we do need a proof here, as this lemma is about move, not Match.

                                  The whole argument is done in the MoveChain section above.

                                  Actual Game Definition #

                                  The game defined in Section 6.2.

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

                                    This helps to pick up the derived instance DecidableEq GamePos above.

                                    Equations
                                    @[simp]
                                    theorem tableauGame_turn_Prover {Hist : History} {X : Sequent} {lpr : ProverPos Hist X} :
                                    @[simp]
                                    theorem tableauGame_turn_Builder {Hist : History} {X : Sequent} {lpr : BuilderPos Hist X} :

                                    From Prover winning strategies to tableau #

                                    @[irreducible]
                                    theorem gameP_general (Hist : History) (X : Sequent) (sP : Strategy tableauGame Prover) (pos : ProverPos Hist X BuilderPos Hist X) (h : winning sP Hist, X, pos) :
                                    Nonempty (Tableau Hist X)

                                    After history Hist, if Prover has a winning strategy then there is a closed tableau. Note: we skip Definition 6.9 (Strategy Tree for Prover) and just use the Strategy type. This is the induction loading for gameP.

                                    The starting position for the given sequent. With an empty history and using posOf to determine the first GamePos.

                                    Equations
                                    Instances For
                                      theorem posOf_for_startPos (X : Sequent) :
                                      ∃ (proPos : ProverPos [] X), posOf [] X = Sum.inl proPos

                                      We start with a prover position, because when the history is empty we can't have any repeat.

                                      theorem gameP (X : Sequent) (s : Strategy tableauGame Prover) (h : winning s (startPos X)) :

                                      If Prover has a winning strategy then there is a closed tableau.