The statement n+0 = n is quite trivial to prove:
theorem add_0: "n+0 = (n::nat)"
apply(simp)
done
Upon trying to convert it to Isar however, I've noticed that it doesn't seem to require any assumption. So in the this attempt:
theorem add_0: "n+0 = (n::nat)"
proof -
thus "True" by simp
qed
It fails, as there are "No current facts available". This second attempt also fails:
theorem add_0: "n+0 = (n::nat)"
proof -
from add_0 show "True" by simp
qed
This time with the error "Failed to refine any pending goal".
Is it possible to prove a statement that requires no assume clause in Isar? If yes, then how?
There are two problems with thus "True"
As you've noted, the proof state that you begin doesn't have any assumptions, therefore no facts in the proof state. The abbreviation thus expands to then show, as we have no facts in our proof state it doesn't make sense to use then so we should instead replace it with show.
show "True" is saying that we want to prove "True" instead we want to prove the goal of the theorem. We can use the schematic variable ?thesis to refer to the original thesis of the theorem. The error Failed to refine any pending goal is just saying that if we were to prove that True is true, it wouldn't help solve the goal of our thesis.
So we can prove our original theorem with an Isar proof using the following pattern.
theorem add_0: "n+0 = (n::nat)"
proof -
show ?thesis by simp
qed
Related
Frequently, when proving a statement in "prove" mode, I find myself in need of some intermediate statements that are not yet stated nor proved. To state them, I usually make use of the subgoal command, followed by proof- to change to "state" mode. In the process, however, all of the local assumptions are removed. A typical example could look like this
lemma "0 < n ⟷ ((2::nat)^n < 3^n)"
apply(auto)
subgoal
proof-
have "0<n" sorry (* here I would like to refer to the assumption from the subgoal *)
then show ?thesis sorry
qed
subgoal sorry
done
I am aware that I could state the assumptions using assume explicitly. However, this becomes quickly rather tedious when multiple assumptions are involved. Is there an easier way to simply refer to all of the assumptions? Alternatively, is there a good way to implement statements with short proofs directly in "prove" mode?
There is the syntax subgoal premises prems to bind the premises of the subgoal to the name prems (or any other name – but prems is a sensible default):
lemma "0 < n ⟷ ((2::nat)^n < 3^n)"
apply(auto)
subgoal premises prems
proof -
thm prems
There is also a method called goal_cases that automatically gives names to all the current subgoals – I find it very useful. If subgoal premises did not exist, you could do this instead:
lemma "0 < n ⟷ ((2::nat)^n < 3^n)"
apply(auto)
subgoal
proof goal_cases
case 1
By the way, looking at your example, it is considered a bad idea to do anything after auto that depends on the exact form of the proof state, such as metis calls or Isar proofs. auto is fairly brutal and might behave differently in the next Isabelle release so that such proofs break. I recommend doing a nice structured Isar proof here.
Also note that your theorem is a direct consequence of power_strict_mono and power_less_imp_less_base and can be proven in a single line:
lemma "0 < n ⟷ ((2::nat)^n < 3^n)"
by (auto intro: Nat.gr0I power_strict_mono)`
I was wondering if there is a way to abort a proof in Isabelle/jEdit?
I searched for commands such as "Reset", "Abort" but couldn't find it.
I know there is Sorry. But I am not sure if one uses Sorry, the theorem at hand is assumed to be true or abandoned. Also, Sorry does not seem to work in the apply..done mode.
Currently, I comment out the theorems that I can't prove. But it requires a lot of typing (four characters each in (* *)) to comment or uncomment something, which is kind of cumbersome.
So is there a standard/universal way to abort a proof in Isabelle?
First, the command is sorry and it does work (but only) in apply style:
lemma
‹False ∧ True›
apply (rule conjI)
apply auto
sorry
About the actual question, oops aborts proofs, whether in apply style or not:
lemma
‹False ∧ True›
proof -
have True
by auto
oops
An oops-ed proof cannot be referenced later.
I'm going through chapter 5 of concrete semantics.
I got some error while working through this toy example proof:
lemma
shows "¬ ev (Suc 0)"
I know this is more than needed (since by cases) magically solves everything & gives a finished proof, but I wanted to make explicit the cases.
I tried this:
lemma
shows "¬ ev (Suc 0)"
proof (rule notI)
assume "ev (Suc 0)"
then show False
proof (cases)
case ev0
then show ?case by blast
next
case evSS
then show ?case sorry
qed
but if I put my mouse on the ?cases I get a complaint by Isabelle's (type checker?) verifier:
proof (chain)
picking this:
Failed to refine any pending goal
Local statement fails to refine any pending goal
Failed attempt to solve goal by exported rule:
HOL.induct_true
what does this error mean?
Why can't I make the proof explicit with the case syntax here? even if it's trivial?
How question is, how do you close a case immediately?
If there are no cases to be proved you can close a proof immediately with qed.
is referenced later but I can't make it work for real proofs.
The auto-generated proof outline is sometimes just wrong. This is one such case.
The reason why cases solves your goal here is that it does some pre-simplification of the cases (as documented in §6.5.2 of the Isabelle/Isar reference manual). This is enough to make both cases disappear automatically here, since they are clearly impossible. Your proof state therefore has no proof obligations left, and Isar only allows you to prove things with show that you still have to prove. That's why you get the error message Failed to refine any pending goal: There simply are no pending goals.
You can disable the pre-simplification of cases using the (no_simp) parameter, i.e.
proof (cases (no_simp))
Note however that cases does not define the ?case variable because it does not change the goal. Just use ?thesis instead.
I have been playing around with basic examples of proofs in Isabelle.
Consider the following simple proof:
lemma
fixes n::nat
shows "n*(n+1) = n^2 + n"
by simp
It seems to me that a powerful proof assistant like Isabelle should be able to prove this lemma without much guidance.
However, I was surprised to find out that Isabelle actually fails at applying the rule simp here (I also tried other "generic" rules like simp_all, auto, force, blast but the result is the same).
If I replace the last line by the following, then it works out:
by (simp add: power2_eq_square)
My concern is that I feel like I shouldn't have had to tell the system about the specific rule power2_eq_square to complete this proof.
Playing around with similar trivial examples, I found that simp is able to prove
n*(n+2)=n*n+n*2
but fails with
n*(n+3)=n*n+n*3
The last example is proven
by (simp add: distrib_left)
It is a complete mystery to me why I need to specify distrib_left in that second example, but not in the first (why is that?).
I have given these examples not for their own sake, but mainly to illustrate my main question:
Is there a way to automate the verification of routine algebraic identities such as the above in Isabelle? If there isn't, then why not? What are the technical obstacles?
Daily proof work indeed often stumbles over »routine algebraic identities«; but after some practical experience one usually develops some intuition how to solve such problems effectively. A pattern I have developed over the years, by example:
context semidom
begin
lemma "a * (b ^ 2 + c) + 2 = a * b * b + c * a + 2"
A typical explorative proof starts with
apply auto
Then associativity and commutative are considered also
apply (auto simp add: ac_simps)
Then more algebaic normalizing rules are applied
apply (auto simp add: algebra_simps)
The last gap is then easily filled by sledgehammer
apply (simp add: power2_eq_square)
After that, the proof can be compactified
by (simp add: algebra_simps power2_eq_square)
The lemma
lemma power2_eq_square: "a^2 = a * a"
is not a good rewrite rule in general, as it will easily blow up the size of terms. So it is expected that a term rewriting based automation like simp will not apply this without you telling it to.
What you want is some sort of proof search, and Isabelle provides that: After writing your lemma, you can invoke the sledgehammer tool, and it will readily and quickly find the proof for you:
Sledgehammering...
Proof found...
"z3": Try this: by (simp add: power2_eq_square) (1 ms)
"cvc4": Try this: by (simp add: power2_eq_square) (5 ms)
What could be the reason for the following error message:
Pending sort hypotheses: trelations
Here,
trelations is a class type
the error is generated when proving a collection of subgoals by contradiction. Subgoals are of the form: "premise1 ==> premise2 ==> False"
the proof state says "No subgoals!", though.
the assumptions of trelations are consistent to me (https://lists.cam.ac.uk/pipermail/cl-isabelle-users/2012-July/msg00023.html)
Thanks.
The error arises because Isabelle can't know for sure that your assumptions are consistent. Here's a contrived example (from Brian Huffman):
class impossible =
assumes impossible: "∃x. x ≠ x"
lemma False: "False"
proof -
obtain x :: "'a::impossible" where "x ≠ x"
using impossible ..
then show "False" by simp
qed
Clearly, the system must reject this proof, because the impossible sort is empty. The technical reason why it is rejected is that the system doesn't know any instance of impossible.
There are two ways to prevent this from happening:
Before doing any proofs over classes, register an instance.
Add a "sort constraint" as an assumption for your lemma: SORT_CONSTRAINT('a::trelations). It gets automatically discharged when you use the lemma (once you've registered an instance somewhere).