01
Start here

What Formal Reasoning Is For

Formal reasoning turns arguments into objects that can be checked. In COMP2067, the practical skill is reading a goal, reading the assumptions, and choosing the next proof move without Lean feedback.

Lean 3 Prop Proof state Exam-first
Lecture slide explaining assume in a proof conversation

Concept Map

Statements
Connectives
Tactics
Datatypes
Exam traces

The Exam Mindset

The final is handwritten. That changes the goal: you are not trying to memorize Lean output, you are training proof-state prediction. A proof state has a context above the line and a goal below it. Before each tactic step, ask what the context contains and what exact goal remains.

Context P Q : Prop p : P Goal Q -> P

One Safe First Move

If the goal is an implication, use assume. If the goal is Q -> P, assume q : Q; the remaining goal becomes P, already available as p. If the goal instead matches a term in the context exactly, exact closes it.

variables P Q : Prop
example (p : P) : Q -> P :=
begin
  assume q,
  exact p,
end
LEAN 3
variables P Q : Prop
example : P -> Q -> P :=
begin
  assume p,
  assume q,
  exact p,
end
PLAIN ENGLISH

Let P and Q be propositions.

We are proving: if P holds, then if Q holds, P still holds.

Start tactic mode.

Assume evidence for P; call it p.

Assume evidence for Q; call it q. It is not actually needed.

The goal is P, and p is exactly proof of P.

The proof is complete.

How to Read Any Proof State

  1. List the assumptions you already have. These are your tools.
  2. Read the goal shape. It tells you the next likely tactic.
  3. If the goal is an implication or universal statement, introduce it with assume.
  4. If the premise contains structure, unpack it before guessing a branch.
  5. Use apply when an implication can reduce the current goal to an earlier premise.
  6. After each tactic, rewrite the new context and goal on paper.
  7. Do not write sorry in an exam proof. It is a placeholder, not evidence.
Goal shapeImplication and universal goals ask you to introduce something.
Premise shapeConjunction, disjunction, and existential premises often need unpacking.
Layer controlProp is the Lean universe of propositions. Later, Prop proofs and bool computations become related but not identical.

The goal is P -> Q. What is the safest first tactic?

Crossword

Across

    Down

      Answer key
      02
      Proof control

      Propositional Proofs Without Panic

      Propositional logic is the course's main tactic gym. Learn the shape: implication introduces, conjunction builds or unpacks, disjunction branches, and equivalence means two directions.

      Lecture slide explaining constructor tactic
      P -> QUse assume to introduce P, then prove Q.
      P /\ Q goalUse constructor, then prove both subgoals.
      P /\ Q premiseUse cases h with p q to extract both parts.
      P \/ Q goalUse left or right only when you know which side is provable.
      P \/ Q premiseUse cases and solve both branches.
      P <-> QUse constructor; prove each implication.
      Lean proof of contradiction from P and not P

      Worked Trace: Swap a Conjunction

      variables P Q R : Prop
      
      theorem comAnd : P /\ Q -> Q /\ P :=
      begin
        assume pq,
        cases pq with p q,
        constructor,
        exact q,
        exact p,
      end

      The key move is not constructor first. The premise already contains evidence, so unpack it first. Once p : P and q : Q are visible, the goal Q /\ P is straightforward.

      LEAN 3
      variables P Q R : Prop
      
      theorem curry :
        (P /\ Q -> R) <-> (P -> Q -> R) :=
      begin
        constructor,
        assume pqr p q,
        apply pqr,
        constructor,
        exact p,
        exact q,
        assume pqr pq,
        cases pq with p q,
        apply pqr,
        exact p,
        exact q,
      end
      PLAIN ENGLISH

      We prove that taking a pair P /\ Q is equivalent to taking P and then Q separately.

      constructor splits the equivalence into two directions.

      First direction: assume a function from the pair to R, then assume separate evidence p and q.

      apply pqr says: to prove R, it is enough to build P /\ Q.

      constructor builds that pair from p and q.

      Second direction: assume a function that takes P then Q, and assume a pair pq.

      cases pq opens the pair into separate evidence.

      Now apply the curried function to p and q.

      Truth Table Discipline

      1. Use the required binary row order, such as 00, 01, 10, 11.
      2. Show intermediate columns, especially for nested implications.
      3. Parse implication as right-associative: P -> Q -> R means P -> (Q -> R).
      4. Call the final column: all 1 is a tautology, all 0 is a contradiction.

      The Four Propositional Moves

      Implication turns a goal into a new assumption. Conjunction is either a pair to build or a pair to unpack. Disjunction is either a branch you choose with left/right or a branch split you must handle with cases. Equivalence is two implications, so it almost always starts with constructor.

      For (P -> Q) \/ (P -> R) -> P -> Q \/ R, after assuming the premises, what should you split?

      Crossword

      Across

        Down

          Answer key
          03
          Classical logic

          When Constructive Evidence Runs Out

          Classical reasoning is not a random extra trick. It is used when the proof needs a case split that the current evidence does not constructively provide.

          Key Syntax

          variables P : Prop
          open classical
          
          example : P \/ not P :=
          begin
            cases em P with p np,
            left,
            exact p,
            right,
            exact np,
          end

          This creates two branches: one where p : P, and one where np : not P.

          The Evidence Problem

          From not (P /\ Q), you know the pair cannot exist. You do not yet know whether P failed, whether Q failed, or both. That is why the direction not (P /\ Q) -> not P \/ not Q needs classical help in the course treatment.

          Classical De Morgan Pattern

          variables P Q : Prop
          open classical
          
          theorem dm2_em :
            not (P /\ Q) -> not P \/ not Q :=
          begin
            assume npq,
            cases em P with p np,
            right,
            assume q,
            apply npq,
            constructor,
            exact p,
            exact q,
            left,
            exact np,
          end
          LEAN 3
          variables P Q : Prop
          open classical
          
          theorem dm2_em :
            not (P /\ Q) -> not P \/ not Q :=
          begin
            assume npq,
            cases em P with p np,
            right,
            assume q,
            apply npq,
            constructor,
            exact p,
            exact q,
            left,
            exact np,
          end
          PLAIN ENGLISH

          Assume it is impossible for both P and Q to hold.

          Classically split on whether P holds.

          If P holds, we cannot prove not P, so choose the right side: not Q.

          To prove not Q, assume q : Q and derive a contradiction.

          The contradiction is that P /\ Q can now be built from p and q, violating npq.

          If P does not hold, choose the left side and give np directly.

          EMP \/ not P. Use when a proof needs a case split.
          RAATo prove P, show that not P leads to impossibility.
          Double negationnot not P -> P is a classical principle.

          What to Know, Not Overdo

          The exam-relevant point is not philosophy for its own sake. You need to know why constructive evidence is stronger, why intuitionistic logic avoids using EM automatically, why EM gives a missing case split, and how RAA changes a goal into a double-negation goal. Do not treat classical tactics as magic; write the branch reason beside the proof.

          Why does not (P /\ Q) -> not P \/ not Q need classical reasoning in this course?

          Crossword

          Across

            Down

              Answer key
              04
              Objects and evidence

              Predicates, Quantifiers, and Equality

              Predicate logic adds objects. That means the proof is no longer only about whether P or Q holds; it is about which object the evidence is about.

              Lecture slide explaining existential witness choice

              Universal Chaining

              variables A : Type
              variables PP QQ : A -> Prop
              
              example : (forall x : A, PP x) ->
                (forall y : A, PP y -> QQ y) ->
                forall z : A, QQ z :=
              begin
                assume p pq a,
                apply pq,
                apply p,
              end

              Existential Chaining

              variables A : Type
              variables PP QQ : A -> Prop
              
              example : (exists x : A, PP x) ->
                (forall y : A, PP y -> QQ y) ->
                exists z : A, QQ z :=
              begin
                assume p pq,
                cases p with a pa,
                existsi a,
                apply pq,
                exact pa,
              end
              LEAN 3
              variables A : Type
              variables PP QQ : A -> Prop
              
              example : (exists x : A, PP x) ->
                (forall y : A, PP y -> QQ y) ->
                exists z : A, QQ z :=
              begin
                assume p pq,
                cases p with a pa,
                existsi a,
                apply pq,
                exact pa,
              end
              PLAIN ENGLISH

              If some object has property PP, and every PP object has property QQ, then some object has property QQ.

              Assume the existential evidence and the universal rule.

              Open the existential evidence: it gives a real witness a and proof pa : PP a.

              Use the same witness a for the new existential goal.

              Apply the universal rule pq; now it is enough to prove PP a.

              pa is exactly that proof.

              Prove forallAssume a generic object.
              Use forallApply it to the object in front of you.
              Prove existsUse existsi with a witness that makes the goal true.
              Use existsUse cases h with a ha to reveal the witness and proof.
              Use equalityrewrite h, rewrite <- h, or rewrite h at hx.
              Predicate EMBracket the proposition: cases em (PP a) with h hnot.

              Witness Rule

              Do not guess existential witnesses just because existsi is available. If an existential premise exists, unpack it first. The witness that came with evidence is usually the one the proof needs.

              A predicate is a property of one object, such as PP x. A relation is a predicate with multiple inputs, such as RR x y. Quantifiers decide how objects enter the proof: forall gives a reusable rule, while exists gives one witness and its evidence.

              For De Morgan with predicates, keep the two patterns separate: not (exists x, PP x) <-> forall x, not (PP x) is the constructive equivalence emphasized in the slides; not (forall x, PP x) <-> exists x, not (PP x) is the classical pattern.

              LEAN 3
              variables A : Type
              variables PP : A -> Prop
              
              example : forall x y : A,
                x = y -> PP x -> PP y :=
              begin
                assume x y eq hx,
                rewrite eq at hx,
                exact hx,
              end
              PLAIN ENGLISH

              For any two objects x and y, if they are equal and PP x holds, then PP y holds.

              Introduce the objects, equality evidence, and predicate evidence.

              Rewrite inside the hypothesis hx, changing evidence about x into evidence about y.

              Now hx has the exact target shape.

              Equality as Transport

              Equality is itself a proposition. When you use rewrite, you transport evidence across that equality. Congruence is the related idea that equal inputs stay equal after applying the same function, which is why examples such as congr_arg nat.succ matter in natural-number proofs.

              What does cases h with a ha do when h : exists x : A, PP x?

              Crossword

              Across

                Down

                  Answer key
                  05
                  Inductive data

                  Booleans and Naturals as Machines

                  Booleans and natural numbers are not vague built-ins in the lecture story. They are inductive datatypes, and their functions reduce by following constructor patterns.

                  Constructor View

                  inductive lecture_bool : Type
                  | tt : lecture_bool
                  | ff : lecture_bool
                  
                  inductive lecture_nat : Type
                  | zero : lecture_nat
                  | succ : lecture_nat -> lecture_nat

                  A constructor is a named way to build a value of an inductive type. The snippets use lecture-prefixed names so the example is copyable without colliding with Lean's built-in bool and nat. In the course material, the real constructors are tt, ff, 0, and nat.succ.

                  Boolean Definition From Rows

                  Fix the first Boolean input. If the row pattern says "return the second input", write | tt b := b. If it says "always true", write | ff b := tt.

                  def bimp : bool -> bool -> bool
                  | tt b := b
                  | ff b := tt

                  Natural Reduction Trace

                  For course-style addition, recursion follows the second argument. Reduction means unfolding the matching equation until constructors remain:

                  def add : ℕ -> ℕ -> ℕ
                  | m 0 := m
                  | m (nat.succ n) := nat.succ (add m n)

                  So reduce by stripping successors from the second input until the base case appears.

                  LEAN 3
                  def bimp : bool -> bool -> bool
                  | tt b := b
                  | ff b := tt
                  
                  #reduce tt && (tt || ff)
                  #reduce ff && (tt || ff)
                  PLAIN ENGLISH

                  Boolean implication is a function taking two Boolean inputs.

                  If the first input is true, implication returns the second input.

                  If the first input is false, implication is true regardless of the second input.

                  Reduction questions ask you to unfold definitions until only constructors remain.

                  The first reduction is true; the second is false because false-and-anything is false.

                  cases xOften solves Boolean equalities by checking tt and ff.
                  is_ttBridge from a Boolean value to a proposition.
                  dsimpUnfold a definition when Lean needs help exposing the computation during a reduction trace.
                  succConstructor that builds the next natural number.
                  No-confusionzero is not equal to succ n.
                  Manual traceExam-useful for double, half, add, mul, ble; induction proofs are background unless the question asks for them.

                  Boolean Definitions Worth Knowing

                  def bxor : bool -> bool -> bool
                  | tt b := bnot b
                  | ff b := b
                  
                  def biff : bool -> bool -> bool
                  | tt b := b
                  | ff b := bnot b

                  bxor flips the second input when the first input is true. biff keeps the second input when the first input is true and flips it when the first input is false.

                  Boolean-to-Proposition Bridge

                  &&, ||, and bnot compute on Boolean data. /\, \/, and not combine propositions. The lecture bridge is is_tt b, meaning the Boolean value b is true as a proposition.

                  LEAN 3
                  def double : ℕ -> ℕ
                  | 0 := 0
                  | (nat.succ n) := nat.succ (nat.succ (double n))
                  
                  #reduce double 2  -- 4
                  PLAIN ENGLISH

                  The base case says double of zero is zero.

                  The successor case says: remove one successor, recursively double the smaller number, then add two successors back.

                  For two, strip one successor and add two around the recursive call.

                  Strip the second successor and add two more.

                  Hit zero, then rebuild outward. The result is four.

                  Revision Functions: Unknown and UnknownII

                  The revision deck uses small recursive functions to test whether you can read constructor equations. unknown behaves like maximum: unknown 0 2 reduces to 2, and unknown 5 3 reduces to 5. unknownII adds two successors in the recursive case, so the checked examples unknownII 5 3 and unknownII 3 5 both reduce to 8.

                  def unknown : ℕ -> ℕ -> ℕ
                  | a 0 := a
                  | 0 b := b
                  | (nat.succ a) (nat.succ b) := nat.succ (unknown a b)
                  
                  def unknownII : ℕ -> ℕ -> ℕ
                  | a 0 := a
                  | 0 b := b
                  | (nat.succ a) (nat.succ b) := nat.succ (nat.succ (unknownII a b))

                  What is the best description of && versus /\?

                  Crossword

                  Across

                    Down

                      Answer key
                      06
                      Final integration

                      Lists, Trees, and Exam Practice

                      Lists and trees complete the datatype arc. The exam-facing skill is not proving an industrial sorting algorithm; it is understanding constructors, no-confusion, injectivity, insertion, and traversal.

                      Revision slide image from COMP2067

                      List Shape

                      #check (@list.nil)
                      #check (@list.cons)

                      [1,2,3] is shorthand for 1 :: 2 :: 3 :: []. If a :: l = b :: m, then injection gives equality of heads and equality of tails. No-confusion says nil cannot equal a cons list.

                      Tree Shape

                      inductive Tree : Type
                      | leaf : Tree
                      | node : Tree -> ℕ -> Tree -> Tree

                      Tree sort builds a binary-search tree, then reads it with in-order traversal: left subtree, root, right subtree.

                      LEAN 3
                      example : [1, 2, 3] = 1 :: 2 :: 3 :: [] :=
                      begin
                        refl,
                      end
                      PLAIN ENGLISH

                      Lean infers this as a list of natural numbers.

                      [] is notation for the empty list, list.nil.

                      :: is notation for list.cons: it puts one element at the front of an existing list.

                      Bracket notation is convenience syntax for repeated cons.

                      refl works because both sides reduce to the same constructor structure.

                      Tree Sort Trace

                      Insert 6 as root
                      3 goes left
                      8 goes right
                      2 goes left-left
                      5 goes left-right

                      In-order traversal of that tree gives 2, 3, 5, 6, 8, matching the retained lecture example.

                      Insertion Example

                      The revision notes keep the list-insertion example ins 5 [6, 4, 2]. With the retained comparator, it reduces to [6, 5, 4, 2]. The exam skill is to trace one comparison at a time, not to recite the whole sorting algorithm.

                      What Can Be Tested

                      No-confusion and injectivity matter. [] cannot equal a :: l, and a :: l = b :: m gives both a = b and l = m. The notes say the injection tactic itself is not the exam target, but the injective property is still fair game.

                      TREE SORT
                      insert [6, 3, 8, 2, 5]
                      6 becomes the root
                      3 goes left of 6
                      8 goes right of 6
                      2 goes left of 3
                      5 goes right of 3
                      in-order: 2, 3, 5, 6, 8
                      PLAIN ENGLISH

                      Tree sort has two phases: build the tree with repeated insertion, then traverse it.

                      The first item anchors the structure.

                      Smaller values move left; larger or equal values move right.

                      The tree stores comparison decisions, not the original order.

                      Reading left-root-right recovers sorted order.

                      Closed-Book Mini Paper

                      1. Truth table: parse P -> Q -> P, write rows in the required binary order.
                      2. Prove P /\ Q -> Q /\ P in Lean tactic style.
                      3. Use EM to explain the hard De Morgan direction.
                      4. Translate a universal English statement into Lean predicates.
                      5. Define Boolean implication from a truth table.
                      6. Trace insertion of one element into a list, then draw one tree-sort example.

                      Which traversal gives sorted output from the binary-search tree in the course examples?

                      Crossword

                      Across

                        Down

                          Answer key
                          07
                          Exam training lab

                          Lean Playground

                          Practice Lean 3 proof-state prediction in two modes: normal feedback when you are learning, and delayed feedback when you are simulating the handwritten exam.

                          Lean 3 only Delayed exam feedback Curated wiki sources

                          Session Status

                          Loading the lightweight playground shell. Lean, SQLite, and Sher load only when needed.