Drafting#
Pantograph supports drafting (technically the sketch step) from
Draft-Sketch-Prove.
Pantograph’s drafting feature is more powerful. At any place in the proof, you
can replace an expression with sorry
, and the sorry
will become a goal. Any type errors will also become goals. In order to detect whether type errors have occurred, the user can look at the messages from each compilation unit.
At this point we must introduce the idea of compilation units. Each Lean definition, theorem, constant, etc., is a compilation unit. When Pantograph extracts data from Lean source code, it sections the data into these compilation units.
For example, consider this sketch produced by a language model prover:
theorem add_comm_proved_formal_sketch : ∀ n m : Nat, n + m = m + n := by
intros n m
induction n with
| zero =>
have h_base: 0 + m = m := sorry
have h_symm: m + 0 = m := sorry
sorry
| succ n ih =>
have h_inductive: n + m = m + n := sorry
have h_pull_succ_out_from_right: m + Nat.succ n = Nat.succ (m + n) := sorry
have h_flip_n_plus_m: Nat.succ (n + m) = Nat.succ (m + n) := sorry
have h_pull_succ_out_from_left: Nat.succ n + m = Nat.succ (n + m) := sorry
sorry
There are some sorry
s that we want to solve automatically with hammer tactics. We can do this by drafting. Feeding this into the drafting feature produces one goal state (corresponding to the one compilation unit) containing as many goals as the draft has sorry
s:
from pantograph import Server
sketch = """
theorem add_comm_proved_formal_sketch : ∀ n m : Nat, n + m = m + n := by
-- Consider some n and m in Nats.
intros n m
-- Perform induction on n.
induction n with
| zero =>
-- Base case: When n = 0, we need to show 0 + m = m + 0.
-- We have the fact 0 + m = m by the definition of addition.
have h_base: 0 + m = m := sorry
-- We also have the fact m + 0 = m by the definition of addition.
have h_symm: m + 0 = m := sorry
-- Combine facts to close goal
sorry
| succ n ih =>
-- Inductive step: Assume n + m = m + n, we need to show succ n + m = m + succ n.
-- By the inductive hypothesis, we have n + m = m + n.
have h_inductive: n + m = m + n := sorry
-- 1. Note we start with: Nat.succ n + m = m + Nat.succ n, so, pull the succ out from m + Nat.succ n on the right side from the addition using addition facts Nat.add_succ.
have h_pull_succ_out_from_right: m + Nat.succ n = Nat.succ (m + n) := sorry
-- 2. then to flip m + S n to something like S (n + m) we need to use the IH.
have h_flip_n_plus_m: Nat.succ (n + m) = Nat.succ (m + n) := sorry
-- 3. Now the n & m are on the correct sides Nat.succ n + m = Nat.succ (n + m), so let's use the def of addition to pull out the succ from the addition on the left using Nat.succ_add.
have h_pull_succ_out_from_left: Nat.succ n + m = Nat.succ (n + m) := sorry
-- Combine facts to close goal
sorry
"""
server = Server()
unit, = server.load_sorry(sketch)
print(unit.goal_state)
m : Nat
⊢ 0 + m = m
m : Nat
h_base : 0 + m = m
⊢ m + 0 = m
m : Nat
h_base : 0 + m = m
h_symm : m + 0 = m
⊢ 0 + m = m + 0
m : Nat
n : Nat
ih : n + m = m + n
⊢ n + m = m + n
m : Nat
n : Nat
ih : n + m = m + n
h_inductive : n + m = m + n
⊢ m + n.succ = (m + n).succ
m : Nat
n : Nat
ih : n + m = m + n
h_inductive : n + m = m + n
h_pull_succ_out_from_right : m + n.succ = (m + n).succ
⊢ (n + m).succ = (m + n).succ
m : Nat
n : Nat
ih : n + m = m + n
h_inductive : n + m = m + n
h_pull_succ_out_from_right : m + n.succ = (m + n).succ
h_flip_n_plus_m : (n + m).succ = (m + n).succ
⊢ n.succ + m = (n + m).succ
m : Nat
n : Nat
ih : n + m = m + n
h_inductive : n + m = m + n
h_pull_succ_out_from_right : m + n.succ = (m + n).succ
h_flip_n_plus_m : (n + m).succ = (m + n).succ
h_pull_succ_out_from_left : n.succ + m = (n + m).succ
⊢ n + 1 + m = m + (n + 1)
For an in-depth example, see experiments/dsp
.