Been trying to reproduce the short example in 3rd tutorial by Mohamed Abouelwafa on YouTube but can't get past the parsing error. Mohamed shows how to input the double right arrow as == but that doesn't seem to work on my Isabelle 2019, so I used Symbols/Arrow to get it. Other than that I can't think of anything, but still can't get this to work. Whatever I tried it doesn't parse. Help anyone? Thanks!
theory example
imports FOL
begin
lemma ex1: "⟦ A; B ⟧ ⟹ A ⋀ B"
apply (rule conjI)
apply assumption
apply assumption
done
end
When I copied your code into Isabelle, I found what appears to be a typo: "A ⋀ B" rather than "A ∧ B"
They look very similar on StackOverflow, but in Isabelle the former is much bigger and is not the correct symbol to use.
When I changed it to the latter symbol, ∧, the parsing error went away and the proof successfully completed. If you start typing \and it will allow you to select the correct symbol from a drop-down menu.
I hope this helps :)
Related
I was playing around with an example from the Isabelle/HOL tutorial to get a better understanding on the correspondence between Isar and Tactics proofs.
This is a version which works:
lemma rtrancl_converseD: "(x,y) ∈ (r ^-1 )^* ⟹ (y,x) ∈ r^* "
proof (induct y rule: rtrancl_induct)
case base
then show ?case ..
next case (step y z)
then have "(z, y) ∈ r" using rtrancl_converseD by simp
with `(y,x)∈ r^*` show "(z,x) ∈ r^*" using [[unify_trace_failure]]
apply (subgoal_tac "1=(1::nat)")
apply (rule converse_rtrancl_into_rtrancl)
apply simp_all
done
qed
I want to instantiate converse_rtrancl_into_rtrancl which proofs (?a, ?b) ∈ ?r ⟹ (?b, ?c) ∈ ?r^* ⟹ (?a, ?c) ∈ ?r^* .
But without the seemingly nonsensical apply (subgoal_tac "1=(1::nat)") line this errors with
Clash: r =/= Transitive_Closure.rtrancl
Failed to apply proof method⌂:
using this:
(y, x) ∈ r^*
(z, y) ∈ r
goal (1 subgoal):
1. (z, x) ∈ r^*
If I fully instantiate the rule apply (rule converse_rtrancl_into_rtrancl[of z y r x]) this becomes Clash: z__ =/= ya__.
This leaves me with three questions: Why does this specific case break? How can I fix it? And how can I figure out what went wrong in these cases since I can't really understand what the unify_trace_failure message wants to tell me.
rule-tactics are usually sensitive to the order of premises. The order of premises in converse_rtrancl_into_rtrancl and in your proof state don't match. Switching the order of premises in the proof state using rotate_tac will make them match the rule, so that you can directly apply fact like this:
... show "(z,x) ∈ r^*"
apply (rotate_tac)
apply (fact converse_rtrancl_into_rtrancl)
done
Or, if you want to include some kind of rule tactic, this would look like this:
apply (rotate_tac)
apply (erule converse_rtrancl_into_rtrancl)
apply (assumption)
(I personally don't use apply scripts ever in my everyday work. So apply-style gurus might know more elegant ways of handling this kind of situation. ;) )
Regarding your 1=(1::nat) / simp_all fix:
The whole goal can directly be solved by simp_all. So, attempts with adding stuff like 1=1 probably did not really tell you a lot about how much the other methods contributed to solving the proof.
However, the additional assumption seems to actually help Isabelle match converse_rtrancl_into_rtrancl correctly. (Don't ask me why!) So, one could indeed circumvent the problem by adding this spurious assumption and then eliminating it with refl again like:
apply (subgoal_tac "1=(1::nat)")
apply (erule converse_rtrancl_into_rtrancl)
apply (assumption)
apply (rule refl)
This does not look particularly elegant, of course.
The [[unify_trace_failure]] probably only really helps if one is familiar with the internal workings of Nipkow's higher-order unification algorithm. (I'm not.) I think the hint for the future here would really be that one must look closely at the order of premises for some tactics (rather than at the unifier debug output).
I found an explanation in the Isar reference 6.4.3 .
The with b1..bn command is equivalent to from b1..bn and this, i.e. it enters the proof chaining mode which adds them as (structured) assumptions to proof methods.
Basic proof methods (such as rule) expect multiple facts to be given
in their proper order, corresponding to a prefix of the premises of
the rule involved. Note that positions may be easily skipped using
something like from _ and a and b, for example. This involves the
trivial rule PROP ψ =⇒ PROP ψ, which is bound in Isabelle/Pure as “_”
(underscore).
Automated methods (such as simp or auto) just insert any given facts
before their usual operation. Depending on the kind of procedure
involved, the order of facts is less significant here.
Given the information about the 'with' translation and that rule expects chained facts in order, we could try to flip the chained facts. And indeed this works:
from this and `(y,x)∈ r^*` show "(z,x) ∈ r^*"
by (rule converse_rtrancl_into_rtrancl)
I think "6.4.3 Fundamental methods and attributes" is also relevant because it describes how the basic methods interact with incoming facts. Notably, the '-' noop which is sometimes used when starting proofs turns forward chaining into assumptions on the goal.
with `(y,x)∈ r^*` show "(z,x) ∈ r^*"
apply -
apply (rule converse_rtrancl_into_rtrancl; assumption)
done
This works because the first apply consumes all chained facts so the second apply is pure backwards chaining. This is also why the subgoal_tac or rotate_tac worked, but only if they are in seperate apply commands.
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.
How can I find which lemmas are used by the simp, auto methods, etc?
In one concrete case, I have a goal like:
lemma "x ∉ dom S ⟹ Something"
apply auto
and after applying auto I get: ¬ Something ⟹ ∃y. S x = Some y. I would like to find out why the whole goal is reversed like this, so that I can delete the respective rules from the rewriting.
I already tried using [[simp_trace_new mode=full]] apply auto and using [[simp_trace]] apply auto, but did not find information about what exactly caused auto to do this transformation.
I know this is necroposting. But for everyone stumbling over this question now, I want to point out that apply_trace is what OP was searching for. For more info see davidgs answer in this thread: Printing out / showing detailed steps of proof methods (like simp) in a proof in isabelle.
A question is posed on the IsaUserList on how to prove this lemma:
lemma "dom (SOME b. dom b = A) = A"
As a first response, P.Lammich says that obtain needs to be used:
You have to show that there is such a beast b, ie,
proof -
obtain b where "dom b = A" ...
thus ?thesis
sledgehammer (*Should find a proof now, using the rules for SOME, probably SomeI*)
Here, I have one main question, one secondary question, and I wonder about some differences between what P.Lammich says to do, some things M.Eberl does, and the results that I got.
Q1: I get the warning Introduced fixed type variable(s): 'c in "b__" at my use of obtain, and at the use of the by statement that proves the obtain. Can I get rid of this warning?
Q2: Is there a command of three dots, ...? I assume it means, "Your proof goes here." However, it sometimes sounds like the writer is also saying, "...because, after all, the proof is really simple here." I also know that there is the command . for by this, and .. for by rule. Additionally, I entertain the idea that ... is commonly known to be some simple proof statement which I'm supposed to know, but don't.
The following source will show the warning. It could be I'm supposed to fix something. The source also shows how I had to help sledgehammer, which is that I had to put an exists statement it.
I leave the error in that's due to the schematic variable, in case anyone is interested in that.
(* I HELP SLEDGEHAMMER with an exists statement. I can delete the exists
statement after the `metis` proof is found.
The `?'c1` below causes an error, but `by` still proves the goal.
*)
lemma "dom (SOME b. dom b = A) = A"
proof-
have "? x. x = (SOME b. dom b = A)"
by(simp)
from this
obtain b where ob1: "dom b = A"
(*WARNING: Orange squiggly under `obtain`. Message: Introduced fixed type
variable(s): 'c in "b__".*)
by(metis (full_types) dom_const dom_restrict inf_top_left)
thus ?thesis
using[[show_types]]
(*Because of `show_types`, a schematic type variable `?'c1` will be part
of the proof command that `sledgehammer` provides in the output panel.*)
(*sledgehammer[minimize=smart,preplay_timeout=10,timeout=60,verbose=true,
isar_proofs=smart,provers="z3 spass remote_vampire"]*)
by(metis (lifting, full_types)
`!!thesis::bool.(!!b::'a => ?'c1 option. dom b = (A::'a set) ==> thesis)
==> thesis`
someI_ex)
(*ERROR: Illegal schematic type variable: ?'c1::type.
To get rid of the error, delete `?`, or use `ob1` as the fact.*)
qed
My Q1 and Q2 are related to what's above. As part of my wonderings, there is the issue of getting an error because of the schematic variable. I may report that as bug-type issue.
In his IsaUserList response, M.Eberl says that he got the following sledgehammer proof for the obtain. He says the proof is slow, and it is. It's about 2 seconds for me.
by(metis (lifting, full_types)
dom_const dom_restrict inf_top.left_neutral someI_ex)
The proof that sledgehammer found for me above for thus ?thesis is only 4ms.
Answer to Q1
Because of M.Eberl's comment, I made a respectable effort to figure out how to get a witness without using obtain. In the process, I answered my main question.
I got rid of the warning about introducing 'c as a type variable by using b :: "'a => 'b option", instead of b, as shown here:
lemma "dom (SOME b. dom b = A) = A"
proof-
obtain b :: "'a => 'b option" where "dom (b) = A"
by(metis (full_types) dom_const dom_restrict inf_top_left)
thus ?thesis
by(metis (lifting, full_types) exE_some)
qed
Answer to Q2
(Update 140119) I finally found Isar syntax for ..., on page 6 of isar-ref.pdf.
term ... -- the argument of the last explicitly stated result (for infix application this is the right-hand side)
The string ... is not exactly a friendly search string. Finding the meaning was a result of starting to look through chapter 1. I now see that chapters 1, 2, and 6 of isar-ref.pdf are key chapters for getting some help on how to use Isar to do proofs. (End update.)
Concerning an error due to using fix/assume as an alternate to obtain
Now, I return back to M.Eberl telling me I shouldn't use obtain, which happened to be beneficial. But it brings up that it's a major effort to try to figure out how to use the language to make the PIDE happy. The last source I show below is another example of what a hassle it is to learn how to make the PIDE happy. To a large extent, it's just using examples to try and figure out the right combination of syntax and commands.
P.Lammich says to use obtain in his answer. I also looked up the use of obtain in prog-prove.pdf page 42, which discusses it in connection with the use of a witness.
I read a few other things, and I thought it was all telling me that obtain is crucial to fixing a variable or constant with certain properties.
Anyway, I used def to create a witness, so I learned something new:
declare[[show_sorts,show_brackets]]
lemma "dom (SOME b. dom b = A) = A"
proof-
def w == "(SOME b::('a => 'b option). dom b = A)"
hence "dom w = A"
by(metis (lifting, mono_tags) dom_const dom_restrict inf_top_left someI_ex)
print_facts
thus ?thesis
by(metis (lifting, full_types) dom_option_map exE_some)
qed
But, I try to use a fix/assume combination in place def, where supposedly def is an abbreviation, and I get that mysterious and greatly infuriating message, "Failed to refine any pending goal", which makes me wonder why I want to use this language.
declare[[show_sorts,show_brackets]]
lemma "dom (SOME b. dom b = A) = A"
proof-
fix w assume w_def: "w == (SOME b::('a => 'b option). dom b = A)"
hence "dom w = A"
by(metis (lifting, mono_tags) dom_const dom_restrict inf_top_left someI_ex)
print_facts
thus ?thesis
oops
For the two proofs, when the cursor is at the line before print_facts, what I see in the output panel is exactly the same, other than the def proof shows proof (state): step 4, and the fix/assume proofs shows proof (state): step 5. The facts at print_facts are also the same.
From searches, I know that "Failed to refine any pending goal" has been a source of great pain for many. In the past, I finally figured out the trick to get rid of it for what I was doing, but it doesn't make sense here, not that it made sense to me there either.
Update 140118_0054
L.Noschinski gives the subtle tip from IsaUserList 2012-11-13:
When you use "fix" or "def" to define a
variable, they either get just generalized (i.e. turned into schematics)
(fix) or replaced by their right hand side (definitions)
when a block is closed / a show is performed.
So for the fix/assumes form of the proof, I put part of it in brackets, and for some reason, it exports the fact in the way that's needed:
lemma "dom (SOME b. dom b = A) = A"
proof-
{
fix w assume "w == (SOME b::('a => 'b option). dom b = A)"
hence "dom w = A"
by(metis (lifting, mono_tags) dom_const dom_restrict inf_top_left someI_ex)
}
thus ?thesis
by(metis (lifting, full_types) dom_option_map exE_some)
qed
I go ahead and throw in a let form of the proof. I wouldn't have known to use the schematic variable ?w without having looked at M.Eberl's proofs.
lemma "dom (SOME b. dom b = A) = A"
proof-
let ?w = "(SOME b::('a => 'b option). dom b = A)"
have "dom ?w = A"
by(metis (lifting, mono_tags) dom_const dom_restrict inf_top_left someI_ex)
thus ?thesis
by(metis (lifting, full_types) dom_option_map exE_some)
qed