push_neg
Push negations inward through logical connectives and quantifiers.push_neg applies De Morgan's laws and negation rules automatically.
❗
push_neg requires Mathlib. Addimport Mathlib.Tactic.PushNeg orimport Mathlib.Tactic.Basic Usage
When you have a negation in front of a compound statement, push_negpushes the negation inward, applying De Morgan's laws and quantifier duality. The result is often easier to work with than the original negated form.
lean
1import Mathlib.Tactic.PushNeg23-- push_neg transforms negations4example : ¬(P ∧ Q) ↔ ¬P ∨ ¬Q := by5 constructor6 · intro h7 push_neg at h -- h becomes: ¬P ∨ ¬Q (not quite, actually P → ¬Q)8 sorry9 · intro h10 push_neg11 sorry1213-- More practically:14example (h : ¬(∀ x : Nat, x > 0)) : ∃ x : Nat, x ≤ 0 := by15 push_neg at h16 -- h is now: ∃ x, x ≤ 017 exact hKey Takeaway
push_neg converts "not forall" to "exists not" and "not exists" to "forall not", and simplifies comparisons.Negating Quantifiers
The most common use of push_neg is negating quantifiers. "Not for all" becomes "there exists not," and "not exists" becomes "for all not." This transformation often reveals what you actually need to prove or find.
lean
1import Mathlib.Tactic.PushNeg23-- ¬∀ becomes ∃¬4example (h : ¬∀ n : Nat, n = 0) : ∃ n : Nat, n ≠ 0 := by5 push_neg at h6 exact h78-- ¬∃ becomes ∀¬9example (h : ¬∃ n : Nat, n > 100) : ∀ n : Nat, n ≤ 100 := by10 push_neg at h11 exact hNegating Comparisons
lean
1import Mathlib.Tactic.PushNeg23-- push_neg simplifies negated comparisons4example (h : ¬(x < y)) : x ≥ y := by5 push_neg at h6 exact h78example (h : ¬(x ≤ y)) : x > y := by9 push_neg at h10 exact h1112example (h : ¬(x = y)) : x ≠ y := by13 -- Already in simplest form14 exact hNegating Implications
lean
1import Mathlib.Tactic.PushNeg23-- ¬(P → Q) becomes P ∧ ¬Q4example (h : ¬(P → Q)) : P ∧ ¬Q := by5 push_neg at h6 exact h78-- Works with quantified implications9example (h : ¬(∀ x : Nat, x > 0 → x ≥ 1)) : ∃ x : Nat, x > 0 ∧ x < 1 := by10 push_neg at h11 exact hℹ
push_neg transforms ¬(P → Q)to P ∧ ¬Q, which is logically equivalent in classical logic.On the Goal
lean
1import Mathlib.Tactic.PushNeg23-- push_neg can also transform the goal4example : ¬(∀ n : Nat, n < n + 1 → n = 0) := by5 push_neg6 -- Goal becomes: ∃ n, n < n + 1 ∧ n ≠ 07 use 18 simp910-- Useful for proving negations11example : ¬(∀ f : Nat → Nat, ∃ x, f x = 0) := by12 push_neg13 -- Goal: ∃ f, ∀ x, f x ≠ 014 use fun _ => 115 simpDeep Dive: push_neg Rules
push_neg applies these transformations:
¬(P ∧ Q)→P → ¬Q¬(P ∨ Q)→¬P ∧ ¬Q¬(P → Q)→P ∧ ¬Q¬∀ x, P x→∃ x, ¬P x¬∃ x, P x→∀ x, ¬P x¬(a < b)→a ≥ b¬(a ≤ b)→a > b
Combined with Other Tactics
lean
1import Mathlib.Tactic.PushNeg2import Mathlib.Tactic.Cases34-- push_neg then rcases5example (h : ¬∀ x : Nat, x = 0 ∨ x > 10) : ∃ x : Nat, x ≠ 0 ∧ x ≤ 10 := by6 push_neg at h7 -- h : ∃ x, x ≠ 0 ∧ x ≤ 108 exact h910-- push_neg in contrapositive proofs11example (h : ¬Q) (hpq : P → Q) : ¬P := by12 intro hp13 exact h (hpq hp)Real-World Examples
Epsilon-Delta Negation
lean
1import Mathlib.Tactic.PushNeg23-- Negating a limit definition4-- "f doesn't converge to L" means:5-- ∃ ε > 0, ∀ δ > 0, ∃ x, |x - a| < δ ∧ |f x - L| ≥ ε6example (h : ¬∀ ε > 0, ∃ δ > 0, ∀ x, |x - a| < δ → |f x - L| < ε) :7 ∃ ε > 0, ∀ δ > 0, ∃ x, |x - a| < δ ∧ |f x - L| ≥ ε := by8 push_neg at h9 exact hCounterexample Finding
lean
1import Mathlib.Tactic.PushNeg23-- Show that not all functions have fixed points4example : ¬∀ f : Nat → Nat, ∃ x, f x = x := by5 push_neg6 -- Need: ∃ f, ∀ x, f x ≠ x7 use (· + 1) -- successor function8 intro x9 omegaBounds and Suprema
lean
1import Mathlib.Tactic.PushNeg23-- "M is not an upper bound" means some element exceeds it4example (h : ¬∀ x ∈ S, x ≤ M) : ∃ x ∈ S, x > M := by5 push_neg at h6 exact hCommon Patterns
lean
1import Mathlib.Tactic.PushNeg23-- Proving something is not bounded4example : ¬∃ M : Nat, ∀ n : Nat, n ≤ M := by5 push_neg6 -- ∀ M, ∃ n, n > M7 intro M8 use M + 19 omega1011-- Proving functions are different12example : (fun x : Nat => x + 1) ≠ (fun x => x) := by13 intro h14 have : 1 = 0 := congrFun h 015 omegaExercise: Push a Negation
Use push_neg to transform a negated universal.
lean
1import Mathlib.Tactic.PushNeg23example (h : ¬∀ x : Nat, x = 0) : ∃ x : Nat, x ≠ 0 := by4 push_neg at h5 exact h