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.

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 " : ").

tfae_have introduces hypotheses for proving goals of the form TFAE [P₁, P₂, ...]. Specifically, tfae_have i <arrow> j := ... introduces a hypothesis of type Pᵢ <arrow> Pⱼ to the local context, where <arrow> can be , , or . Note that i and j are natural number indices (beginning at 1) used to specify the propositions P₁, P₂, ... that appear in the goal.

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.

Once sufficient hypotheses have been introduced by tfae_have, tfae_finish can be used to close the goal. For 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

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

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
  ...
Equations
    Instances For

      tfae_finish is used to close 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
            Instances For

              Convert an expression representing an explicit list into a list of expressions.

              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
                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.Chain (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
                    Instances For

                      tfae_have components #

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

                      Construct a name for a hypothesis introduced by tfae_have.

                      Equations
                        Instances For

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

                          Equations
                            Instances For

                              Tactic implementation #

                              def Mathlib.Tactic.TFAE.elabTFAEType (tfaeList : List Q(Prop)) :
                              Lean.TSyntax `_private.Mathlib.Tactic.TFAE.0.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
                                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.

                                  "Goal-style" tfae_have syntax is deprecated. Now, tfae_have ... should be followedby := ...; see below for the new behavior. This warning can be turned off with set_option Mathlib.Tactic.TFAE.useDeprecated true.


                                  tfae_have introduces hypotheses for proving goals of the form TFAE [P₁, P₂, ...]. Specifically, tfae_have i <arrow> j := ... introduces a hypothesis of type Pᵢ <arrow> Pⱼ to the local context, where <arrow> can be , , or . Note that i and j are natural number indices (beginning at 1) used to specify the propositions P₁, P₂, ... that appear in the goal.

                                  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.

                                  Once sufficient hypotheses have been introduced by tfae_have, tfae_finish can be used to close the goal. For 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
                                  

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

                                  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
                                    ...
                                  
                                  Equations
                                    Instances For