feat(builtin/macros): add assume/take macros for making proof scripts more readable

Signed-off-by: Leonardo de Moura <leonardo@microsoft.com>
This commit is contained in:
Leonardo de Moura 2014-01-11 18:36:37 -08:00
parent 781720a26a
commit 6508e63a17
8 changed files with 88 additions and 62 deletions

View file

@ -1,7 +1,7 @@
import macros.
theorem simple (p q r : Bool) : (p → q) ∧ (q → r) → p → r
:= λ H_pq_qr H_p,
:= assume H_pq_qr H_p,
let P_pq := and_eliml H_pq_qr,
P_qr := and_elimr H_pq_qr
in P_qr (P_pq H_p)
@ -10,7 +10,7 @@ set_option pp::implicit true.
print environment 1.
theorem simple2 (a b c : Bool) : (a → b → c) → (a → b) → a → c
:= λ H_abc H_ab H_a,
:= assume H_abc H_ab H_a,
(H_abc H_a) (H_ab H_a)
print environment 1.

View file

@ -1,10 +1,10 @@
import macros.
theorem my_and_comm (a b : Bool) : (a ∧ b) → (b ∧ a)
:= λ H_ab, and_intro (and_elimr H_ab) (and_eliml H_ab).
:= assume H_ab, and_intro (and_elimr H_ab) (and_eliml H_ab).
theorem my_or_comm (a b : Bool) : (a b) → (b a)
:= λ H_ab,
:= assume H_ab,
or_elim H_ab
(λ H_a, or_intror b H_a)
(λ H_b, or_introl H_b a).
@ -21,8 +21,8 @@ theorem my_or_comm (a b : Bool) : (a b) → (b a)
-- produces
-- a
theorem pierce (a b : Bool) : ((a → b) → a) → a
:= λ H, or_elim (em a)
(λ H_a, H_a)
(λ H_na, not_imp_eliml (mt H H_na)).
:= assume H, or_elim (em a)
(λ H_a, H_a)
(λ H_na, not_imp_eliml (mt H H_na)).
print environment 3.

View file

@ -8,7 +8,8 @@ scope
(Linked : ∀ x, ∃ y, R x y)
:
∀ x, R x x :=
λ x, obtain (w : A) (H : R x w), from (Linked x),
take x,
obtain (w : A) (H : R x w), from (Linked x),
let L1 : R w x := Symm x w H
in Trans x w x H L1

View file

@ -9,16 +9,17 @@ definition subset {A : Type} (s1 : Set A) (s2 : Set A) := ∀ x, x ∈ s1 → x
infix 50 ⊆ : subset
theorem subset_trans {A : Type} {s1 s2 s3 : Set A} (H1 : s1 ⊆ s2) (H2 : s2 ⊆ s3) : s1 ⊆ s3
:= λ (x : A) (Hin : x ∈ s1),
have x ∈ s3 :
let L1 : x ∈ s2 := H1 x Hin
in H2 x L1
:= take x : A,
assume Hin : x ∈ s1,
have x ∈ s3 :
let L1 : x ∈ s2 := H1 x Hin
in H2 x L1
theorem subset_ext {A : Type} {s1 s2 : Set A} (H : ∀ x, x ∈ s1 = x ∈ s2) : s1 = s2
:= funext H
theorem subset_antisym {A : Type} {s1 s2 : Set A} (H1 : s1 ⊆ s2) (H2 : s2 ⊆ s1) : s1 = s2
:= subset_ext (have (∀ x, x ∈ s1 = x ∈ s2) :
λ x, have x ∈ s1 = x ∈ s2 :
take x, have x ∈ s1 = x ∈ s2 :
boolext (have x ∈ s1 → x ∈ s2 : H1 x)
(have x ∈ s2 → x ∈ s1 : H2 x))

View file

@ -323,7 +323,7 @@ theorem ne_lt_succ {a b : Nat} (H1 : a ≠ b) (H2 : a < b + 1) : a < b
... = b : L))
theorem strong_induction {P : Nat → Bool} (H : ∀ n, (∀ m, m < n → P m) → P n) : ∀ a, P a
:= λ a,
:= take a,
let stronger : P a ∧ ∀ m, m < a → P m :=
-- we prove a stronger result by regular induction on a
induction_on a

View file

@ -46,7 +46,7 @@ definition neq {A : TypeU} (a b : A) := ¬ (a == b)
infix 50 ≠ : neq
theorem em (a : Bool) : a ¬ a
:= λ Hna : ¬ a, Hna
:= assume Hna : ¬ a, Hna
axiom case (P : Bool → Bool) (H1 : P true) (H2 : P false) (a : Bool) : P a
@ -90,13 +90,13 @@ theorem false_elim (a : Bool) (H : false) : a
:= case (λ x, x) trivial H a
theorem imp_trans {a b c : Bool} (H1 : a → b) (H2 : b → c) : a → c
:= λ Ha, H2 (H1 Ha)
:= assume Ha, H2 (H1 Ha)
theorem imp_eq_trans {a b c : Bool} (H1 : a → b) (H2 : b == c) : a → c
:= λ Ha, H2 ◂ (H1 Ha)
:= assume Ha, H2 ◂ (H1 Ha)
theorem eq_imp_trans {a b c : Bool} (H1 : a == b) (H2 : b → c) : a → c
:= λ Ha, H2 (H1 ◂ Ha)
:= assume Ha, H2 (H1 ◂ Ha)
theorem not_not_eq (a : Bool) : (¬ ¬ a) == a
:= case (λ x, (¬ ¬ x) == x) trivial trivial a
@ -105,10 +105,10 @@ theorem not_not_elim {a : Bool} (H : ¬ ¬ a) : a
:= (not_not_eq a) ◂ H
theorem mt {a b : Bool} (H1 : a → b) (H2 : ¬ b) : ¬ a
:= λ Ha, absurd (H1 Ha) H2
:= assume Ha : a, absurd (H1 Ha) H2
theorem contrapos {a b : Bool} (H : a → b) : ¬ b → ¬ a
:= λ Hnb : ¬ b, mt H Hnb
:= assume Hnb : ¬ b, mt H Hnb
theorem absurd_elim {a : Bool} (b : Bool) (H1 : a) (H2 : ¬ a) : b
:= false_elim b (absurd H1 H2)
@ -116,19 +116,19 @@ theorem absurd_elim {a : Bool} (b : Bool) (H1 : a) (H2 : ¬ a) : b
theorem not_imp_eliml {a b : Bool} (Hnab : ¬ (a → b)) : a
:= not_not_elim
(have ¬ ¬ a :
λ Hna : ¬ a, absurd (λ Ha : a, absurd_elim b Ha Hna)
Hnab)
assume Hna : ¬ a, absurd (assume Ha : a, absurd_elim b Ha Hna)
Hnab)
theorem not_imp_elimr {a b : Bool} (H : ¬ (a → b)) : ¬ b
:= λ Hb : b, absurd (λ Ha : a, Hb)
H
:= assume Hb : b, absurd (assume Ha : a, Hb)
H
theorem resolve1 {a b : Bool} (H1 : a b) (H2 : ¬ a) : b
:= H1 H2
-- Recall that and is defined as ¬ (a → ¬ b)
theorem and_intro {a b : Bool} (H1 : a) (H2 : b) : a ∧ b
:= λ H : a → ¬ b, absurd H2 (H H1)
:= assume H : a → ¬ b, absurd H2 (H H1)
theorem and_eliml {a b : Bool} (H : a ∧ b) : a
:= not_imp_eliml H
@ -138,15 +138,15 @@ theorem and_elimr {a b : Bool} (H : a ∧ b) : b
-- Recall that or is defined as ¬ a → b
theorem or_introl {a : Bool} (H : a) (b : Bool) : a b
:= λ H1 : ¬ a, absurd_elim b H H1
:= assume H1 : ¬ a, absurd_elim b H H1
theorem or_intror {b : Bool} (a : Bool) (H : b) : a b
:= λ H1 : ¬ a, H
:= assume H1 : ¬ a, H
theorem or_elim {a b c : Bool} (H1 : a b) (H2 : a → c) (H3 : b → c) : c
:= not_not_elim
(λ H : ¬ c,
absurd (have c : H3 (have b : resolve1 H1 (have ¬ a : (mt (λ Ha : a, H2 Ha) H))))
(assume H : ¬ c,
absurd (have c : H3 (have b : resolve1 H1 (have ¬ a : (mt (assume Ha : a, H2 Ha) H))))
H)
theorem refute {a : Bool} (H : ¬ a → false) : a
@ -161,7 +161,7 @@ theorem trans {A : TypeU} {a b c : A} (H1 : a == b) (H2 : b == c) : a == c
infixl 100 ⋈ : trans
theorem ne_symm {A : TypeU} {a b : A} (H : a ≠ b) : b ≠ a
:= λ H1 : b = a, H (symm H1)
:= assume H1 : b = a, H (symm H1)
theorem eq_ne_trans {A : TypeU} {a b c : A} (H1 : a = b) (H2 : b ≠ c) : a ≠ c
:= subst H2 (symm H1)
@ -187,11 +187,11 @@ theorem congr {A : TypeU} {B : A → TypeU} {f g : ∀ x : A, B x} {a b : A} (H1
-- Recall that exists is defined as ¬ ∀ x : A, ¬ P x
theorem exists_elim {A : TypeU} {P : A → Bool} {B : Bool} (H1 : Exists A P) (H2 : ∀ (a : A) (H : P a), B) : B
:= refute (λ R : ¬ B,
absurd (λ a : A, mt (λ H : P a, H2 a H) R)
absurd (take a : A, mt (assume H : P a, H2 a H) R)
H1)
theorem exists_intro {A : TypeU} {P : A → Bool} (a : A) (H : P a) : Exists A P
:= λ H1 : (∀ x : A, ¬ P x),
:= assume H1 : (∀ x : A, ¬ P x),
absurd H (H1 a)
theorem boolext {a b : Bool} (Hab : a → b) (Hba : b → a) : a == b
@ -207,34 +207,34 @@ theorem iff_intro {a b : Bool} (Hab : a → b) (Hba : b → a) : a == b
:= boolext Hab Hba
theorem eqt_intro {a : Bool} (H : a) : a == true
:= boolext (λ H1 : a, trivial)
(λ H2 : true, H)
:= boolext (assume H1 : a, trivial)
(assume H2 : true, H)
theorem eqf_intro {a : Bool} (H : ¬ a) : a == false
:= boolext (λ H1 : a, absurd H1 H)
(λ H2 : false, false_elim a H2)
:= boolext (assume H1 : a, absurd H1 H)
(assume H2 : false, false_elim a H2)
theorem or_comm (a b : Bool) : (a b) == (b a)
:= boolext (λ H, or_elim H (λ H1, or_intror b H1) (λ H2, or_introl H2 a))
(λ H, or_elim H (λ H1, or_intror a H1) (λ H2, or_introl H2 b))
:= boolext (assume H, or_elim H (λ H1, or_intror b H1) (λ H2, or_introl H2 a))
(assume H, or_elim H (λ H1, or_intror a H1) (λ H2, or_introl H2 b))
theorem or_assoc (a b c : Bool) : ((a b) c) == (a (b c))
:= boolext (λ H : (a b) c,
:= boolext (assume H : (a b) c,
or_elim H (λ H1 : a b, or_elim H1 (λ Ha : a, or_introl Ha (b c))
(λ Hb : b, or_intror a (or_introl Hb c)))
(λ Hc : c, or_intror a (or_intror b Hc)))
(λ H : a (b c),
(assume H : a (b c),
or_elim H (λ Ha : a, (or_introl (or_introl Ha b) c))
(λ H1 : b c, or_elim H1 (λ Hb : b, or_introl (or_intror a Hb) c)
(λ Hc : c, or_intror (a b) Hc)))
theorem or_id (a : Bool) : (a a) == a
:= boolext (λ H, or_elim H (λ H1, H1) (λ H2, H2))
(λ H, or_introl H a)
:= boolext (assume H, or_elim H (λ H1, H1) (λ H2, H2))
(assume H, or_introl H a)
theorem or_falsel (a : Bool) : (a false) == a
:= boolext (λ H, or_elim H (λ H1, H1) (λ H2, false_elim a H2))
(λ H, or_introl H false)
:= boolext (assume H, or_elim H (λ H1, H1) (λ H2, false_elim a H2))
(assume H, or_introl H false)
theorem or_falser (a : Bool) : (false a) == a
:= (or_comm false a) ⋈ (or_falsel a)
@ -249,34 +249,34 @@ theorem or_tauto (a : Bool) : (a ¬ a) == true
:= eqt_intro (em a)
theorem and_comm (a b : Bool) : (a ∧ b) == (b ∧ a)
:= boolext (λ H, and_intro (and_elimr H) (and_eliml H))
(λ H, and_intro (and_elimr H) (and_eliml H))
:= boolext (assume H, and_intro (and_elimr H) (and_eliml H))
(assume H, and_intro (and_elimr H) (and_eliml H))
theorem and_id (a : Bool) : (a ∧ a) == a
:= boolext (λ H, and_eliml H)
(λ H, and_intro H H)
:= boolext (assume H, and_eliml H)
(assume H, and_intro H H)
theorem and_assoc (a b c : Bool) : ((a ∧ b) ∧ c) == (a ∧ (b ∧ c))
:= boolext (λ H, and_intro (and_eliml (and_eliml H)) (and_intro (and_elimr (and_eliml H)) (and_elimr H)))
(λ H, and_intro (and_intro (and_eliml H) (and_eliml (and_elimr H))) (and_elimr (and_elimr H)))
:= boolext (assume H, and_intro (and_eliml (and_eliml H)) (and_intro (and_elimr (and_eliml H)) (and_elimr H)))
(assume H, and_intro (and_intro (and_eliml H) (and_eliml (and_elimr H))) (and_elimr (and_elimr H)))
theorem and_truer (a : Bool) : (a ∧ true) == a
:= boolext (λ H : a ∧ true, and_eliml H)
(λ H : a, and_intro H trivial)
:= boolext (assume H : a ∧ true, and_eliml H)
(assume H : a, and_intro H trivial)
theorem and_truel (a : Bool) : (true ∧ a) == a
:= trans (and_comm true a) (and_truer a)
theorem and_falsel (a : Bool) : (a ∧ false) == false
:= boolext (λ H, and_elimr H)
(λ H, false_elim (a ∧ false) H)
:= boolext (assume H, and_elimr H)
(assume H, false_elim (a ∧ false) H)
theorem and_falser (a : Bool) : (false ∧ a) == false
:= (and_comm false a) ⋈ (and_falsel a)
theorem and_absurd (a : Bool) : (a ∧ ¬ a) == false
:= boolext (λ H, absurd (and_eliml H) (and_elimr H))
(λ H, false_elim (a ∧ ¬ a) H)
:= boolext (assume H, absurd (and_eliml H) (and_elimr H))
(assume H, false_elim (a ∧ ¬ a) H)
theorem imp_truer (a : Bool) : (a → true) == true
:= case (λ x, (x → true) == true) trivial trivial a
@ -362,16 +362,16 @@ theorem exists_unfold2 {A : TypeU} {P : A → Bool} (a : A) (H : P a (∃ x
exists_intro w (and_elimr Hw)))
theorem exists_unfold {A : TypeU} (P : A → Bool) (a : A) : (∃ x : A, P x) = (P a (∃ x : A, x ≠ a ∧ P x))
:= boolext (λ H : (∃ x : A, P x), exists_unfold1 a H)
(λ H : (P a (∃ x : A, x ≠ a ∧ P x)), exists_unfold2 a H)
:= boolext (assume H : (∃ x : A, P x), exists_unfold1 a H)
(assume H : (P a (∃ x : A, x ≠ a ∧ P x)), exists_unfold2 a H)
-- Remark: ordered rewriting + assoc + comm + left_comm sorts a term lexicographically
theorem left_comm {A : TypeU} {R : A -> A -> A} (comm : ∀ x y, R x y = R y x) (assoc : ∀ x y z, R (R x y) z = R x (R y z)) :
∀ x y z, R x (R y z) = R y (R x z)
:= λ x y z, calc R x (R y z) = R (R x y) z : symm (assoc x y z)
... = R (R y x) z : { comm x y }
... = R y (R x z) : assoc y x z
:= take x y z, calc R x (R y z) = R (R x y) z : symm (assoc x y z)
... = R (R y x) z : { comm x y }
... = R y (R x z) : assoc y x z
theorem and_left_comm (a b c : Bool) : (a ∧ (b ∧ c)) = (b ∧ (a ∧ c))
:= left_comm and_comm and_assoc a b c

View file

@ -116,3 +116,27 @@ macro("obtain", { macro_arg.Parameters, macro_arg.Comma, macro_arg.Id, macro_arg
fun(a_name, a_type, fun(H_name, H_type, body)))
end,
0)
function mk_lambdas(bindings, body)
local r = body
for i = #bindings, 1, -1 do
r = fun(bindings[i][1], bindings[i][2], r)
end
return r
end
-- Allow (assume x : A, B) to be used instead of (fun x : A, B).
-- It can be used to make scripts more readable, when (fun x : A, B) is being used to encode a discharge
macro("assume", { macro_arg.Parameters, macro_arg.Comma, macro_arg.Expr},
function (env, bindings, body)
return mk_lambdas(bindings, body)
end,
0)
-- Allow (assume x : A, B) to be used instead of (fun x : A, B).
-- It can be used to make scripts more readable, when (fun x : A, B) is being used to encode a forall_intro
macro("take", { macro_arg.Parameters, macro_arg.Comma, macro_arg.Expr},
function (env, bindings, body)
return mk_lambdas(bindings, body)
end,
0)

View file

@ -26,7 +26,7 @@
'("--") ;; comments start with
'("import" "definition" "variable" "variables" "print" "theorem" "axiom" "universe" "alias" "help" "environment" "options" "infix" "infixl" "infixr" "notation" "eval" "check" "exit" "coercion" "end" "using" "namespace" "builtin" "scope" "pop_scope" "set_opaque" "set_option") ;; some keywords
'(("\\_<\\(Bool\\|Int\\|Nat\\|Real\\|Type\\|TypeU\\|\\|\\)\\_>" . 'font-lock-type-face)
("\\_<\\(calc\\|have\\|in\\|let\\|forall\\|exists\\|if\\|then\\|else\\)\\_>" . font-lock-keyword-face)
("\\_<\\(calc\\|have\\|in\\|let\\|forall\\|exists\\|if\\|then\\|else\\|assume\\|take\\|obtain\\|from\\)\\_>" . font-lock-keyword-face)
("\"[^\"]*\"" . 'font-lock-string-face)
("\\(->\\|/\\\\\\|==\\|\\\\/\\|[*+/<=>¬∧∨≠≤≥-]\\)" . 'font-lock-constant-face)
("\\\\|→\\|∃\\|∀\\|:\\|:=\\)" . font-lock-constant-face)