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

    The simp configuration used in push.

    Equations
      Instances For

        Try to rewrite using a push lemma.

        Equations
          Instances For

            Common entry point to the implementation of push.

            Equations
              Instances For

                Try to rewrite using a pull lemma.

                Equations
                  Instances For

                    Common entry point to the implementation of pull.

                    Equations
                      Instances For

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

                        Equations
                          Instances For

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

                            Equations
                              Instances For

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

                                Equations
                                  Instances For

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

                                    Equations
                                      Instances For

                                        Run the push tactic.

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