Does Isabelle support custom case distinctions when proving statements? Let's say I want to prove a statement for all natural numbers n, but the proof is entirely different depending on whether n is even or odd. Is it possible to do that case distinction in a proof, like
proof(cases n)
assume "n mod 2 = 0"
<proof>
next assume "n mod 2 = 1"
<proof>
qed
So far, I'd split the lemma/theorem in two seperate parts (assuming n even/odd) and then use these parts to proof the statement for all natural numbers, but that does not appear to be the optimal solution.
In Isabelle2017, you can prove ad-hoc case distinction rules easily, like so:
lemma "P (n::nat)"
proof -
consider (odd) "odd n" | (even) "even n" by auto
then show ?thesis
proof cases
case odd
then show ?thesis sorry
next
case even
then show ?thesis sorry
qed
qed
You can probably try the following thing:
proof -
have "your statement" when "n mod 2 = 0"
<proof>
moreover
have "your statement" when "n mod 2 = 1"
<proof>
ultimately
show "your statement"
by <some tactic>
qed
Related
Say I'm proving a theorem that assumes "n ≥ m" (both are natural numbers), and I apply induction on n. In the base case, the assumption is that "n = 0". With these two, we can conclude that, in the base case, "m = 0".
However, I'm having trouble in using the statement "n = 0":
lemma foo:
assumes "(n::nat) ≥ (m::nat)"
shows ...
proof (induct n)
case 0
have "m = 0" using <I don't know what to put here> assms by simp
...
qed
I've tried using "n = 0", but it appears to be an "Undefined fact". I've also tried adding it as an assumption, but to no avail. Nonetheless, it is clear that it is an implicit assumption when analyzing the base case.
So, how may I use the assumption of the base case directly in my proof?
Any assumptions that you need to be part of the induction need to be part of the proof state when you call induct. In particular, that should be all assumptions that contain the thing you do the induction over (i.e. all the ones that contain n in your case).
You should therefore do a using assms before the proof. Then 0 ≥ m will be available to you in the base case, under the name "0.prems" (or just 0 for all of these plus the induction hypothesis, which in this case doesn't exist).
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
In my exercise to learn Isabelle/HOL syntax, I tried to prove a toy lemma below. It's about lambda expressions (and things like the "Greatest" notation that takes a predicate as input). The intended content of the lemma is that "the greatest natural number that is l.e. 1 is 1".
lemma "1 = Greatest (λ x::nat. x ≤ 1)"
proof -
show ?thesis
by auto
qed
However, the above proof doesn't work either by auto or simp, and generates a message that.
Failed to finish proof⌂:
goal (1 subgoal):
1. Suc 0 = (GREATEST x. x ≤ Suc 0)
Can someone help explain what went wrong with the statement or how to prove this correctly (if the statement is correct)?
There is nothing wrong with the lemma, it's just that none of the rules for Greatest are declared in such a way that auto knows about them. Which is probably good, because these kinds of rules tend to mess with automation a lot.
You can prove your statement using e.g. the rule Greatest_equality:
lemma "1 = Greatest (λ x::nat. x ≤ 1)"
proof -
have "(GREATEST (x::nat). x ≤ 1) = 1"
by (rule Greatest_equality) auto
thus ?thesis by simp
qed
You can find rules like this using the Query panel in Isabelle/jEdit or the find_theorems command by searching for the constant Greatest.
If the GREATEST thing confuses you, the syntax GREATEST x. P x is just fancy syntax for Greatest (λx. P x). Such notation is fairly standard in Isabelle, we also have ∃x. P x for Ex (λx. P x) etc.
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 sometimes find it hard to use Isabelle because I cannot have a "print command" like in normal programming.
For example, I want to see what ?thesis. The concrete semantics book says:
The unknown ?thesis is implicitly matched against any goal stated by lemma or show. Here is a typical example:
My silly sample FOL proof is:
lemma
assumes "(∃ x. ∀ y. x ≤ y)"
shows "(∀x. ∃ y. y ≤ x)"
proof (rule allI)
show ?thesis
but I get the error:
proof (state)
goal (1 subgoal):
1. ⋀x. ∃y. y ≤ x
Failed to refine any pending goal
Local statement fails to refine any pending goal
Failed attempt to solve goal by exported rule:
∀x. ∃y. y ≤ x
but I do know why.
I expected
?thesis === ⋀x. ∃y. y ≤ x
since my proof state is:
proof (state)
goal (1 subgoal):
1. ⋀x. ∃y. y ≤ x
Why can't I print ?thesis?
It's really annoying to have to write the statement I'm trying to proof if it's obvious. Perhaps it's meant to be explicit but in the examples in chapter 5 they get away with using ?thesis in:
lemma fixes a b :: int assumes "b dvd (a+b)" shows "b dvd a" proof −
have "∃k′. a = b∗k′" if asm: "a+b = b∗k" for k proof
show "a = b∗(k − 1)" using asm by(simp add: algebra_simps) qed
then show ?thesis using assms by(auto simp add: dvd_def ) qed
but whenever I try to use ?thesis I always fail.
Why is it?
Note that this does work:
lemma
assumes "(∃ x. ∀ y. x ≤ y)"
shows "(∀x. ∃ y. y ≤ x)"
proof (rule allI)
show "⋀x. ∃y. y ≤ x" proof -
but I thought ?thesis was there to avoid this.
Also, thm ?thesis didn't work either.
Another example is when I use:
let ?ys = take k1 xs
but I can't print ?ys value.
TODO:
why doesn't:
lemma "length(tl xs) = length xs - 1"
thm (cases xs)
show anything? (same if your replaces cases with induction).
You can find ?theorem and others in the print context window:
As for why ?thesis doesn't work, by applying the introduction rule proof (rule allI) you are changing the goal, so it no longer matches ?thesis. The example in the book uses proof- which prevents Isabelle from applying any introduction rule.
It seems I asked a very similar question worth pointing to: What is the best way to search through general definitions, theorems, functions, etc for Isabelle?
But here is a list of thing's I've learned so far:
thm: seems to work for definition, lemmas and functions. For definition do name_def for a definition with name name. For functions do thm f.simps for all definitions in the function. For a single one do thm f.simps(1) for the first one. For lemmas do thm lemma_name or thm impI or HOL.mp etc.
term: for terms do term term_name e.g. in isar term ?thesis or term this
print_theorems: if you place this after a definition or a function it shows all the theorems defined for those! It's amazing.
print... I just noticed in jedit if you let the auto complete show you the rest for print it has a bunch of options! Probably useful!
Search engine for Isabelle: https://search.isabelle.in.tum.de/
You can use Query (TODO: improve this)
TODO: how to find good way to display stuff about tactics.
I plan to update this as I learn all the ways to debug in Isabelle.