Can you prove Excluded Middle is wrong in Coq if I do not import classical logic - logic

I know excluded middle is impossible in the logic of construction. However, I am stuck when I try to show it in Coq.
Theorem em: forall P : Prop, ~P \/ P -> False.
My approach is:
intros P H.
unfold not in H.
intuition.
The system says following:
2 subgoals
P : Prop
H0 : P -> False
______________________________________(1/2)
False
______________________________________(2/2)
False
How should I proceed?
Thanks

What you are trying to construct is not the negation of LEM, which would say "there exists some P such that EM doesn't hold", but the claim that says that no proposition is decidable, which of course leads to a trivial inconsistency:
Axiom not_lem : forall (P : Prop), ~ (P \/ ~ P).
Goal False.
now apply (not_lem True); left.
No need to use the fancy double-negation lemma; as this is obviously inconsistent [imagine it would hold!]
The "classical" negation of LEM is indeed:
Axiom not_lem : exists (P : Prop), ~ (P \/ ~ P).
and it is not provable [otherwise EM wouldn't be admissible], but you can assume it safely; however it won't be of much utility for you.

One cannot refute the law of excluded middle (LEM) in Coq.
Let's suppose you proved your refutation of LEM. We model this kind of situation by postulating it as an axiom:
Axiom not_lem : forall (P : Prop), ~ (P \/ ~ P).
But then we also have a weaker version (double-negated) of LEM:
Lemma not_not_lem (P : Prop) :
~ ~ (P \/ ~ P).
Proof.
intros nlem. apply nlem.
right. intros p. apply nlem.
left. exact p.
Qed.
These two facts together would make Coq's logic inconsistent:
Lemma Coq_would_be_inconsistent :
False.
Proof.
apply (not_not_lem True).
apply not_lem.
Qed.

I'm coming from mathoverflow, but I don't have permission to comment on #Anton Trunov's answer. I think his answer is unjust, or at least incomplete: he hides the following "folklore":
Coq + Impredicative Set + Weak Excluded-middle -> False
This folklore is a variation of the following facts:
proof irrelevance + large elimination -> false
And Coq + Impredicative Set is canonical, soundness, strong normalization, So it is consistent.
Coq + Impredicative Set is the old version of Coq. I think this at least shows that the defense of the LEM based on double negative translation is not that convincing.
If you want to get information about the solutions, you can get it from here https://github.com/FStarLang/FStar/issues/360
On the other hand, you may be interested in the story of how Coq-HoTT+UA went against LEM∞...
=====================================================
Ok, let's have some solutions.
use command-line flag -impredicative-set, or the install old version(<8.0) of coq.
excluded-middle -> proof-irrelevance
proof-irrelevance -> False
Or you can work with standard coq + coq-hott.
install coq-hott
Univalence + Global Excluded-middle (LEM∞) -> False
It is not recommended that you directly click on the code in question without grasping the specific concept.
I skipped a lot about meta-theoretic implementations, such as Univalence not being computable in Coq-HoTT but only in Agda-CuTT, such as the consistency proof for Coq+Impredicative Set/Coq-HoTT.
However, metatheoretical considerations are important. If we just want to get an Anti-LEM model and don't care about metatheory, then we can use "Boolean-valued forcing" in coq to wreak havoc on things that only LEM can introduce, such as "every function about real set is continuous", Dedekind infinite...
But this answer ends there.

Related

How to prove in Coq ~~(P \/ ~P)

I want to prove ~~(P \/ ~P) in Coq, which sounds somehow trivial... However I do not know where to go since there is not any single hypothesis.
I have written the following code which is not working, since it is giving the following exception [ltac_use_default] expected after [tactic] (in [tactic_command]).
Parameter P: Prop.
Section r20.
Lemma regra1: ~~(P \/ ~P).
Proof.
intro.
- cut P.
- cut ~P
Qed.
End r20.
It is little tricky one. Here is one way to prove it.
Parameter P : Prop.
Section r20.
Lemma regra1: ~~(P \/ ~P).
Proof.
unfold not. intros H1.
apply H1. right.
intros H2.
apply H1. left.
exact H2.
Qed.
End r20.

Expanding all definitions in Isabelle lemma

How can I tell Isabelle to expand all my definitions, please, because that way the proof is trivial? Unfortunately there is no default expansion or simplification happens, and basically I get back the original expression as the subgoal.
Example:
theory Test
imports Main
begin
definition b0 :: "nat⇒nat"
where "b0 n ≡ (n mod 2)"
definition b1 :: "nat⇒nat"
where "b1 n ≡ (n div 2)"
lemma "(a::nat)≤3 ∧ (b::nat)≤3 ⟶
2*(b1 a)+(b0 a)+2*(b1 b)+(b0 b) = a+b"
apply auto
oops
end
Respose before oops:
proof (prove)
goal (1 subgoal):
1. a ≤ 3 ⟹
b ≤ 3 ⟹ 2 * b1 a + b0 a + 2 * b1 b + b0 b = a + b
My recommendation: unfolding
There is a special keyword unfolding for unpacking definitions at the start of proofs. For your example this would read:
unfolding b0_def b1_def by simp
I consider unfolding the most elegant way. It also helps while writing the proofs. Internally, this is (mostly?) equivalent to using the unfold-method:
apply (unfold b0_def b1_def) by simp
This will recursively (!) use the set of equalities you supply to rewrite the proof goal. (Due to the recursion, you should rather not supply a set of equalities that could generate cycles...)
Alternative: Using the simplifier
In cases with possible loops, the simplifier might be able to reach a nice unfolding without running into these cycles, maybe by interleaving with other simplifications. In such cases, by (simp add: b0_def b1_def), as you've suggested, is great!
Alternative definition: Maybe it's just an abbreviation (and no definition)?
If you find yourself unfolding a definition in every single instance, you could consider, using abbreviation instead of definition. Then, some Isabelle magic will do the packing/unpacking for you without further hints. abbeviation does only affect how the user communicates with Isabelle. It does not introduce new symbols at the object level, and consequently, there would be no b1_def facts and the like.
abbreviation b0 :: "nat⇒nat"
where "b0 n ≡ (n mod 2)"
Usually not recommended: Building something like an abbreviation using the simplifier
If you (for whatever reason) want to have a defined name at the object level, but unfold it in almost every instance, you can also feed the defining equality directly into the simplifier.
definition b0 :: "nat⇒nat"
where [simp]: "b0 n ≡ (n mod 2)"
(Usually there should be little reason for the last option.)
Yes, I keep forgetting that definitions are not used in simplifications by default.
Adding the definitions explicitly to the simplification rules solves this problem:
lemma "(a::nat)≤3 ∧ (b::nat)≤3 ⟶
2*(b1 a)+(b0 a)+2*(b1 b)+(b0 b) = a+b"
by (simp add: b0_def b1_def)
This way the definitions (b0, b1) are correctly used.

Remove All Double Negations in Coq

I would like to systematically remove all double negations which can appear in my hypotheses and goals. I know that ~~A -> Ais not a part of intuitionist logic, but the course I am taking is classical, so I don't mind.
I am aware that the mentioned axiom can be accessed by Coq.Logic.Classical_Prop.NNPPbut this axiom doesn't help removing double negation from more complex sentences such as say
H : ~ ~ A \/ (B /\ ~ C)
Preferably I would like to be able to apply a Ltac tactic to Hso it would transform into
H1 : A \/ (B /\ ~C).
Any help writing such a tactic or any other suggestions are much appreciated.
You can use the rewrite tactic, because it can rewrite with logical equivalences in logical contexts, i.e. it can do setoid rewriting. First, you'd need the following simple lemma:
From Coq Require Import Classical_Prop.
Lemma NNP_iff_P (P : Prop) : ~~ P <-> P.
Proof. split; [apply NNPP | intuition]. Qed.
Now, you can use NNP_iff_P to achieve what you want:
Section Example.
Context (A B C D : Prop).
Context (H : ~ ~ A \/ (B /\ ~ C)).
Goal ~~ A.
rewrite !NNP_iff_P in *.
Abort.
End Example.
! means "rewrite zero or many times, until no rewrites are possible" and in * means "apply the tactic in the context and to the goal".

Intro rule for "∀r>0" in Isabelle

When I have a goal such as "∀x. P x" in Isabelle, I know that I can write
show "∀x. P x"
proof (rule allI)
However, when the goal is "∀x>0. P x", I cannot do that. Is there a similar rule/method that I can use after proof in order to simplify my goal? I would also be interested in one for the situation where you have a goal of the form "∃x>0. P x".
I'm looking for an Isar proof that uses the proof (rule something) style.
Universal quantifier
To expand on Lars's answer: ∀x>0. P x is just syntactic sugar for ∀x. x > 0 ⟶ P x. As a consequence, if you want to prove a statement like this, you first have to strip away the universal quantifier with allI and then strip away the implication with impI. You can do something like this:
lemma "∀x>0. P x"
proof (rule allI, rule impI)
Or using intro, which is more or less the same as applying rule until it is not possible anymore:
lemma "∀x>0. P x"
proof (intro allI impI)
Or you can use safe, which eagerly applies all introduction rules that are declared as ‘safe’, such as allI and impI:
lemma "∀x>0. P x"
proof safe
In any case, your new proof state is then
proof (state)
goal (1 subgoal):
1. ⋀x. 0 < x ⟹ P x
And you can proceed like this:
lemma "∀x>0. P (x :: nat)"
proof safe
fix x :: nat assume "x > 0"
show "P x"
Note that I added an annotation; I didn't know what type your P has, so I just used nat. When you fix a variable in Isar and the type is not clear from the assumptions, you will get a warning that a new free type variable was introduced, which is not what you want. When you get that warning, you should add a type annotation to the fix like I did above.
Existential quantifier
For an existential quantifier, safe will not work because the intro rule exI is not always safe due to technical reasons. The typical proof pattern for an ∃x>0. P x would be something like:
lemma "∃x>0. P (x :: nat)"
proof -
have "42 > (0 :: nat)" by simp
moreover have "P 42" sorry
ultimately show ?thesis by blast
qed
Or a little more explicitly:
lemma "∃x>0. P (x :: nat)"
proof -
have "42 > 0 ∧ P 42" sorry
thus ?thesis by (rule exI)
qed
In cases when the existential witness (i.e. the 42 in this example) does not depend on any variables that you got out of an obtain command, you can also do it more directly:
lemma "∃x>0. P (x :: nat)"
proof (intro exI conjI)
This leaves you with the goals ?x > 0 and P ?x. Note that the ?x is a schematic variable for which you can put it anything. So you can complete the proof like this:
lemma "∃x>0. P (x :: nat)"
proof (intro exI conjI)
show "42 > (0::nat)" by simp
show "P 42" sorry
qed
As I said, this does not work if your existential witness depends on some variable that you got from obtain due to technical restrictions. In that case, you have to fall back to the other solution I mentioned.
The following works in Isabelle2016-1-RC2:
lemma "∀ x>0. P x"
apply (rule allI)
In general, you can also just use apply rule, which will select the default introduction rule. Same is true for the existential quantifier.

Proofs in coq using MSet

So I am still new to coq and MSets are giving me some issues. Here are two functions to compute whether an element is in a list or set, please let me know if you think the set_contains definition is correct or if there is a better way to do it. Thanks for any help.
Require Import MSets ZArith.
Module mset := MSetAVL.Make Positive_as_OT.
Notation pos_set := mset.t.
Definition set_contains (x : positive) (s : pos_set) :=
mset.mem x s.
Fixpoint list_contains (x : positive) (l : list positive) : bool :=
match l with
| nil => false
| y :: l' =>
if Pos.eqb x y then true
else nodelist_contains x l'
end.
Lemma nodelist_nodeset_contains :
forall x (s : pos_set),
(nodelist_contains x (mset.elements s)) = (nodeset_contains x s).
Proof.
induction s.
destruct list_contains.
destruct set_contains.
auto.
It seems that set_contains evaluates to true at the base case after the destructs and i'm not sure why. Would the set not be mset.empty during that stage of the proof?
I also do not know how to work with the mset.In, I have trouble with the base case of this proof, obviously I have the same problem. I want to eventually state:
Lemma nodelist_containsP :
forall x (l : pos_set),
reflect (mset.In x l) (nodeset_contains x l).
In case anyone is interested here is how I did this proof.
intros.
apply iff_reflect.
unfold nodeset_contains.
symmetry.
apply mset.mem_spec.
Qed.
list_contains and set_contains are functions so it does not make sense to try to destruct them. Coq tries to infer what you meant and guesses that you want to case on the value of an expression starting with list_contains and set_contains respectively.
This is not what you want. What you want is to observe the behaviour of the two functions on the same input. And you can do so by inspecting it.
This should send you in the right direction:
destruct s as [mset mset_isok].
induction mset.
+ unfold set_contains, mset.mem.
simpl.
reflexivity.
+ unfold list_contains, set_contains, mset.mem.
simpl.

Resources