I want to prove the following logic equivalence in Coq.
(p->q)->(~q->~p)
Here is what I attempted. How can I fix this?
Lemma work : (forall p q : Prop, (p->q)->(~q->~p)).
Proof.
intros p q.
intros p_implies_q not_q_implies_not_p.
refine (not_q_implies_not_p).
refine (p_implies_q).
Qed.
Two things that might help.
First, in your second intros, the second hypothesis is not not_q_implies_not_p, but rather, simply not_q. This is because the goal is (after intros p_implies_q) ~q -> ~p, so another invocation of intros only brings in the hypothesis of this goal: ~q, and leaves ~p as the new goal.
Second, remember that ~p simply means p -> False, which allows us to introduce another hypothesis from the goal of ~p. This also means that you can use a premise like ~p to prove False, assuming you know that p is true.
So your proof should start out something like
Lemma work : (forall p q : Prop, (p->q)->(~q->~p)).
Proof.
intros p q.
intros p_implies_q not_q.
intros p_true.
Related
I have the following proof state:
1. ⋀i is s stk stack.
(⋀stack.
length (exec is s stack) = n' ⟹
length stack = n ⟹ ok n is n') ⟹
length (exec (i # is) s stack) = n' ⟹
length stack = n ⟹ ok n (i # is) n'
How do I perform a case split on i? Where i is of type:
datatype instr = LOADI val | LOAD vname | ADD
I'm doing this for exc 4.7 of concrete semantics so this should be possible to do with tactics.
If anything you should use cases i rule: instr.cases, but that will not work here because i is not a fixed variable but a bound variable. Also, the rule: instr.cases is not really needed because Isabelle will use that rule by default anyway.
Doing a case distinction on a bound variable without fixing it first is kind of discouraged; that said, it can be done by doing apply (case_tac i) instead of apply (cases i). But as I said, this is not the nice way to do it.
A more proper way to do it is to explicitly fix i using e.g. the subgoal command:
subgoal for i is s stk stack
apply (cases i)
An even better way would probably be to use a structured Isar proof instead.
However, I don't think the subgoal command or Isar proofs are something that you know about at this stage of the Concrete Semantics book, so my guess would be that there is a nicer way to do the proof where you don't have to do any manual case splitting.
Most probably you are doing an induction on the list of instructions; it would probably be better to do an induction on the predicate ok instead. But then again: Where is that predicate ok? I don't see it in your assumptions. It's hard to say what's going on there without knowing how you defined ok and what lemma you are trying to prove exactly and what tactics you applied already.
I'm using Isabelle/HOL, trying to prove a statement Q. On the way to proving Q, I have proven the existence of a natural number that satisfies P::"nat=>bool". How can I create an instance x::nat that satisfies P, so that I can reference it in subsequent lemmas?
Inside any given lemma, I can do it using the obtains command. I want to reference the same witness instance in a number of different lemmas, however, so I need a way to do it outside of any lemma. I tried to use fix/assume inside a new locale, as shown below:
locale outerlocale
fixes a b c ...
begin
definition Q::bool where ...
lemma existence: "EX x. P x"
proof -
...
qed
locale innerlocale = outerlocale +
fixes x::nat
assumes "P x"
begin
(*lots of lemmas that reference x*)
lemma innerlemma0
...
lemma innerlemma7
proof -
...
qed
lemma finalinnerlemma: "Q"
proof -
...
...
qed
end (*innerlocale*)
lemma outerlemma: "Q"
proof -
(*I don't know what goes here*)
qed
end (*outerlocale)
Unfortunately this just kicks the can down the road. I need a way to use the existence lemma to extract the final inner lemma into the outer locale. If I try to interpret the inner locale, I'm once again up against the problem of supplying a witness. I can't interpret locales inside lemmas (unless I'm misunderstanding the error I get), and I can't use obtain outside of lemmas, so I'm stuck.
So it looks I need to figure out either
how to specify a witness instance outside a lemma or
how to extract a lemma from a locale by proving that locale's assumptions
Or is there a better way to do what I'm trying to do? Thanks!
You can just use SOME x. P x, e.g., in a definition:
definition my_witness :: nat where
"my_witness = (SOME x. P x)"
and then use thm someI_ex to show P my_witness.
For an example lemma like this:
lemma someFuncLemma: "∀ (e::someType) . pre_someFunc 2 e"
which gives the following when using quickcheck:
Auto Quickcheck found a counterexample:
e = - 1
or when using Nitpick (which isn't really the main point here):
Nitpick found a counterexample:
Skolem constant:
e = - 1
How can I then use this counterexample to finish the proof?
As you can see, I'm not very familiar with Isabelle and POs.
Thank you for your help!
The presence of a counterexample usually indicates that you won't be able to prove your proposition, except maybe
the counterexample is spurious;
the underlying logic is inconsistent.
I'm assuming you want to prove there exists some e such that pre_someFunc 2 e is false. You would have to change your lemma to use exists instead of forall, and prefix your predicate with not:
lemma "∃e::someType. ¬(pre_someFunc 2 e)"
Then you can provide the counter-example using rule exI[where x=...] which sets the free variable x in exI to something. You can look at the definition of exI and how x is used by clicking it while holding Ctrl in Isabelle JEdit.
A simple example:
lemma "∃n :: nat. ¬ odd n"
apply (rule exI[where x=2])
apply simp
done
Quick review:
Inference rule = conclusion + rule + premises
Proof tree = conclusion + rule + sub-trees
Backward proof search: given an input goal, try to build a proof tree by applying inference rules in bottom-up way (for example, the goal is the final conclusion, after applying a rule, it will generate a list of new sub-goals on the premises)
Problem:
Given an input goal (e.g. A AND B,C), assume that we apply the rule AND firstly on A AND B, then get two new sub-goals, the first one is A,C, the second one is B,C.
The problem is that A and B are useless, which means we can build a complete proof tree using only C. However, we have two sub-goals, then we have to prove C two times, so it is really inefficient.
Question:
For example, we have A AND B,C AND D,E AND F,G,H AND I. In this case, we only need D and G to build a complete proof tree. So how to choose the right rules to apply?
This is an example code in Ocaml:
(* conclusion -> tree *)
let rec prove goal = (* the function builds a proof tree from an input goal *)
let rule = get_rule goal in (* get the first rule *)
let sub-goals = apply_rule goal in (* apply a rule *)
let sub-trees = List.map (fun g -> prove g) sub-goals in (* prove sub-goals recursively *)
(goal, rule, sub-trees) (* return proof tree *)
If you want the shortest (shallowest) proof, which in this case uses disjunction introduction and avoids conjunction introduction, then you can look at techniques like iterative deepening. For instance you could change your code as follows:
let rec prove n goal =
if n=0 then failwith "No proof found" else
let rule = get_rule goal in
let sub-goals = apply_rule goal in
let sub-trees = List.map (fun g -> prove (n-1) g) sub-goals in
(goal, rule, sub-trees)
let idfs maxn goal =
let rec aux n =
if n > maxn then None else
try
Some (prove n goal)
with Failure _ -> aux (n+1) in
aux 1
If you want to avoid re-doing the proof for a sub-goal that has already appeared, then you can use some form of memoization (a narrow form of lemma speculation/application really). See for instance the answers to this question, especially the second answer since prove is naturally recursive.
These suggestions do not touch the subject of how you pick the rules to apply, that is how exactly get_rule is coded. In practice, many options will be available and you would want to iterate through them.
In Isabelle, one occasionally reaches a scenario where there are duplicate subgoals. For example, imagine the following proof script:
lemma "a ∧ a"
apply (rule conjI)
with goals:
proof (prove): step 1
goal (2 subgoals):
1. a
2. a
Is there any way to eliminate the duplicate subgoal in-place, so proofs need not be repeated?
The ML-level tactic distinct_subgoals_tac in Pure/tactic.ML removes duplicate subgoals, and can be used as follows:
lemma "a ∧ a"
apply (rule conjI)
apply (tactic {* distinct_subgoals_tac *})
leaving:
proof (prove): step 2
goal (1 subgoal):
1. a
There does not appear to be a way without dropping into the ML world, unfortunately.
I came across a similar behavior as a side effect of the subst method applied to any theorem, and for example refl. Then apply (subst refl) do indeed remove the duplicate subgoals.
It's not a bug, It's a feature ;-).
Adding to davidg's answer, if one does not want to use tactic for whatever reason, it is easy enough to turn distinct_subgoals_tac into a method:
method_setup distinct_subgoals =
‹Scan.succeed (K (SIMPLE_METHOD distinct_subgoals_tac))›
lemma P and P and P
(* here there are three goals P *)
apply distinct_subgoals
(* now there is only one goal P *)