Zulip Chat Archive

Stream: lean4

Topic: calculational proof of equivalence of two propositions


Bulhwi Cha (Feb 09 2023 at 07:04):

import Mathlib.Logic.Basic

example (p q r : Prop)
      : (p ∧ q ∧ ¬r) ∨ (p ∧ ¬q ∧ r) ∨ (¬p ∧ q ∧ r) ∨ (p ∧ q ∧ r)
      ↔ (p ∧ q) ∨ (p ∧ r) ∨ (q ∧ r) := calc
    (p ∧ q ∧ ¬r) ∨ (p ∧ ¬q ∧ r) ∨ (¬p ∧ q ∧ r) ∨ (p ∧ q ∧ r)
  ↔ (p ∧ q ∧ ¬r) ∨ (p ∧ ¬q ∧ r) ∨ (¬p ∧ q ∧ r) ∨
    (p ∧ q ∧  r) ∨ (p ∧  q ∧ r) ∨ ( p ∧ q ∧ r) := by repeat rw [or_self]
_ ↔ ((p ∧ q ∧ ¬r) ∨ (p ∧ q ∧ r)) ∨
    ((p ∧ ¬q ∧ r) ∨ (p ∧ q ∧ r)) ∨
    ((¬p ∧ q ∧ r) ∨ (p ∧ q ∧ r)) :=
      by rw [← @or_assoc (¬p ∧ q ∧ r), @or_comm ((¬p ∧ q ∧ r) ∨ (p ∧ q ∧ r)),
             ← @or_assoc (p ∧ ¬q ∧ r), ← @or_assoc (p ∧ ¬q ∧ r),
             @or_comm ((p ∧ ¬q ∧ r) ∨ (p ∧ q ∧ r)), ← @or_assoc (p ∧ q ∧ ¬r),
             ← @or_assoc (p ∧ q ∧ ¬r), or_assoc]
_ ↔ (( p ∧ q) ∧ (¬r ∨ r)) ∨
    (( p ∧ r) ∧ (¬q ∨ q)) ∨
    ((¬p ∨ p) ∧   q ∧ r) := by conv =>
      lhs
      congr
      . simp [← and_assoc, ← and_or_left]
      . congr
        . simp [@and_comm _ r, ← and_assoc, ← and_or_left]; rw [@and_comm r]
        . rw [← or_and_right]
_ ↔ (p ∧ q) ∨ (p ∧ r) ∨ (q ∧ r) := by conv =>
      lhs
      congr
      . rw [eq_true (em' r), and_true]
      . congr
        . rw [eq_true (em' q), and_true]
        . rw [eq_true (em' p), true_and]

Bulhwi Cha (Feb 09 2023 at 07:04):

Is there any way to write a calculational proof shorter than mine?

Mario Carneiro (Feb 09 2023 at 07:40):

does by tauto count?

Mario Carneiro (Feb 09 2023 at 07:41):

can confirm this works

import Mathlib.Tactic.Tauto

example (p q r : Prop)
      : (p ∧ q ∧ ¬r) ∨ (p ∧ ¬q ∧ r) ∨ (¬p ∧ q ∧ r) ∨ (p ∧ q ∧ r)
      ↔ (p ∧ q) ∨ (p ∧ r) ∨ (q ∧ r) := by tauto

Bulhwi Cha (Feb 09 2023 at 08:03):

Oh, thanks! Now I'm blaming myself for not having thought about using the tauto tactic.

Bulhwi Cha (Feb 09 2023 at 08:04):

But is it the only way to shorten my proof?

Mario Carneiro (Feb 09 2023 at 08:18):

here's another brute-force-ish proof:

example (p q r : Prop)
      : (p ∧ q ∧ ¬r) ∨ (p ∧ ¬q ∧ r) ∨ (¬p ∧ q ∧ r) ∨ (p ∧ q ∧ r)
      ↔ (p ∧ q) ∨ (p ∧ r) ∨ (q ∧ r) := by
  by_cases p <;> by_cases q <;> by_cases r <;> simp [*]

Bulhwi Cha (Feb 09 2023 at 08:24):

I should take a closer look at Lean's tactics.

Mario Carneiro (Feb 09 2023 at 08:24):

and here's a more "conceptual" proof most similar to your calc proof:

import Mathlib.Logic.Basic

example (p q r : Prop)
      : (p ∧ q ∧ ¬r) ∨ (p ∧ ¬q ∧ r) ∨ (¬p ∧ q ∧ r) ∨ (p ∧ q ∧ r)
      ↔ (p ∧ q) ∨ (p ∧ r) ∨ (q ∧ r) :=
  calc
    (p ∧ q ∧ ¬r) ∨ (p ∧ ¬q ∧ r) ∨ (¬p ∧ q ∧ r) ∨ (p ∧ q ∧ r)
      ↔ (p ∧ q ∧ ¬r ∨ p ∧ q ∧ r) ∨ (p ∧ ¬q ∧ r ∨ p ∧ q ∧ r) ∨ ¬p ∧ q ∧ r ∨ p ∧ q ∧ r :=
      by simp only [or_assoc, or_left_comm, or_self]
    _ ↔ (p ∧ q ∧ (¬r ∨ r)) ∨ (p ∧ (¬q ∨ q) ∧ r) ∨ ((¬p ∨ p) ∧ q ∧ r) :=
      by simp only [or_and_right, and_or_left]
    _ ↔ (p ∧ q) ∨ (p ∧ r) ∨ (q ∧ r) := by simp only [em', and_true, true_and]

Bulhwi Cha (Feb 09 2023 at 09:11):

Thanks again. Your last proof gave me some lessons:

  • Don't forget to use left and right commutativity.
  • Use parentheses carefully.
  • Get a better understanding of how tactics work under the hood.

Last updated: Feb 28 2026 at 14:05 UTC