Documentation

Mathlib.Tactic.TFAE

The Following Are Equivalent (TFAE) #

This file provides the tactics tfae_have and tfae_finish for proving goals of the form TFAE [P₁, P₂, ...].

Parsing and syntax #

We implement tfae_have in terms of a syntactic have. To support as much of the same syntax as possible, we recreate the parsers for have, except with the changes necessary for tfae_have.

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

          A tfae_have type specification, e.g. 1 ↔ 3 The numbers refer to the proposition at the corresponding position in the TFAE goal (starting at 1).

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

            The following parsers are similar to those for have in Lean.Parser.Term, but instead of optType, we use tfaeType := num >> impArrow >> num (as a tfae_have invocation must always include this specification). Also, we disallow including extra binders, as that makes no sense in this context; we also include " : " after the binder to avoid breaking tfae_have 1 → 2 syntax (which, unlike have, omits " : ").

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

                        tfae_have i → j := t, where the goal is TFAE [P₁, P₂, ...] introduces a hypothesis tfae_i_to_j : Pᵢ → Pⱼ and proof t to the local context. Note that i and j are natural number literals (beginning at 1) used as indices to specify the propositions P₁, P₂, ... that appear in the goal.

                        Once sufficient hypotheses have been introduced by tfae_have, tfae_finish can be used to close the goal.

                        All features of have are supported by tfae_have, including naming, matching, destructuring, and goal creation.

                        • tfae_have i ← j := t adds a hypothesis in the reverse direction, of type Pⱼ → Pᵢ.
                        • tfae_have i ↔ j := t adds a hypothesis in the both directions, of type Pᵢ ↔ Pⱼ.
                        • tfae_have hij : i → j := t names the introduced hypothesis hij instead of tfae_i_to_j.
                        • tfae_have i j | p₁ => t₁ | ... matches on the assumption p : Pᵢ.
                        • tfae_have ⟨hij, hji⟩ : i ↔ j := t destructures the bi-implication into hij : Pᵢ → Pⱼ and hji : Pⱼ → Pⱼ.
                        • tfae_have i → j := t ?a creates a new goal for ?a.

                        Examples:

                        example (h : P → R) : TFAE [P, Q, R] := by
                          tfae_have 1 → 3 := h
                          -- The resulting context now includes `tfae_1_to_3 : P → R`.
                          sorry
                        
                        -- An example of `tfae_have` and `tfae_finish`:
                        example : TFAE [P, Q, R] := by
                          tfae_have 1 → 2 := sorry /- proof of P → Q -/
                          tfae_have 2 → 1 := sorry /- proof of Q → P -/
                          tfae_have 2 ↔ 3 := sorry /- proof of Q ↔ R -/
                          tfae_finish
                        
                        -- All features of `have` are supported by `tfae_have`:
                        example : TFAE [P, Q] := by
                          -- assert `tfae_1_to_2 : P → Q`:
                          tfae_have 1 → 2 := sorry
                        
                          -- assert `hpq : P → Q`:
                          tfae_have hpq : 1 → 2 := sorry
                        
                          -- match on `p : P` and prove `Q` via `f p`:
                          tfae_have 1 → 2
                          | p => f p
                        
                          -- assert `pq : P → Q`, `qp : Q → P`:
                          tfae_have ⟨pq, qp⟩ : 1 ↔ 2 := sorry
                        
                          -- assert `h : P → Q`; `?a` is a new goal:
                          tfae_have h : 1 → 2 := f ?a
                        
                          sorry
                        
                        Equations
                        • One or more equations did not get rendered due to their size.
                        Instances For

                          tfae_finish closes goals of the form TFAE [P₁, P₂, ...] once a sufficient collection of hypotheses of the form Pᵢ → Pⱼ or Pᵢ ↔ Pⱼ have been introduced to the local context.

                          tfae_have can be used to conveniently introduce these hypotheses; see tfae_have.

                          Example:

                          example : TFAE [P, Q, R] := by
                            tfae_have 1 → 2 := sorry /- proof of P → Q -/
                            tfae_have 2 → 1 := sorry /- proof of Q → P -/
                            tfae_have 2 ↔ 3 := sorry /- proof of Q ↔ R -/
                            tfae_finish
                          
                          Equations
                          Instances For

                            Setup #

                            Extract a list of Prop expressions from an expression of the form TFAE [P₁, P₂, ...] as long as [P₁, P₂, ...] is an explicit list.

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

                              Proof construction #

                              partial def Mathlib.Tactic.TFAE.dfs (hyps : Array ( × × Lean.Expr)) (atoms : Array Q(Prop)) (i j : ) (P P' : Q(Prop)) (hP : Q(«$P»)) :

                              Uses depth-first search to find a path from P to P'.

                              def Mathlib.Tactic.TFAE.proveImpl (hyps : Array ( × × Lean.Expr)) (atoms : Array Q(Prop)) (i j : ) (P P' : Q(Prop)) :
                              Lean.MetaM Q(«$P»«$P'»)

                              Prove an implication via depth-first traversal.

                              Equations
                              • One or more equations did not get rendered due to their size.
                              Instances For
                                partial def Mathlib.Tactic.TFAE.proveChain (hyps : Array ( × × Lean.Expr)) (atoms : Array Q(Prop)) (i : ) (is : List ) (P : Q(Prop)) (l : Q(List Prop)) :
                                Lean.MetaM Q(List.IsChain (fun (x1 x2 : Prop) => x1x2) («$P» :: «$l»))

                                Generate a proof of Chain (· → ·) P l. We assume P : Prop and l : List Prop, and that l is an explicit list.

                                partial def Mathlib.Tactic.TFAE.proveGetLastDImpl (hyps : Array ( × × Lean.Expr)) (atoms : Array Q(Prop)) (i i' : ) (is : List ) (P P' : Q(Prop)) (l : Q(List Prop)) :
                                Lean.MetaM Q(«$l».getLastD «$P'»«$P»)

                                Attempt to prove getLastD l P' → P given an explicit list l.

                                def Mathlib.Tactic.TFAE.proveTFAE (hyps : Array ( × × Lean.Expr)) (atoms : Array Q(Prop)) (is : List ) (l : Q(List Prop)) :
                                Lean.MetaM Q(«$l».TFAE)

                                Attempt to prove a statement of the form TFAE [P₁, P₂, ...].

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

                                  tfae_have components #

                                  def Mathlib.Tactic.TFAE.mkTFAEId :
                                  Lean.TSyntax `Mathlib.Tactic.TFAE.Parser.tfaeTypeLean.MacroM Lean.Name

                                  Construct a name for a hypothesis introduced by tfae_have.

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

                                    Turn syntax for a given index into a natural number, as long as it lies between 1 and maxIndex.

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

                                      Tactic implementation #

                                      def Mathlib.Tactic.TFAE.elabTFAEType (tfaeList : List Q(Prop)) :
                                      Lean.TSyntax `Mathlib.Tactic.TFAE.Parser.tfaeTypeLean.Elab.TermElabM Lean.Expr

                                      Accesses the propositions at indices i and j of tfaeList, and constructs the expression Pi <arr> Pj, which will be the type of our tfae_have hypothesis

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

                                        Deprecated "Goal-style" tfae_have #

                                        This syntax and its implementation, which behaves like "Mathlib have" is deprecated; we preserve it here to provide graceful deprecation behavior.

                                        Re-enables "goal-style" syntax for tfae_have when true.

                                        tfae_have i → j := t, where the goal is TFAE [P₁, P₂, ...] introduces a hypothesis tfae_i_to_j : Pᵢ → Pⱼ and proof t to the local context. Note that i and j are natural number literals (beginning at 1) used as indices to specify the propositions P₁, P₂, ... that appear in the goal.

                                        Once sufficient hypotheses have been introduced by tfae_have, tfae_finish can be used to close the goal.

                                        All features of have are supported by tfae_have, including naming, matching, destructuring, and goal creation.

                                        • tfae_have i ← j := t adds a hypothesis in the reverse direction, of type Pⱼ → Pᵢ.
                                        • tfae_have i ↔ j := t adds a hypothesis in the both directions, of type Pᵢ ↔ Pⱼ.
                                        • tfae_have hij : i → j := t names the introduced hypothesis hij instead of tfae_i_to_j.
                                        • tfae_have i j | p₁ => t₁ | ... matches on the assumption p : Pᵢ.
                                        • tfae_have ⟨hij, hji⟩ : i ↔ j := t destructures the bi-implication into hij : Pᵢ → Pⱼ and hji : Pⱼ → Pⱼ.
                                        • tfae_have i → j := t ?a creates a new goal for ?a.

                                        Examples:

                                        example (h : P → R) : TFAE [P, Q, R] := by
                                          tfae_have 1 → 3 := h
                                          -- The resulting context now includes `tfae_1_to_3 : P → R`.
                                          sorry
                                        
                                        -- An example of `tfae_have` and `tfae_finish`:
                                        example : TFAE [P, Q, R] := by
                                          tfae_have 1 → 2 := sorry /- proof of P → Q -/
                                          tfae_have 2 → 1 := sorry /- proof of Q → P -/
                                          tfae_have 2 ↔ 3 := sorry /- proof of Q ↔ R -/
                                          tfae_finish
                                        
                                        -- All features of `have` are supported by `tfae_have`:
                                        example : TFAE [P, Q] := by
                                          -- assert `tfae_1_to_2 : P → Q`:
                                          tfae_have 1 → 2 := sorry
                                        
                                          -- assert `hpq : P → Q`:
                                          tfae_have hpq : 1 → 2 := sorry
                                        
                                          -- match on `p : P` and prove `Q` via `f p`:
                                          tfae_have 1 → 2
                                          | p => f p
                                        
                                          -- assert `pq : P → Q`, `qp : Q → P`:
                                          tfae_have ⟨pq, qp⟩ : 1 ↔ 2 := sorry
                                        
                                          -- assert `h : P → Q`; `?a` is a new goal:
                                          tfae_have h : 1 → 2 := f ?a
                                        
                                          sorry
                                        
                                        Equations
                                        • One or more equations did not get rendered due to their size.
                                        Instances For