Skip to content
The Lumenary

Formal mathematics laboratory

Lumenary.PropositionalLogic

Propositional logic and truth tables

Formal library

  • FormulastructureDefinitionNo axioms
    FormulaLean 4Formally verified
    /-- Propositional formulas in `n` variables `x₀, …, xₙ₋₁`: variables, the constants true and
    false, and the connectives not, and, or, implies and if-and-only-if. -/
    inductive Formula (n : ℕ) : Type where
      | var : Fin n → Formula n
      | tt : Formula n
      | ff : Formula n
      | not : Formula n → Formula n
      | and : Formula n → Formula n → Formula n
      | or : Formula n → Formula n → Formula n
      | imp : Formula n → Formula n → Formula n
      | iff : Formula n → Formula n → Formula n
    Axioms used: No axiomsformal/Lumenary/PropositionalLogic.leanTry it in the Lean web editor
  • Formula.evaldefDefinitionNo axioms
    evalLean 4Formally verified
    /-- The truth value of a formula in one row of its truth table. A row (a *valuation*) `v`
    assigns `true` or `false` to each variable. Note the conditional: `φ → ψ` is false only when
    `φ` is true and `ψ` is false, i.e. it has the value `!φ || ψ`. -/
    def Formula.eval {n : ℕ} (v : Fin n → Bool) : Formula n → Bool
      | .var i => v i
      | .tt => true
      | .ff => false
      | .not φ => !φ.eval v
      | .and φ ψ => φ.eval v && ψ.eval v
      | .or φ ψ => φ.eval v || ψ.eval v
      | .imp φ ψ => !φ.eval v || ψ.eval v
      | .iff φ ψ => φ.eval v == ψ.eval v
    Axioms used: No axiomsformal/Lumenary/PropositionalLogic.leanTry it in the Lean web editor
  • valuationsdefDefinitionpropext
    valuationsLean 4Formally verified
    /-- All rows of a truth table in `n` variables, in textbook order (the first variable is true
    in the first half of the rows, false in the second half, and so on recursively). -/
    def valuations : (n : ℕ) → List (Fin n → Bool)
      | 0 => [fun i => i.elim0]
      | n + 1 => [true, false].flatMap fun b => (valuations n).map (Fin.cons b)
    Axioms used: propextformal/Lumenary/PropositionalLogic.leanTry it in the Lean web editor
  • length_valuationstheoremProved here from basic factspropext
    length_valuationsLean 4Proved here from basic factsFormally verified
    /-- A truth table in `n` variables has `2 ^ n` rows: each new variable doubles the number of
    rows, once with the variable true and once with it false. Proved by induction on `n`. -/
    theorem length_valuations (n : ℕ) : (valuations n).length = 2 ^ n := by
      induction n with
      | zero => rfl
      | succ n ih => simp [valuations, ih, pow_succ, Nat.mul_two]
    Axioms used: propextformal/Lumenary/PropositionalLogic.leanTry it in the Lean web editor
  • mem_valuationstheoremProved here from basic factspropext, Quot.sound
    mem_valuationsLean 4Proved here from basic factsFormally verified
    /-- **Every row appears.** Any assignment of truth values to `n` variables is one of the rows
    listed by `valuations n`. Proof by induction on `n`: an assignment to `n + 1` variables is its
    value on the first variable followed by an assignment to the remaining `n`
    (`Fin.cons_self_tail`). -/
    theorem mem_valuations : ∀ (n : ℕ) (v : Fin n → Bool), v ∈ valuations n
      | 0, v => by
        simp only [valuations, List.mem_singleton]
        funext i
        exact i.elim0
      | n + 1, v => by
        simp only [valuations, List.mem_flatMap, List.mem_map]
        refine ⟨v 0, by cases v 0 <;> simp, Fin.tail v, mem_valuations n (Fin.tail v), ?_⟩
        exact Fin.cons_self_tail v
    Axioms used: propext, Quot.soundformal/Lumenary/PropositionalLogic.leanTry it in the Lean web editor
  • isTautologydefDefinitionpropext
    isTautologyLean 4Formally verified
    /-- The **truth-table test**: a formula passes when it is true in every row of its table. -/
    def isTautology {n : ℕ} (φ : Formula n) : Bool := (valuations n).all fun v => φ.eval v
    Axioms used: propextformal/Lumenary/PropositionalLogic.leanTry it in the Lean web editor
  • isTautology_ifftheoremProved here from basic factspropext, Quot.sound
    isTautology_iffLean 4Proved here from basic factsFormally verified
    /-- **The truth-table method is correct.** The finite check `isTautology φ` succeeds exactly
    when `φ` is true under *every* assignment, i.e. exactly when `φ` is a tautology. The forward
    direction needs `mem_valuations`: no row has been forgotten. -/
    theorem isTautology_iff {n : ℕ} (φ : Formula n) :
        isTautology φ = true ↔ ∀ v : Fin n → Bool, φ.eval v = true := by
      unfold isTautology
      rw [List.all_eq_true]
      exact ⟨fun h v => h v (mem_valuations n v), fun h v _ => h v⟩
    Axioms used: propext, Quot.soundformal/Lumenary/PropositionalLogic.leanTry it in the Lean web editor
  • EquivalentdefDefinitionNo axioms
    EquivalentLean 4Formally verified
    /-- Two formulas are **logically equivalent** when they have the same truth value in every row
    of the truth table. -/
    def Equivalent {n : ℕ} (φ ψ : Formula n) : Prop := ∀ v : Fin n → Bool, φ.eval v = ψ.eval v
    Axioms used: No axiomsformal/Lumenary/PropositionalLogic.leanTry it in the Lean web editor
  • equivalent_iff_tautologytheoremProved here from basic factspropext, Quot.sound
    equivalent_iff_tautologyLean 4Proved here from basic factsFormally verified
    /-- `φ` and `ψ` are equivalent exactly when the biconditional `φ ↔ ψ` is a tautology, so the
    truth-table test also decides equivalence. -/
    theorem equivalent_iff_tautology {n : ℕ} (φ ψ : Formula n) :
        Equivalent φ ψ ↔ isTautology (.iff φ ψ) = true := by
      rw [isTautology_iff]
      simp [Equivalent, Formula.eval]
    Axioms used: propext, Quot.soundformal/Lumenary/PropositionalLogic.leanTry it in the Lean web editor
  • pdefDefinitionpropext
    pLean 4Formally verified
    /-- The variable `p`, the first of two variables. -/
    abbrev p : Formula 2 := var 0
    Axioms used: propextformal/Lumenary/PropositionalLogic.leanTry it in the Lean web editor
  • qdefDefinitionpropext
    qLean 4Formally verified
    /-- The variable `q`, the second of two variables. -/
    abbrev q : Formula 2 := var 1
    Axioms used: propextformal/Lumenary/PropositionalLogic.leanTry it in the Lean web editor
  • contrapositive_tabletheoremProved here from basic factspropext, Quot.sound
    contrapositive_tableLean 4Proved here from basic factsFormally verified
    /-- **Contrapositive.** `p → q` is equivalent to `¬q → ¬p`: the truth-table test passes on all
    four rows (computed by `decide`). -/
    theorem contrapositive_table : Equivalent (imp p q) (imp (not q) (not p)) := by
      rw [equivalent_iff_tautology]
      decide
    Axioms used: propext, Quot.soundformal/Lumenary/PropositionalLogic.leanTry it in the Lean web editor
  • converse_tabletheoremProved here from basic factspropext
    converse_tableLean 4Proved here from basic factsFormally verified
    /-- **The converse is different.** `p → q` and `q → p` are *not* equivalent: they disagree in
    the row `p = false`, `q = true`, where `p → q` is (vacuously) true but `q → p` is false. -/
    theorem converse_table : ¬ Equivalent (imp p q) (imp q p) := by
      intro h
      have row := h (fun i => if i = 0 then false else true)
      revert row
      decide
    Axioms used: propextformal/Lumenary/PropositionalLogic.leanTry it in the Lean web editor
  • de_morgan_tabletheoremProved here from basic factspropext, Quot.sound
    de_morgan_tableLean 4Proved here from basic factsFormally verified
    /-- **De Morgan's laws** as truth tables: `¬(p ∧ q) ≡ ¬p ∨ ¬q` and `¬(p ∨ q) ≡ ¬p ∧ ¬q`. -/
    theorem de_morgan_table :
        Equivalent (not (and p q)) (or (not p) (not q)) ∧
          Equivalent (not (or p q)) (and (not p) (not q)) := by
      rw [equivalent_iff_tautology, equivalent_iff_tautology]
      decide
    Axioms used: propext, Quot.soundformal/Lumenary/PropositionalLogic.leanTry it in the Lean web editor
  • not_imp_tabletheoremProved here from basic factspropext, Quot.sound
    not_imp_tableLean 4Proved here from basic factsFormally verified
    /-- **Negating a conditional.** `¬(p → q) ≡ p ∧ ¬q`: a promise "if p then q" is broken exactly
    when p happens and q does not. -/
    theorem not_imp_table : Equivalent (not (imp p q)) (and p (not q)) := by
      rw [equivalent_iff_tautology]
      decide
    Axioms used: propext, Quot.soundformal/Lumenary/PropositionalLogic.leanTry it in the Lean web editor
  • argument_formstheoremProved here from basic factspropext
    argument_formsLean 4Proved here from basic factsFormally verified
    /-- **Valid and invalid argument forms.** *Modus ponens* `((p → q) ∧ p) → q` and *modus tollens*
    `((p → q) ∧ ¬q) → ¬p` are tautologies; *affirming the consequent* `((p → q) ∧ q) → p` is not. -/
    theorem argument_forms :
        isTautology (imp (and (imp p q) p) q) = true ∧
          isTautology (imp (and (imp p q) (not q)) (not p)) = true ∧
          isTautology (imp (and (imp p q) q) p) = false := by
      decide
    Axioms used: propextformal/Lumenary/PropositionalLogic.leanTry it in the Lean web editor
  • contrapositivetheoremProved here from basic factsNo axioms
    contrapositiveLean 4Proved here from basic factsFormally verified
    /-- From `p → q` we get `¬q → ¬p`: if `q` fails, then `p` must fail too, since `p` would give `q`.
    This direction is *constructive*: it uses no law of excluded middle. -/
    theorem contrapositive {p q : Prop} (h : p → q) : ¬q → ¬p :=
      fun hnq hp => hnq (h hp)
    Axioms used: No axiomsformal/Lumenary/PropositionalLogic.leanTry it in the Lean web editor
  • contrapositive_ifftheoremProved here from basic factspropext, Classical.choice, Quot.sound
    contrapositive_iffLean 4Proved here from basic factsFormally verified
    /-- **The contrapositive law** `(p → q) ↔ (¬q → ¬p)`. The way back, from `¬q → ¬p` to `p → q`,
    argues by contradiction: given `p`, if `q` failed we would get `¬p`, which is absurd. That step
    uses classical logic (`by_contra`). -/
    theorem contrapositive_iff (p q : Prop) : (p → q) ↔ (¬q → ¬p) := by
      constructor
      · exact contrapositive
      · intro h hp
        by_contra hnq
        exact h hnq hp
    Axioms used: propext, Classical.choice, Quot.soundformal/Lumenary/PropositionalLogic.leanTry it in the Lean web editor
  • contrapositive_iff_librarytheoremApplies a library theorempropext, Classical.choice, Quot.sound
    contrapositive_iff_libraryLean 4Applies a library theoremFormally verified
    /-- The contrapositive law, by Mathlib's `not_imp_not : (¬a → ¬b) ↔ (b → a)`. -/
    theorem contrapositive_iff_library (p q : Prop) : (p → q) ↔ (¬q → ¬p) :=
      not_imp_not.symm
    Axioms used: propext, Classical.choice, Quot.soundformal/Lumenary/PropositionalLogic.leanTry it in the Lean web editor
  • converse_failstheoremProved here from basic factsNo axioms
    converse_failsLean 4Proved here from basic factsFormally verified
    /-- **An implication does not imply its converse.** Take `p` false and `q` true: `p → q` holds
    (its hypothesis is false), but `q → p` would turn a proof of `True` into a proof of `False`. -/
    theorem converse_fails : ¬ ∀ p q : Prop, (p → q) → (q → p) := by
      intro h
      exact h False True (fun hf => hf.elim) trivial
    Axioms used: No axiomsformal/Lumenary/PropositionalLogic.leanTry it in the Lean web editor
  • de_morgan_ortheoremProved here from basic factsNo axioms
    de_morgan_orLean 4Proved here from basic factsFormally verified
    /-- **De Morgan** `¬(p ∨ q) ↔ ¬p ∧ ¬q`, proved constructively: "neither p nor q". -/
    theorem de_morgan_or (p q : Prop) : ¬(p ∨ q) ↔ ¬p ∧ ¬q :=
      ⟨fun h => ⟨fun hp => h (Or.inl hp), fun hq => h (Or.inr hq)⟩,
        fun ⟨hnp, hnq⟩ h => h.elim hnp hnq⟩
    Axioms used: No axiomsformal/Lumenary/PropositionalLogic.leanTry it in the Lean web editor
  • de_morgan_andtheoremApplies a library theorempropext, Classical.choice, Quot.sound
    de_morgan_andLean 4Applies a library theoremFormally verified
    /-- **De Morgan** `¬(p ∧ q) ↔ ¬p ∨ ¬q`, by Mathlib's `not_and_or`. Going from left to right
    needs classical logic: to name *which* of `p`, `q` fails we must decide whether `p` holds. -/
    theorem de_morgan_and (p q : Prop) : ¬(p ∧ q) ↔ ¬p ∨ ¬q :=
      not_and_or
    Axioms used: propext, Classical.choice, Quot.soundformal/Lumenary/PropositionalLogic.leanTry it in the Lean web editor
  • not_imp_ifftheoremApplies a library theorempropext, Classical.choice, Quot.sound
    not_imp_iffLean 4Applies a library theoremFormally verified
    /-- **Negating a conditional**: `¬(p → q) ↔ p ∧ ¬q`, by core Lean's `Classical.not_imp`. -/
    theorem not_imp_iff (p q : Prop) : ¬(p → q) ↔ p ∧ ¬q :=
      Classical.not_imp
    Axioms used: propext, Classical.choice, Quot.soundformal/Lumenary/PropositionalLogic.leanTry it in the Lean web editor
  • not_forall_imptheoremProved here from basic factspropext, Classical.choice, Quot.sound
    not_forall_impLean 4Proved here from basic factsFormally verified
    /-- **Negating a quantified conditional**: "not every `x` with `P` has `Q`" means "some `x` has
    `P` but not `Q`". It combines `Classical.not_forall` (`¬∀ ↔ ∃¬`) with the negation of a
    conditional. -/
    theorem not_forall_imp {α : Type*} (P Q : α → Prop) :
        (¬ ∀ x, P x → Q x) ↔ ∃ x, P x ∧ ¬ Q x := by
      rw [Classical.not_forall]
      exact exists_congr fun x => Classical.not_imp
    Axioms used: propext, Classical.choice, Quot.soundformal/Lumenary/PropositionalLogic.leanTry it in the Lean web editor
  • not_every_prime_oddtheoremProved here from basic factspropext, Classical.choice, Quot.sound
    not_every_prime_oddLean 4Proved here from basic factsFormally verified
    /-- "Every prime is odd" is false. By `not_forall_imp`, its negation is "some prime is not odd",
    and `2` is a witness. -/
    theorem not_every_prime_odd : ¬ ∀ n : ℕ, n.Prime → Odd n := by
      rw [not_forall_imp]
      exact ⟨2, Nat.prime_two, by decide⟩
    Axioms used: propext, Classical.choice, Quot.soundformal/Lumenary/PropositionalLogic.leanTry it in the Lean web editor
  • vacuous_truththeoremProved here from basic factsNo axioms
    vacuous_truthLean 4Proved here from basic factsFormally verified
    /-- **Vacuous truth.** "If a natural number is negative, then it equals 17" is *true*: its
    hypothesis never holds, so it can never be broken. -/
    theorem vacuous_truth : ∀ n : ℕ, n < 0 → n = 17 :=
      fun n h => absurd h (Nat.not_lt_zero n)
    Axioms used: No axiomsformal/Lumenary/PropositionalLogic.leanTry it in the Lean web editor

Formal exercises

Each exercise contains a sorry for you to replace. Open it in the Lean web editor, or clone the repository and run lake build.

contrapositivesorry × 1Try it in the Lean web editor
/-- From `p → q`, prove `¬q → ¬p`.
Hint: `¬q` is a function from proofs of `q` to `False`. Start with `intro hnq hp`. -/
theorem contrapositive {p q : Prop} (h : p → q) : ¬q → ¬p := by
  sorry
Show the compiled solution
contrapositiveLean 4Proved here from basic factsFormally verified
/-- From `p → q` we get `¬q → ¬p`: if `q` fails, then `p` must fail too, since `p` would give `q`.
This direction is *constructive*: it uses no law of excluded middle. -/
theorem contrapositive {p q : Prop} (h : p → q) : ¬q → ¬p :=
  fun hnq hp => hnq (h hp)
Axioms used: No axiomsformal/Lumenary/PropositionalLogic.leanTry it in the Lean web editor
de_morgan_orsorry × 1Try it in the Lean web editor
/-- De Morgan: "not (p or q)" is the same as "not p and not q".
Hint: use `constructor`; for each direction, `intro` the hypotheses and use `Or.inl`, `Or.inr`
or `Or.elim`. No classical logic is needed. -/
theorem de_morgan_or (p q : Prop) : ¬(p ∨ q) ↔ ¬p ∧ ¬q := by
  sorry
Show the compiled solution
de_morgan_orLean 4Proved here from basic factsFormally verified
/-- **De Morgan** `¬(p ∨ q) ↔ ¬p ∧ ¬q`, proved constructively: "neither p nor q". -/
theorem de_morgan_or (p q : Prop) : ¬(p ∨ q) ↔ ¬p ∧ ¬q :=
  ⟨fun h => ⟨fun hp => h (Or.inl hp), fun hq => h (Or.inr hq)⟩,
    fun ⟨hnp, hnq⟩ h => h.elim hnp hnq⟩
Axioms used: No axiomsformal/Lumenary/PropositionalLogic.leanTry it in the Lean web editor
not_every_prime_oddsorry × 1Try it in the Lean web editor
/-- Refute "every prime is odd" with a counterexample.
Hint: `intro h`, then apply `h` to `2` and `Nat.prime_two`, and use `decide` to see that `2` is
not odd. -/
theorem not_every_prime_odd : ¬ ∀ n : ℕ, n.Prime → Odd n := by
  sorry
Show the compiled solution
not_every_prime_oddLean 4Proved here from basic factsFormally verified
/-- "Every prime is odd" is false. By `not_forall_imp`, its negation is "some prime is not odd",
and `2` is a witness. -/
theorem not_every_prime_odd : ¬ ∀ n : ℕ, n.Prime → Odd n := by
  rw [not_forall_imp]
  exact ⟨2, Nat.prime_two, by decide⟩
Axioms used: propext, Classical.choice, Quot.soundformal/Lumenary/PropositionalLogic.leanTry it in the Lean web editor