Skip to content

Instantly share code, notes, and snippets.

@benediktahrens
Created January 29, 2020 01:15
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save benediktahrens/a52dc0137db2e845bb96b5f67645bad7 to your computer and use it in GitHub Desktop.
Save benediktahrens/a52dc0137db2e845bb96b5f67645bad7 to your computer and use it in GitHub Desktop.
------------------------------
----REMINDER------------------
------------------------------
/-
Last week we saw
1. intro and elim rules in Lean
2. first proofs in Lean
In particular, we saw how
implication introduction works
Today, we learn more features
of Lean.
Having understood the previous
lecture is crucial - watch it
again if necessary, and type
the code yourself.
-/
------------------------------
----DOING WITHOUT VARIABLES---
------------------------------
/-
Instead of assuming "global"
variables for the propositions
we discuss, using
variables A B C D : Prop
, we can turn these
propositions into parameters
of each example:
-/
example (A : Prop) : A → A :=
sorry
--assume a : A, a
------------------------------
--SAVING PROOFS FOR REUSE-----
------------------------------
/-
We can give names to proofs
of propositions, and refer
to these proofs later on.
-/
theorem and_commute (A B : Prop) :
A ∧ B → B ∧ A :=
sorry
--assume h : A ∧ B,
-- and.intro
-- (and.elim_right h)
-- (and.elim_left h)
/-
The above proposition is
also the first example where
the antecedent of an implication
is not atomic.
Have you understood how we use
the hypothesis
"h : A ∧ B"
?
-/
/-
We now use "and_commute"
in the proof of another
result.
-/
section use_theorem
variables C D E : Prop
variable h1 : C ∧ ¬ D
variable h2 : ¬ D ∧ C → E
include h1 h2
example : E := sorry
--h2
-- (and_commute C (¬ D) h1)
end use_theorem
/-
In the example above,
Lean can *guess* the parameters
C and ¬ D of "and_commute".
Test:
replace them with underscores!
If we put the parameters of a
theorem in braces instead of
parentheses, we do not need
to specify them later
-/
theorem and_commute_var {A B : Prop} :
A ∧ B → B ∧ A :=
assume h,
and.intro
(and.right h)
(and.left h)
section use_theorem
variables C D E : Prop
variable h1 : C ∧ ¬ D
variable h2 : ¬ D ∧ C → E
include h1 h2
example : E := sorry
--h2 (and_commute_var h1)
end use_theorem
------------------------------
--EXAMPLE WITH OR ELIMINATION-
------------------------------
/-
OR-elim looks a bit tricky at
first.
In Lean, it is actually quite
easy:
-/
#check or.elim
--this shows that or.elim
--takes 3 arguments:
--the first is a proof of
--P ∨ Q for some P, Q;
--the second and third
--are implications
--Lean calls these propositions
--by strange names.
--We simply start by
--using "or.elim h _ _"
--where h : P ∨ Q
example (A B C D : Prop) :
A ∨ B → (A → C) →
(B → D) → C ∨ D :=
sorry
/-
assume h : A ∨ B,
assume f : A → C,
assume g : B → D,
or.elim h
(assume a : A , or.intro_left D (f a))
(assume b : B, or.intro_right C (g b))
-/
------------------------------
----FORWARD REASONING IN LEAN-
------------------------------
--Example
section forward
example (A B C : Prop) :
(A → B) → (B → C) → (A → C) :=
sorry
/-
assume f : A → B,
assume g : B → C,
assume a : A,
have b : B, from f a,
show C, from g b
-/
end forward
/-
Writing a proof with
"have h : A, from P,
... h ... "
is the same as writing
"... P ...."
Advantages of "have":
1. more readable
2. can use "h" multiple times,
hence avoid repetition
3. makes proofs more modular
and results in readable
messages from Lean
Use of "have" is entirely
optional: any proposition that
can be proved with "have"
can also be proved without
using "have"
-/
example (A B : Prop) :
A ∧ B → B ∧ A :=
sorry
--assume h1 : A ∧ B,
--have a : A, from and.left h1,
--have b : B, from and.right h1,
--and.intro b a
------------------------------
--CLASSICAL REASONING IN LEAN-
------------------------------
/-
In Lean, access to the rule
¬ ¬ A
-------
A
requires importing a special
library called "classical"
-/
--First we prove a result
--that we want to use later
theorem Not_Or {A B : Prop} :
¬ (A ∨ B) → (¬ A ∧ ¬ B) :=
sorry
/-
assume f : ¬ (A ∨ B),
and.intro
(assume a : A,
f (or.intro_left _ a))
(assume b : B,
f (or.intro_right _ b))
-/
open classical
example (A : Prop) : ¬ ¬ A → A :=
assume nna : ¬ ¬ A,
by_contradiction nna
theorem Not_And {A B : Prop} :
¬ (A ∧ B) → ¬ A ∨ ¬ B :=
sorry
/-
assume h : ¬ (A ∧ B),
by_contradiction
(assume w : ¬(¬A ∨ ¬B) ,
have k : ¬ ¬ A ∧ ¬ ¬ B, from Not_Or w ,
h (and.intro (by_contradiction k.left)
(by_contradiction k.right))
)
-/
theorem Excluded_Middle (A : Prop) :
A ∨ ¬ A :=
sorry
/-
by_contradiction
(assume nor : ¬ (A ∨ ¬ A),
have foo : ¬ A ∧ ¬ ¬ A,
from Not_Or (assume k : A ∨ ¬ A , nor k),
foo.right foo.left
)
-/
------------------------------
--SHOWING MORE INFORMATION----
------------------------------
/-
Looking back at last example,
we might want to spell out the
result of some intermediate
expressions, e.g.,
-/
example (A B : Prop) :
A ∧ B → B ∧ A :=
assume h1 : A ∧ B,
have h2 : A, from and.left h1,
have h3 : B, from and.right h1,
show B ∧ A, from and.intro h3 h2
/-
Schematically, we replaced
some expression "p" above,
where p : P,
by
"show P, from p"
Technically, these are
entirely equivalent.
Advantages of "show":
1. better error messages from
Lean
2. better readability for us
-/
--We can be more extreme:
example (A B : Prop) :
A ∧ B → B ∧ A :=
assume h1 : A ∧ B,
have a : A, from and.left h1,
have b : B, from and.right h1,
show B ∧ A, from
and.intro
(show B, from b)
(show A, from a)
------------------------------
--BI-IMPLICATION--------------
------------------------------
/-
When A → B and B → A, then we
call A and B "equivalent".
Intuitively, they are equally
"strong" as propositions.
Bi-implication expresses this
concept. Bi-implication could
be *defined*, just like negation,
in terms of the other logical
connectives:
A ↔ B = (A → B) ∧ (B → A)
In Lean, bi-implication is
however a primitive concept,
implemented through introduction
and elimination rules.
The introduction rule is
A → B B → A
---------------
A ↔ B
as one might expect. Similarly,
we get two elimination rules:
A ↔ B
-------
A → B
and
A ↔ B
-------
B → A
See the Lean code below.
-/
section bi_impl
variables A B : Prop
variable f : A → B
variable g : B → A
#check iff.intro f g
variable h : A ↔ B
#check iff.elim_left h
#check iff.elim_right h
end bi_impl
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment