Documentation

Mathlib.Tactic.Push

The push, push_neg and pull tactics #

The push tactic pushes a given constant inside expressions: it can be applied to goals as well as local hypotheses and also works as a conv tactic. push_neg is a macro for push Not.

The pull tactic does the reverse: it pulls the given constant towards the head of the expression.

theorem Mathlib.Tactic.Push.not_exists {α : Sort u_1} (s : αProp) :
¬Exists s ∀ (x : α), binderNameHint x s ¬s x
theorem Mathlib.Tactic.Push.not_and_eq (p q : Prop) :
(¬(p q)) = (p¬q)
theorem Mathlib.Tactic.Push.not_forall_eq {α : Sort u_1} (s : αProp) :
(¬∀ (x : α), s x) = (x : α), ¬s x

The configuration options for the push tactic.

  • distrib : Bool

    If true (default false), rewrite ¬ (p ∧ q) into ¬ p ∨ ¬ q instead of p → ¬ q.

Instances For

    Function elaborating Push.Config.

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

      The simp configuration used in push.

      Equations
      Instances For

        Try to rewrite using a push lemma.

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

          Common entry point to the implementation of push.

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

            Try to rewrite using a pull lemma.

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

              Common entry point to the implementation of pull.

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

                Return true if stx is an underscore, i.e. _ or fun $_ => _/fun $_ ↦ _.

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

                  resolvePushId? is a version of resolveId? that also supports notations like _ ∈ _, ∃ x, _ and ∑ x, _.

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

                    Elaborator for the argument passed to push. It accepts a constant, or a function

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

                      Elaborate the (disch := ...) syntax for a simp-like tactic.

                      Equations
                      Instances For

                        Run the push tactic.

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

                          push c rewrites the goal by pushing the constant c deeper into an expression. For instance, push _ ∈ _ rewrites x ∈ {y} ∪ zᶜ into x = y ∨ ¬ x ∈ z. More precisely, the push tactic repeatedly rewrites an expression by applying lemmas of the form c ... = ... (c ...) (where c can appear 0 or more times on the right hand side). To extend the push tactic, you can tag a lemma of this form with the @[push] attribute.

                          To instead move a constant closer to the head of the expression, use the pull tactic.

                          push works as both a tactic and a conv tactic.

                          • push _ ~ _ pushes the (binary) operator ~, push ~ _ pushes the (unary) operator ~.
                          • push c at l1 l2 ... rewrites at the given locations.
                          • push c at * rewrites at all hypotheses and the goal.
                          • push (disch := tac) c uses the tactic tac to discharge any hypotheses for @[push] lemmas.

                          Examples:

                          • push _ ∈ _ rewrites x ∈ {y} ∪ zᶜ into x = y ∨ ¬ x ∈ z.
                          • push (disch := positivity) Real.log rewrites log (a * b ^ 2) into log a + 2 * log b.
                          • push ¬ _ is the same as push_neg or push Not, and it rewrites ¬ ∀ ε > 0, ∃ δ > 0, δ < ε into ∃ ε > 0, ∀ δ > 0, ε ≤ δ.
                          • push fun _ ↦ _ rewrites fun x => f x ^ 2 + 5 into f ^ 2 + 5
                          • push ∀ _, _ rewrites ∀ a, p a ∧ q a into (∀ a, p a) ∧ (∀ a, q a).
                          Equations
                          • One or more equations did not get rendered due to their size.
                          Instances For

                            push_neg rewrites the goal by pushing negations deeper into an expression. For instance, the goal ¬ ∀ x, ∃ y, x ≤ y will be transformed by push_neg into ∃ x, ∀ y, y < x. Binder names are preserved (contrary to what would happen with simp using the relevant lemmas). push_neg works as both a tactic and a conv tactic.

                            push_neg is a special case of the more general push tactic, namely push Not. The push tactic can be extended using the @[push] attribute. push has special-casing built in for push Not.

                            Tactics that introduce a negation usually have a version that automatically calls push_neg on that negation. These include by_cases!, contrapose! and by_contra!.

                            • push_neg at l1 l2 ... rewrites at the given locations.
                            • push_neg at * rewrites at each hypothesis and the goal.
                            • push_neg +distrib rewrites ¬ (p ∧ q) into ¬ p ∨ ¬ q (by default, the tactic rewrites it into p → ¬ q instead).

                            Example:

                            example (h : ¬ ∀ ε > 0, ∃ δ > 0, ∀ x, |x - x₀| ≤ δ → |f x - y₀| ≤ ε) :
                                ∃ ε > 0, ∀ δ > 0, ∃ x, |x - x₀| ≤ δ ∧ ε < |f x - y₀| := by
                              push_neg at h
                              -- Now we have the hypothesis `h : ∃ ε > 0, ∀ δ > 0, ∃ x, |x - x₀| ≤ δ ∧ ε < |f x - y₀|`
                              exact h
                            
                            Equations
                            • One or more equations did not get rendered due to their size.
                            Instances For

                              pull c rewrites the goal by pulling the constant c closer to the head of the expression. For instance, pull _ ∈ _ rewrites x ∈ y ∨ ¬ x ∈ z into x ∈ y ∪ zᶜ. More precisely, the pull tactic repeatedly rewrites an expression by applying lemmas of the form ... (c ...) = c ... (where c can appear 1 or more times on the left hand side). pull is the inverse tactic to push. To extend the pull tactic, you can tag a lemma with the @[push] attribute. pull works as both a tactic and a conv tactic.

                              A lemma is considered a pull lemma if its reverse direction is a push lemma that actually moves the given constant away from the head. For example

                              • not_or : ¬ (p ∨ q) ↔ ¬ p ∧ ¬ q is a pull lemma, but not_not : ¬ ¬ p ↔ p is not.
                              • log_mul : log (x * y) = log x + log y is a pull lemma, but log_abs : log |x| = log x is not.
                              • Pi.mul_def : f * g = fun (i : ι) => f i * g i and Pi.one_def : 1 = fun (x : ι) => 1 are both pull lemmas for fun, because every push fun _ ↦ _ lemma is also considered a pull lemma.

                              TODO: define a @[pull] attribute for tagging pull lemmas that are not push lemmas.

                              • pull _ ~ _ pulls the operator or relation ~.
                              • pull c at l1 l2 ... rewrites at the given locations.
                              • pull c at * rewrites at all hypotheses and the goal.
                              • pull (disch := tac) c uses the tactic tac to discharge any hypotheses for @[push] lemmas.

                              Examples:

                              • pull _ ∈ _ rewrites x ∈ y ∨ ¬ x ∈ z into x ∈ y ∪ zᶜ.
                              • pull (disch := positivity) Real.log rewrites log a + 2 * log b into log (a * b ^ 2).
                              • pull fun _ ↦ _ rewrites f ^ 2 + 5 into fun x => f x ^ 2 + 5 where f is a function.
                              Equations
                              • One or more equations did not get rendered due to their size.
                              Instances For

                                A simproc variant of push fun _ ↦ _, to be used as simp [↓pushFun].

                                Equations
                                Instances For

                                  A simproc variant of pull fun _ ↦ _, to be used as simp [pullFun].

                                  Equations
                                  Instances For

                                    push c rewrites the goal by pushing the constant c deeper into an expression. For instance, push _ ∈ _ rewrites x ∈ {y} ∪ zᶜ into x = y ∨ ¬ x ∈ z. More precisely, the push tactic repeatedly rewrites an expression by applying lemmas of the form c ... = ... (c ...) (where c can appear 0 or more times on the right hand side). To extend the push tactic, you can tag a lemma of this form with the @[push] attribute.

                                    To instead move a constant closer to the head of the expression, use the pull tactic.

                                    push works as both a tactic and a conv tactic.

                                    • push _ ~ _ pushes the (binary) operator ~, push ~ _ pushes the (unary) operator ~.
                                    • push c at l1 l2 ... rewrites at the given locations.
                                    • push c at * rewrites at all hypotheses and the goal.
                                    • push (disch := tac) c uses the tactic tac to discharge any hypotheses for @[push] lemmas.

                                    Examples:

                                    • push _ ∈ _ rewrites x ∈ {y} ∪ zᶜ into x = y ∨ ¬ x ∈ z.
                                    • push (disch := positivity) Real.log rewrites log (a * b ^ 2) into log a + 2 * log b.
                                    • push ¬ _ is the same as push_neg or push Not, and it rewrites ¬ ∀ ε > 0, ∃ δ > 0, δ < ε into ∃ ε > 0, ∀ δ > 0, ε ≤ δ.
                                    • push fun _ ↦ _ rewrites fun x => f x ^ 2 + 5 into f ^ 2 + 5
                                    • push ∀ _, _ rewrites ∀ a, p a ∧ q a into (∀ a, p a) ∧ (∀ a, q a).
                                    Equations
                                    • One or more equations did not get rendered due to their size.
                                    Instances For

                                      push_neg rewrites the goal by pushing negations deeper into an expression. For instance, the goal ¬ ∀ x, ∃ y, x ≤ y will be transformed by push_neg into ∃ x, ∀ y, y < x. Binder names are preserved (contrary to what would happen with simp using the relevant lemmas). push_neg works as both a tactic and a conv tactic.

                                      push_neg is a special case of the more general push tactic, namely push Not. The push tactic can be extended using the @[push] attribute. push has special-casing built in for push Not.

                                      Tactics that introduce a negation usually have a version that automatically calls push_neg on that negation. These include by_cases!, contrapose! and by_contra!.

                                      • push_neg at l1 l2 ... rewrites at the given locations.
                                      • push_neg at * rewrites at each hypothesis and the goal.
                                      • push_neg +distrib rewrites ¬ (p ∧ q) into ¬ p ∨ ¬ q (by default, the tactic rewrites it into p → ¬ q instead).

                                      Example:

                                      example (h : ¬ ∀ ε > 0, ∃ δ > 0, ∀ x, |x - x₀| ≤ δ → |f x - y₀| ≤ ε) :
                                          ∃ ε > 0, ∀ δ > 0, ∃ x, |x - x₀| ≤ δ ∧ ε < |f x - y₀| := by
                                        push_neg at h
                                        -- Now we have the hypothesis `h : ∃ ε > 0, ∀ δ > 0, ∃ x, |x - x₀| ≤ δ ∧ ε < |f x - y₀|`
                                        exact h
                                      
                                      Equations
                                      • One or more equations did not get rendered due to their size.
                                      Instances For

                                        #push head e, where head is a constant and e is an expression, prints the push head form of e.

                                        #push understands local variables, so you can use them to introduce parameters.

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

                                          #push_neg e, where e is an expression, prints the push_neg form of e.

                                          #push_neg understands local variables, so you can use them to introduce parameters.

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

                                            pull c rewrites the goal by pulling the constant c closer to the head of the expression. For instance, pull _ ∈ _ rewrites x ∈ y ∨ ¬ x ∈ z into x ∈ y ∪ zᶜ. More precisely, the pull tactic repeatedly rewrites an expression by applying lemmas of the form ... (c ...) = c ... (where c can appear 1 or more times on the left hand side). pull is the inverse tactic to push. To extend the pull tactic, you can tag a lemma with the @[push] attribute. pull works as both a tactic and a conv tactic.

                                            A lemma is considered a pull lemma if its reverse direction is a push lemma that actually moves the given constant away from the head. For example

                                            • not_or : ¬ (p ∨ q) ↔ ¬ p ∧ ¬ q is a pull lemma, but not_not : ¬ ¬ p ↔ p is not.
                                            • log_mul : log (x * y) = log x + log y is a pull lemma, but log_abs : log |x| = log x is not.
                                            • Pi.mul_def : f * g = fun (i : ι) => f i * g i and Pi.one_def : 1 = fun (x : ι) => 1 are both pull lemmas for fun, because every push fun _ ↦ _ lemma is also considered a pull lemma.

                                            TODO: define a @[pull] attribute for tagging pull lemmas that are not push lemmas.

                                            • pull _ ~ _ pulls the operator or relation ~.
                                            • pull c at l1 l2 ... rewrites at the given locations.
                                            • pull c at * rewrites at all hypotheses and the goal.
                                            • pull (disch := tac) c uses the tactic tac to discharge any hypotheses for @[push] lemmas.

                                            Examples:

                                            • pull _ ∈ _ rewrites x ∈ y ∨ ¬ x ∈ z into x ∈ y ∪ zᶜ.
                                            • pull (disch := positivity) Real.log rewrites log a + 2 * log b into log (a * b ^ 2).
                                            • pull fun _ ↦ _ rewrites f ^ 2 + 5 into fun x => f x ^ 2 + 5 where f is a function.
                                            Equations
                                            • One or more equations did not get rendered due to their size.
                                            Instances For

                                              The syntax is #pull head e, where head is a constant and e is an expression, which will print the pull head form of e.

                                              #pull understands local variables, so you can use them to introduce parameters.

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

                                                #push_discr_tree X shows the discrimination tree of all lemmas used by push X. This can be helpful when you are constructing a set of push lemmas for the constant X.

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

                                                  #push_discr_tree X shows the discrimination tree of all lemmas used by push X. This can be helpful when you are constructing a set of push lemmas for the constant X.

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