Lean : Proof that \ not p \to (p \ to q) or similar false \to p - theorem-proving

I am new at lean - prover and I am trying to solve the examples on the online tutorial.
I am stuck at this example and I need to prove that "false implies q" or something like that.
My code is :
variables p q : Prop
example : ¬ p → (p → q) :=
assume h : ¬ p,
assume hp : p,
--have hnpq : ¬ p ∨ q, from or.inl h,
have hf : false, from h hp,
--show q, from hf
sorry
I do not think that defining hnpq can help because this proof is part of the (¬ p ∨ q) → (p → q).
In set theory I think that false implies everything.
Any suggestions or thoughts?

Related

The missing De Morgan's law

Coq uses constructive logic, which means that if you try to fill out
De Morgan's laws, you'll end up missing 2.
Namely, you can't prove:
Theorem deMorgan_nand P Q (andPQ : ~(P /\ Q)) : P \/ Q.
Abort.
Theorem deMorgan_nall {A} (P : A -> Prop) (allPa : ~forall a, P a) : exists a, ~P a.
Abort.
This makes sense, because you've have to compute whether it was
the left or right item of the or, which you can't do in general.
Looking at
"Classical Mathematics for a Constructive World"
(https://arxiv.org/pdf/1008.1213.pdf)
has the definitions
Definition orW P Q := ~(~P /\ ~Q).
Definition exW {A} (P : A -> Prop) := ~forall a, ~P a.
similar to De Morgan's law. This suggests an alternative formulation.
Theorem deMorgan_nand P Q (andPQ : ~(P /\ Q)) : orW (~P) (~Q).
hnf; intros nnPQ; destruct nnPQ as [ nnP nnQ ].
apply nnP; clear nnP; hnf; intros p.
apply nnQ; clear nnQ; hnf; intros q.
apply (andPQ (conj p q)).
Qed.
Theorem deMorgan_nall {A} (P : A -> Prop) (allPa : ~forall a, P a) : exW (fun a => ~P a).
Abort.
But, it doesn't work with negating forall. In particular, it gets stuck on
trying to convert ~~P a into P a. So, despite in the nand case
converting ~~P into P, it doesn't seem to work with forall.
You can also show that there is some element of a that has
P a.
Similarly, you could try to show
Theorem deMorgan_nexn {A} (P : A -> Prop) (exPa : ~exists a, ~P a) : ~~forall a, P a.
Abort.
but that gets stuck in that once you have the argument a,
the conclusion is no longer False, so you can't use ~~P -> P.
So, if you can't prove deMorgan_nall, is there any theorem like it?
Or is ~forall a, P a already as simplified as it can get?
More generally, when the conclusion is False, that allows for using
the law of excluded middle (P \/ ~P). Is there any counterpart
to that that works when the proposition takes an argument, that is
P : A -> Prop instead of P : Prop ?
The principle you are looking for is known as double negation shift. It is not valid in intuitionistic logic in general. Despite looking fairly innocuous at first, as its conclusion is a doubly-negated formula, it is actually quite potent. Indeed, DNS is essentially what is needed in order to interpret the axiom of choice through the double-negation translation.
Edit by scubed:
So, that means I have to add an axiom to handle this case. Using the axiom,
Axiom deMorgan_allnn : forall {A} (P : A -> Prop) (allPa : forall a, ~~P a), ~~forall a, P a.
Theorem deMorgan_nall {A} (P : A -> Prop) (allPa : ~forall a, P a) : exW (fun a => ~P a).
hnf; intros ex1; apply deMorgan_allnn in ex1.
apply ex1; clear ex1; hnf; intros all2.
apply (allPa all2).
Qed.

How to prove two statements in propositional logic using LEAN?

Two proofs at the end of chapter 3 in the LEAN tutorial that I still struggle with (and hence prevent me from going further with reading the manual) are the following:
theorem T11 : ¬(p ↔ ¬p) := sorry
for which my attempt to prove the right implication stopped at this point:
theorem T11R : ¬(p → ¬p) :=
begin
assume hyp : p → ¬ p,
cases (em p) with hp hnp,
exact (hyp hp) hp,
exact sorry
end
as obviously I don't know yet how to make use of ¬p. Not sure how to show the left implication either. The other one is this:
theorem T2R : ((p ∨ q) → r) → (p → r) ∧ (q → r) :=
begin
intros porqr, sorry
end
which I'm supposedly using (as the right implication) to show the following:
theorem T2 : ((p ∨ q) → r) ↔ (p → r) ∧ (q → r) :=
begin
have goR : ((p ∨ q) → r) → (p → r) ∧ (q → r), from T2R p q r,
have goL : (p → r) ∧ (q → r) → ((p ∨ q) → r), from T2L p q r,
exact iff.intro (goR) (goL)
end
Here I got the left-side going:
theorem T2L : (p → r) ∧ (q → r) → ((p ∨ q) → r) :=
begin
intros prqr,
assume porq : p ∨ q,
exact or.elim porq prqr.left prqr.right
end
theorem T11R is not true, for example if p is false then p → ¬ p is true.
¬(p ↔ ¬p) is not equivalent to (¬ (p → ¬ p)) ∧ ¬ (¬ p → p); it's equivalent to ¬ ((p → ¬ p) ∧ (¬ p → p)), which is different.
For theorem T2R if you use the split tactic, it will give you two goals, one for each side of the and. You can use the left and right tactics to turn the goal p ∨ q into either p or q. The theorems or.inl and or.inr can be used to prove an or as well.
Here's a proof of T2R
theorem T2R : ((p ∨ q) → r) → (p → r) ∧ (q → r) :=
begin
intros porqr,
split,
{ assume hp : p,
apply porqr,
left,
exact hp },
{ assume hq : q,
apply porqr,
right,
exact hq },
end

How to simplify a proof by induction in Lean?

I'd like to simplify a proof by induction in Lean.
I've defined an inductive type with 3 constructors in Lean and a binary relation on this type. I've included the axioms because Lean wouldn't let me have them as constructors for rel.
inductive Fintype : Type
| a : Fintype
| b : Fintype
| c : Fintype
inductive rel : Fintype → Fintype → Prop
| r1 : rel Fintype.a Fintype.b
| r2 : ∀ p : Prop, (p → rel Fintype.a Fintype.c )
| r3 : ∀ p : Prop, (¬ p → rel Fintype.c Fintype.b)
axiom asymmetry_for_Fintype : ∀ x y : Fintype, rel x y → ¬ rel y x
axiom trivial1 : ¬ rel Fintype.c Fintype.a
axiom trivial2 : ¬ rel Fintype.b Fintype.c
axiom trivial3 : ∀ p : Prop, rel Fintype.a Fintype.c → p
axiom trivial4 : ∀ p : Prop, rel Fintype.c Fintype.b → ¬ p
A goal was to prove the following theorem:
def nw_o_2 (X : Type) (binrel : X → X → Prop) (x y : X) : Prop := ¬ binrel y x
def pw_o_2 (X : Type) (binrel : X → X → Prop )(x y : X) : Prop := ∀ z : X, (binrel z x → binrel z y) ∧ (binrel y z → binrel x z)
theorem simple17: ∀ x y : Fintype, nw_o_2 Fintype rel x y → pw_o_2 Fintype rel x y :=
I've proved it by induction on x, y, and z; the "z" comes from the definition of pw_o_2 above. But the proof is quite long (~136 lines). Is there another way to have a shorter proof?
Note that your first two axioms are really theorems, provable with an empty pattern match. (The constructors of an inductive types are assumed to be surjective.) The periods at the ends of these lines indicates that the declaration is over, that no body is expected. Internally, Lean is recursing on a proof of rel Fintype.c Fintype.a and showing that each case is structurally impossible.
lemma trivial1 : ¬ rel Fintype.c Fintype.a.
lemma trivial2 : ¬ rel Fintype.b Fintype.c.
Your second two axioms are inconsistent, which makes the proof of your theorem easy but uninteresting.
theorem simple17: ∀ x y : Fintype, nw_o_2 Fintype rel x y → pw_o_2 Fintype rel x y :=
false.elim (trivial3 _ (rel.r2 _ trivial))
I'm not sure that you've defined rel in the way you meant to. The second and third constructors are equivalent to just rel Fintype.a Fintype.c and rel Fintype.c Fintype.b respectively.
lemma rel_a_c : rel Fintype.a Fintype.c :=
rel.r2 true trivial
lemma rel_c_b : rel Fintype.c Fintype.b :=
rel.r3 false not_false

coq syntax of theorem implication

I follow this tutorial : https://softwarefoundations.cis.upenn.edu/lf-current/Basics.html
Section 'Proof by Rewritting' :
The code
Theorem plus_id_example : forall n m : nat,
n = m =>
n + n = m + m.
Produces the error :
Syntax error: '.' expected after [vernac:gallina] (in [vernac_aux]).
I don't get what am I doing wrong ?
Also, what is the best place to get documentation ? I mean, beginner-friendly documentation.
To use the text as it's written on the page you linked, you need to import some notations. In particular, ∀ and → don't exist by default. To import these notations use Require Import Utf8.
Require Import Utf8.
Theorem plus_id_example : ∀n m:nat,
n = m →
n + n = m + m.
The ASCII equivalents of these notations are forall for ∀ (as you figured out) and -> for →. If you have the notations imported, you can see what they stand for using Locate. Locate "→". will have output
Notation
"x → y" := forall _ : x, y : type_scope
(default interpretation)
Of course, this doesn't give us ->, since -> is itself a notation for the same thing. Coq will display that notation by default, so if you input
Theorem plus_id_example : forall n m : nat,
forall _ : n = m,
n + n = m + m.
(without Utf8 imported), the output is
1 subgoal
______________________________________(1/1)
forall n m : nat, n = m -> n + n = m + m
which uses the -> notation.

Abstracting over the term ... leads to a term ... which is ill-typed

Here is what I am trying to prove:
A : Type
i : nat
index_f : nat → nat
n : nat
ip : n < i
partial_index_f : nat → option nat
L : partial_index_f (index_f n) ≡ Some n
V : ∀ i0 : nat, i0 < i → option A
l : ∀ z : nat, partial_index_f (index_f n) ≡ Some z → z < i
============================
V n ip
≡ match
partial_index_f (index_f n) as fn
return (partial_index_f (index_f n) ≡ fn → option A)
with
| Some z => λ p : partial_index_f (index_f n) ≡ Some z, V z (l z p)
| None => λ _ : partial_index_f (index_f n) ≡ None, None
end eq_refl
The obvious next step is either rewrite L or destruct (partial_index_f (index_f n). Trying to applying rewrite gives me an error:
Error: Abstracting over the term "partial_index_f (index_f n)"
leads to a term
"λ o : option nat,
V n ip
≡ match o as fn return (o ≡ fn → option A) with
| Some z => λ p : o ≡ Some z, V z (l z p)
| None => λ _ : o ≡ None, None
end eq_refl" which is ill-typed.
I do not understand what is causing this problem. I also would like to understand how I can deal with it in general.
I was able to prove it using the following steps, but I am not sure this is the best way:
destruct (partial_index_f (index_f n)).
inversion L.
generalize (l n0 eq_refl).
intros. subst n0.
replace l0 with ip by apply proof_irrelevance.
reflexivity.
congruence.
In Coq's theory, when you perform a rewrite with an equation, you have to generalize over the side of the equation that you want to replace. In your case, you want to replace partial_index_f (index_f n), so Coq tries to generalize that, as you can tell from the error message you got.
Now, if your goal contains something whose type mentions the thing that you want to replace, you might run into trouble, because this generalization might make the goal become ill-typed. (Notice that that type does not exactly occur in the goal, hence Coq does not try to deal with it like it does when something occurs in the goal.) Going back to your case, your l function has type ∀ z : nat, partial_index_f (index_f n) ≡ Some z → z < i, which mentions partial_index_f (index_f n), the term you want to replace. In the first branch of your match, you apply this function to the o = Some z hypothesis that you abstracted over. On the original goal, o was the thing you wanted to replace, but when Coq tries to generalize, the two do not match anymore, hence the error message.
I can't try to fix the problem on my own, but you can solve issues like this usually by generalizing over the term in your context that mentions the term you are replacing, because then its type will show in the goal, associated to a universally quantified variable. This might not help if your term is defined globally and you need it to have a certain shape after the rewrite in order to be able to perform additional reasoning steps, in which case you will probably have to generalize over the lemmas that you need as well.