A Natural Deduction Proof System

Gries’ second style of formal reasoning — deriving new facts line by line from premises using named inference rules, the way a working mathematician actually argues, rather than rewriting one formula into another with equivalence laws.

This page covers Chapter 4 of The Science of Programming — the natural deduction (ND) proof system. It complements the equivalence-transformation style of Foundations. Both prove the same theorems; they are simply two disciplines for getting there.

By this point you can manipulate propositions with the algebra of equivalence — De Morgan, distribution, absorption — rewriting a formula step by step until it collapses to T. That is elegant for boolean simplification, but it is not how anyone proves “if the input is sorted then binary search returns the right index.” For implications and case analysis you want to reason forward from assumptions: suppose the antecedent, grind out consequences, arrive at the conclusion. That is natural deduction, and it is the workhorse for the implication proof obligations that program correctness throws at you.

Notation follows Gries: (and), (or), (implies), ¬ (not), (equivalence), F (false/contradiction). A rule name like ∧-I reads “and-introduction”; the turnstile reads “proves”.

Contents

  1. Two styles of proof
  2. The format of a proof
  3. Inference rules
  4. Assumptions and their scope
  5. The Deduction Theorem
  6. Soundness & when to use which style
  7. Summary

Two styles of proof

Gries develops two complete, sound systems for propositional logic. They reach exactly the same set of theorems; they differ entirely in how a proof is written down.

Equivalence transformation (Ch 2/3)
# Prove:  P ∧ (P ⇒ Q)  ⇒  Q
# Rewrite one formula until it is T.
   P ∧ (P ⇒ Q)  ⇒  Q
# implication as disjunction
≡ ¬(P ∧ (¬P ∨ Q)) ∨ Q
# distribute, De Morgan, simplify
≡ ¬(P ∧ Q) ∨ Q
≡ ¬P ∨ ¬Q ∨ Q
≡ ¬P ∨ T
≡ T          # a theorem
Natural deduction (Ch 4)
# Prove:  P, P ⇒ Q  ⊢  Q
# Derive new LINES from premises.
1  P              premise
2  P ⇒ Q          premise
3  Q              ⇒-E on 1, 2
# Q is derived → done. This is how a
# mathematician writes it: modus ponens.

The left column treats a proof as a chain of equivalences massaging a single expression toward T. The right column treats a proof as a sequence of assertions, each one either given or squeezed out of earlier ones by a rule of inference. The second style scales far better to hypothetical reasoning (“assume this, then…”) and to breaking a goal into cases — the two moves that dominate real proofs.

Equivalence style: rewrite one formula with laws until it is T.
Natural deduction: derive new lines from premises via inference rules.
Both are sound. ND is closer to how mathematicians argue.

The format of a proof

A natural deduction proof is a numbered sequence of lines. Each line holds one proposition together with a justification: either it is a premise (something given) or an assumption (something temporarily supposed), or it is derived from one or more earlier lines by a named inference rule. The proposition on the last line is the goal — when it appears, the proof is complete.

To prove that premises H1, …, Hn yield conclusion C — written H1, …, Hn ⊢ C — you list the premises, then extend the list one justified line at a time until C shows up. Here is a small worked proof that P ∧ Q and Q ⇒ R together give R ∧ P:

# Goal:  P ∧ Q,  Q ⇒ R   ⊢   R ∧ P

  line   proposition        justification
  ────   ───────────        ───────────────────────
   1     P ∧ Q             premise
   2     Q ⇒ R             premise
   3     P                 ∧-E on 1        # left conjunct
   4     Q                 ∧-E on 1        # right conjunct
   5     R                 ⇒-E on 2, 4     # modus ponens
   6     R ∧ P             ∧-I on 5, 3     # goal reached

Read it top to bottom: nothing on any line is unjustified. Lines 1–2 are the givens; 3–4 take the conjunction apart; 5 fires modus ponens; 6 reassembles the goal. Every step cites the earlier line numbers it depends on and the rule that licenses it. This bookkeeping is exactly what makes the proof checkable — a reader (or a machine) can verify each line in isolation.

Inference rules

The engine of the system is a fixed, small set of inference rules. They come in matched pairs, one per connective: an introduction rule that tells you how to build a formula with that connective, and an elimination rule that tells you how to use one you already have. Above each line is what you must already have; below is what you may then write.

RuleForm (from → infer)Meaning
∧-I (and-introduction)from P and Q  infer  P ∧ QIf both are established, their conjunction is.
∧-E (and-elimination)from P ∧ Q  infer  P  (and separately infer Q)A conjunction lets you extract either conjunct.
∨-I (or-introduction)from P  infer  P ∨ Q  (for any Q)Anything true is true of a wider disjunction.
∨-E (or-elimination / proof by cases)from P ∨ Q, P ⇒ R, and Q ⇒ R  infer  RIf each disjunct forces R, then R holds regardless of which one is true.
⇒-I (implication introduction / assumption discharge)assume P, derive Q  then  infer P ⇒ QShowing Q follows from a supposed P establishes the implication and discharges the assumption.
⇒-E (implication elimination / modus ponens)from P and P ⇒ Q  infer  QAn implication plus its antecedent yields its consequent.
¬-I (not-introduction / reductio)assume P, derive F  then  infer ¬PIf assuming P leads to a contradiction, P must be false.
¬-E (not-elimination)from P and ¬P  infer  FA proposition and its negation together are a contradiction.
≡-I / ≡-EP ≡ Q  is  (P ⇒ Q) ∧ (Q ⇒ P)Prove equivalence as two implications; use it as either.

Two of these carry more weight than the rest. Proof by cases (∨-E) is how you reason about a disjunctive fact you cannot pin down — you show the same conclusion in every case. Assumption discharge (⇒-I) is how you prove an implication at all: you cannot prove P ⇒ Q by knowing P is true, because it may not be; instead you temporarily suppose it, work forward, and record that the resulting Q depended on that supposition.

Reductio ad absurdum (¬-I) is assumption discharge’s twin: to prove ¬P, assume P, derive a contradiction F (usually via ¬-E from some R and ¬R), and conclude ¬P, discharging the assumption. It is the same box-and-discharge machinery pointed at a negation.

Assumptions and their scope

An assumption is not a free fact — it is a supposition that lives inside a subproof, drawn as an indented box. Everything you derive inside the box may lean on the assumption; nothing outside the box may. When you close the box with ⇒-I, you discharge the assumption: the box collapses to a single implication assumption ⇒ last-line, which is now usable at the outer level. This scoping is what keeps ND honest — a temporary supposition can never leak out and be mistaken for a proven fact.

The classic first example is P ⇒ (Q ⇒ P) — provable from no premises at all, using nested boxes:

# Goal:   ⊢   P ⇒ (Q ⇒ P)

  1  ┌─ P                assume  (outer box, scope of P)
  2  │  ┌─ Q             assume  (inner box, scope of Q)
  3  │  │   P            reiterate line 1 — P is in scope here
  4  │  └─ Q ⇒ P        ⇒-I: discharge Q (from 2–3)
  5  └─ P ⇒ (Q ⇒ P)    ⇒-I: discharge P (from 1–4)
# Both assumptions discharged → the conclusion
# depends on nothing. It is a tautology.

Note how P from line 1 is legitimately reused at line 3: line 3 sits inside the outer box, so P is still in scope. Had line 1’s box already closed, citing it would be an error.

A more useful example is the transitivity of implication, (P ⇒ Q) ∧ (Q ⇒ R)  ⊢  (P ⇒ R) — the shape you meet constantly when chaining program steps:

# Goal:  (P ⇒ Q) ∧ (Q ⇒ R)   ⊢   P ⇒ R

  1     (P ⇒ Q) ∧ (Q ⇒ R)   premise
  2     P ⇒ Q                 ∧-E on 1
  3     Q ⇒ R                 ∧-E on 1
  4  ┌─ P                     assume  (scope of P opens)
  5  │   Q                    ⇒-E on 2, 4   (modus ponens)
  6  │   R                    ⇒-E on 3, 5   (modus ponens)
  7  └─ P ⇒ R                 ⇒-I: discharge P (from 4–6)
# Line 7 no longer depends on the assumption;
# it depends only on premise 1.  ∎

Inside the box we happily use P as if true (lines 5–6). The instant we close the box at line 7, that usage is sealed inside an implication and the assumption is gone. This assume-work-discharge rhythm is the single most important pattern in the whole system.

The Deduction Theorem

Why is the assume-and-discharge move legitimate? Because of a metatheorem that connects derivation from an extra premise to a derived implication:

Deduction Theorem:
  {premises, P} ⊢ Q  iff  {premises} ⊢ P ⇒ Q

In words: proving Q with P added to your premises is exactly as good as proving the implication P ⇒ Q without it. The two are interderivable. That equivalence is precisely what ⇒-I encodes as a mechanical rule — opening a box adds P to your working premises, and closing it trades the box for P ⇒ Q at the outer level.

The payoff is enormous: it means you never have to reason directly about an implication as an opaque object. You reduce proving P ⇒ Q to the far easier task of assuming P and hunting for Q. The theorem guarantees the two are the same, so the shortcut is sound. Every subproof box in the previous section is the Deduction Theorem applied once.

Read both directions. Left-to-right justifies discharging an assumption (turn a hypothetical derivation into an implication). Right-to-left justifies the reverse: if you have P ⇒ Q and you assume P, you may help yourself to Q — which is just modus ponens. The theorem ties introduction and elimination of together.

Soundness & when to use which style

Both proof systems are sound: every rule preserves truth, so anything you derive is genuinely a logical consequence of the premises (and, for ND, the system is also complete — every valid consequence has a proof). Soundness is what lets you trust a mechanical, line-by-line check as a real guarantee of correctness. The choice between the styles is therefore about ergonomics, not validity.

Use……when the goal isWhy it wins
Equivalence transformationsimplifying or normalising a boolean expression; showing two formulas are equalSlick, symmetric, no assumptions to track — pure algebra.
Natural deductionproving an implication, or a conclusion that needs case analysisAssume-and-discharge and proof-by-cases map directly onto the goal’s shape.

For program proofs this matters concretely. Almost every verification condition you generate has the form of an implication — most often P ∧ B ⇒ wp(S, P), the obligation that a loop body preserves its invariant, or P ∧ ¬B ⇒ R, that exit re-establishes the postcondition. ND handles these cleanly: assume the antecedent (the invariant and the guard), then derive the consequent step by step. The equivalence style, by contrast, would force you to flatten the whole implication into a single formula and grind it to T — possible, but painful the moment the predicates involve real arithmetic or arrays.

See The iterative command (DO) for where these implication obligations come from: the five-part loop checklist is a list of facts, and natural deduction is the tool for discharging each one.

Summary

IdeaThe one-line takeaway
Two stylesEquivalence rewriting massages one formula to T; natural deduction derives new lines from premises — both sound.
Proof formatA numbered sequence of lines, each a premise/assumption or derived by a named rule; the goal is the last line.
Introduction vs. eliminationEach connective has a rule to build it and a rule to use it — ∧-I/∧-E, ∨-I/∨-E, ⇒-I/⇒-E, ¬-I/¬-E.
Modus ponens (⇒-E)From P and P ⇒ Q infer Q — the most-used elimination rule.
Proof by cases (∨-E)If each disjunct of P ∨ Q forces R, then R holds either way.
Assumption & scopeAn assumption lives in a subproof box; usable only inside; discharged by ⇒-I into an implication.
Reductio (¬-I)Assume P, derive contradiction F, conclude ¬P.
Deduction Theorem{prem, P} ⊢ Q iff {prem} ⊢ P ⇒ Q — the justification for assume-and-discharge.
Which style for programsVerification conditions are implications like P ∧ B ⇒ wp(S,P); ND discharges them cleanly.
The recurring theme: natural deduction mirrors how you actually think. Suppose the hypothesis, follow consequences, box off temporary assumptions, and combine cases — the same moves a mathematician makes at a whiteboard, made mechanical and checkable. For the implication-shaped proof obligations of program correctness, it is the tool that fits the hand.