How to use the base case assumption when proving with 'induct' in Isabelle - isabelle

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).

Related

How to use lambda expression in Isabelle/HOL?

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.

Local assumptions in "state" mode

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)`

How to obtain witness instances outside a lemma in Isabelle/HOL

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.

Custom case distinctions in proofs

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

Instantiating theorems in Isabelle

Suppose some lemma, lets call it an_equation, proves that equation f(n)=n*n+1 holds for all odd natural numbers n (and f is some previously defined function).
How can I instantiate this lemma to concrete values of n, so that I can prove, say f(5)=5*5+1?
(There is the lemmas keyword, with which I can prove lemmas inst = an_equation[where n=5, simplified], but this is not quite what I what. What I want is
lemma inst_new : "f(5) = 5*5+1"
but as there were scarcely any example around in the usual documentation thai I consult, I couldn't figure out how to prove this.)
You can instantiate free variables in your theorem with the of and where attributes, e.g. an_equation[of 5] or an_equation[where n = 5]. You can also instantiate its assumptions, e.g. if you have a theorem called foo of the form P x ⟹ Q x and you have a theorem called bar of the form P 5, you can do foo[OF bar] to get the theorem Q 5.
You can inspect these instantiated with thm (e.g. thm foo[of 5]) and use them in a proof with using, from, etc.
Note that proof methods also instantiate theorems whenever needed, e.g. if you have, as above, the theorem foo stating that P n ⟹ Q n and you have the goal Q 5, you can do this:
lemma "Q 5"
apply (rule foo)
Then the goal state will have one subgoal, namely P 5.
So, in your case, by (rule an_equation) should do the trick. Something like by (simp add: an_equation) or using an_equation by simp or using an_equation by blast would probably also work, but might be slightly less robust in general since the simplifier can do other stuff first and then the rule might not apply anymore.

Resources