I have a function called feedback which calculates the power of 3 (i.e)
feedback(t) = 3^t
primrec feedback :: "nat ⇒ nat" where
"feedback 0 = Suc(0)"|
"feedback (Suc t) = (feedback t)*3"
I want to prove that
if t > 5 then feedback(t) > 200
using Induction
lemma th2: "¬(t>5) ∨ ((feedback t) > 200)" (is "?H(t)" is "?P(t)∨?Q(t)" is "(?P(t))∨(?F(t) > 200)")
proof(induct t)
case 0 show "?P 0 ∨ ?Q 0" by simp
next
assume a:" ?F(t) > 200"
assume d: "?P(t) = False"
have b: "?F (Suc(t)) ≥ ?F(t)" by simp
from b and a have c: "?F(Suc(t)) > 200" by simp
from c have e: "?Q(Suc(t))" by simp
from d have f:"?P(Suc(t)) = False" by simp
from f and e have g: "?P(Suc(t))∨?Q(Suc(t))" by simp
from a and d and g have h: "?P(t)∨?Q(t) ⟹ ?P(Suc(t))∨?Q(Suc(t))" by simp
from a and d have "?H(Suc(t))" by simp
qed
First I prove that
feedback(t+1) >= feedback(t)
then assume feedback(t) > 200, so feedback(t+1)>200
Assume t>5
this implies (t+1) > 5
Also ~((t+1)>5) V (feedback (t+1) > 200) is True
Thus if P(t) is true then P(t+1) is true
But this is not working. I have no idea what the problem is
Well, first of all, you cannot simply assume arbitrary things in Isar. Or rather, you can do that, but you won't be able to show your goal after you've done that. The things that Isar allows you to assume are quite rigid; in your case, it's ¬ 5 < t ∨ 200 < feedback t.
I recommend using the case command, which assumes the right things for you. Then you can do a case distinction about that disjunction and then another one about whether t = 5:
lemma th2: "¬(t>5) ∨ ((feedback t) > 200)"
proof (induct t)
case 0
show ?case by simp
next
case (Suc t)
thus ?case
proof
assume "¬t > 5"
moreover have "feedback 6 = 729" by code_simp
-- ‹"simp add: eval_nat_numeral" would also work›
ultimately show ?thesis
by (cases "t = 5") auto
next
assume "feedback t > 200"
thus ?thesis by simp
qed
qed
Or, more compactly:
lemma th2: "¬(t>5) ∨ ((feedback t) > 200)"
proof (induct t)
case (Suc t)
moreover have "feedback 6 = 729" by code_simp
ultimately show ?case by (cases "t = 5") auto
qed simp_all
If your feedback function is actually monotonic, I would recommend proving that first, then the proof becomes a little less tedious.
Related
I'm having some issues trying to do exercise 4.5 of 'Concrete Semantics' in Isar:
inductive S :: "alpha list ⇒ bool" where
Sε : "S []" |
aSb : "S m ⟹ S (a#m # [b])" |
SS : "S l ⟹ S r ⟹ S (l # r)"
inductive T :: "alpha list ⇒ bool" where
Tε : "T []" |
TaTb : "T l ⟹ T r ⟹ T (l # a#(r # [b]))"
lemma TS: "T w ⟹ S w"
proof (induction w rule: T.induct)
case Tε
show ?case by (simp add:Sε)
case (TaTb l r) show ?case using TaTb.IH(1) (* This being S l, which allows us to case-split on l using S.induct *)
proof (cases "l" rule: S.induct)
case Sε
then show ?case by (simp add: TaTb.IH(2) aSb)
next case (aSb m)
I'm getting Illegal schematic variable(s) in case "aSb"⌂
Also I find suspicious that in Sε I cannot refer to ?case, I get Unbound schematic variable: ?case. I'm thinking that maybe the problem is that I have a cases in an induction?
As summarized by the comments, you have two problems:
cases "l" rule: S.induct makes little sense and you should either use a nested induction induction l rule: S.induct or a case distinction cases l rule: S.cases
In cases you should use ?thesis instead of cases as the Isabelle/jEdit outline tells you (you can click on that thing to insert it into the buffer!). That way you would also have given a name to all variable in the case TaTb.
So you probably want something like:
lemma TS: "T w ⟹ S w"
proof (induction w rule: T.induct)
case Tε
show ?case by (simp add:Sε)
next
case (TaTb l r a b) show ?case using TaTb.IH(1)
proof (cases "l" rule: S.cases)
case Sε
then show ?thesis sorry
next
case (aSb m a b)
then show ?thesis sorry
next
case (SS l r)
then show ?thesis sorry
qed
qed
I was trying to recreate a simplified version of the natural numbers, for learning purposes (as it involves inductive definitions, recursive functions, etc...). In that process however, I got stuck in something that I thought would be very trivial.
Basically, I have a definition for natural numbers 'natt' and a definition for the '<' relation:
datatype natt = Zero | Succ natt
primrec natt_less :: "natt ⇒ natt ⇒ bool" (infixl "<" 75) where
"natt_less n Zero = False"
| "natt_less n (Succ m') = (case n of Zero ⇒ True | Succ n' ⇒ natt_less n' m')"
and from these, I tried to prove 3 basic properties of the < relation:
Non-reflexivity: ~ (a < a)
Non-symmetry: a < b ⟹ ~ (b < a)
Transitivity: a < b ⟹ b < c ⟹ a < c
I was able to prove the first, but not the others. What took me even more by surprise, is that there are some sub-lemmas that would aid on these, such as Succ a < b ⟹ a < b, a < b ⟹ a < Succ b or a < b ∨ a = b ∨ b < a, which seem even more trivial, but nonetheless I was also not able to prove, even after many attempts. It seems like only one of these (including 2. and 3.) is enough to prove the rest, but I wasn't able to prove any of them.
I'm mostly trying to use induction. Together with the fact that I've made the definitions myself, there are two possibilities - Either my definitions are wrong, and do not have the desired properties, or I'm missing some method/argument. So, I have two questions:
Is my definition wrong (i.e. it does not accurately represent < and lacks the desired properties)? If so, how may I fix it?
If not, how can I prove these seemingly trivial properties?
For context, my current attempts are by induction, which I can prove the base case, but always get stuck in the induction case, not really knowing where to go with the assumptions, such as in this example:
lemma less_Succ_1: "Succ a < b ⟹ a < b"
proof (induction b)
case Zero
assume "Succ a < Zero"
then have "False" by simp
then show ?case by simp
next
case (Succ b)
assume "(Succ a < b ⟹ a < b)" "Succ a < Succ b"
then show "a < Succ b" oops
After some tips from user9716869, it's clear that my main problem was the lack of knowledge about the arbitrary option in induction. Using (induction _ arbitrary: _) and (cases _) (see the reference manual for details), the proofs are quite straight forward.
Since these are made for educational purposes, the following proofs are not meant to be concise, but to make every step very clear. Most of these could be vastly reduced if more automation is desired, and some can be done in one line (which I left as a comment below the lemma).
Note: In these proofs, we are using an implicit lemma about inductive types, their injectivity (which implies (Succ a = Succ b) ≡ (a = b) and Zero ≠ Succ a). Furthermore, (Succ a < Succ b) ≡ (a < b) by definition.
First, we prove 2 useful lemmas:
a < b ⟹ b ≠ Zero
b ≠ Zero ⟷ (∃ b'. b = Succ b')
lemma greater_not_Zero [simp]: "a < b ⟹ b ≠ Zero"
(*by clarsimp*)
proof
assume "a < b" "b = Zero"
then have "a < Zero" by simp
then show "False" by simp
qed
lemma not_Zero_is_Succ: "b ≠ Zero ⟷ (∃ b'. b = Succ b')"
(*by (standard, cases b) auto*)
proof
show "b ≠ Zero ⟹ ∃ b'. b = Succ b'"
proof (cases b)
case Zero
assume ‹b ≠ Zero›
moreover note ‹b = Zero›
ultimately show "∃b'. b = Succ b'" by contradiction
next
case (Succ b')
assume ‹b ≠ Zero›
note ‹b = Succ b'›
then show "∃b'. b = Succ b'" by simp
qed
next
assume "∃ b'. b = Succ b'"
then obtain b'::natt where "b = Succ b'" by clarsimp
then show "b ≠ Zero" by simp
qed
Armed with these, we can prove the 3 main statements:
Non-reflexivity: ~ (a < a)
Non-symmetry: a < b ⟹ ~ (b < a)
Transitivity: a < b ⟹ b < c ⟹ a < c
lemma less_not_refl [simp]: "¬ a < a"
(*by (induction a) auto*)
proof (induction a)
case Zero
show "¬ Zero < Zero" by simp
next
case (Succ a)
note IH = ‹¬ a < a›
show "¬ Succ a < Succ a"
proof
assume "Succ a < Succ a"
then have "a < a" by simp
then show "False" using IH by contradiction
qed
qed
lemma less_not_sym: "a < b ⟹ ¬ b < a"
proof (induction a arbitrary: b)
case Zero
then show "¬ b < Zero" by simp
next
case (Succ a)
note IH = ‹⋀b. a < b ⟹ ¬ b < a›
and IH_prems = ‹Succ a < b›
show "¬ b < Succ a"
proof
assume asm:"b < Succ a"
have "b ≠ Zero" using IH_prems by simp
then obtain b'::natt where eq: "b = Succ (b')"
using not_Zero_is_Succ by clarsimp
then have "b' < a" using asm by simp
then have "¬ a < b'" using IH by clarsimp
moreover have "a < b'" using IH_prems eq by simp
ultimately show "False" by contradiction
qed
qed
lemma less_trans [trans]: "a < b ⟹ b < c ⟹ a < c"
proof (induction c arbitrary: a b)
case Zero
note ‹b < Zero›
then have "False" by simp
then show ?case by simp
next
case (Succ c)
note IH = ‹⋀a b. a < b ⟹ b < c ⟹ a < c›
and IH_prems = ‹a < b› ‹b < Succ c›
show "a < Succ c"
proof (cases a)
case Zero
note ‹a = Zero›
then show "a < Succ c" by simp
next
case (Succ a')
note cs_prem = ‹a = Succ a'›
have "b ≠ Zero" using IH_prems by simp
then obtain b' where b_eq: "b = Succ b'"
using not_Zero_is_Succ by clarsimp
then have "a' < b'" using IH_prems cs_prem b_eq by simp
moreover have "b' < c" using IH_prems b_eq by simp
ultimately have "a' < c" using IH by simp
then show "a < Succ c" using cs_prem by simp
qed
qed
Consider as an example the following definition of inequality of natural numbers in Isabelle:
inductive unequal :: "nat ⇒ nat ⇒ bool" where
zero_suc: "unequal 0 (Suc _)" |
suc_zero: "unequal (Suc _) 0" |
suc_suc: "unequal n m ⟹ unequal (Suc n) (Suc m)"
I want to prove irreflexivity of unequal, that is, ¬ unequal n n. For illustration purposes let me first prove the contrived lemma ¬ unequal (n + m) (n + m):
lemma "¬ unequal (n + m) (n + m)"
proof
assume "unequal (n + m) (n + m)"
then show False
proof (induction "n + m" "n + m" arbitrary: n m)
case zero_suc
then show False by simp
next
case suc_zero
then show False by simp
next
case suc_suc
then show False by presburger
qed
qed
In the first two cases, False must be deduced from the assumptions 0 = n + m and Suc _ = n + m, which is trivial.
I would expect that the proof of ¬ unequal n n can be done in an analogous way, that is, according to the following pattern:
lemma "¬ unequal n n"
proof
assume "unequal n n"
then show False
proof (induction n n arbitrary: n)
case zero_suc
then show False sorry
next
case suc_zero
then show False sorry
next
case suc_suc
then show False sorry
qed
qed
In particular, I would expect that in the first two cases, I get the assumptions 0 = n and Suc _ = n. However, I get no assumptions at all, meaning that I am asked to prove False from nothing. Why is this and how can I conduct the proof of inequality?
You are inducting over unequal. Instead, you should induct over n, like this:
lemma "¬ (unequal n n)"
proof (induct n)
case 0
then show ?case sorry
next
case (Suc n)
then show ?case sorry
qed
Then we can use Sledgehammer on each of the subgoals marked with sorry. Sledgehammer (with CVC4) recommends us to complete the proof as follows:
lemma "¬ (unequal n n)"
proof (induct n)
case 0
then show ?case using unequal.cases by blast
next
case (Suc n)
then show ?case using unequal.cases by blast
qed
The induction method handles variable instantiations and non-variable instantiations differently. A non-variable instantiation t is a shorthand for x ≡ t where x is a fresh variable. As a result, induction is done on x, and the context additionally contains the definition x ≡ t.
Therefore, (induction "n + m" "n + m" arbitrary: n m) in the first proof is equivalent to (induction k ≡ "n + m" l ≡ "n + m" arbitrary: n m) with the effect described above. To get this effect for the second proof, you have to replace (induction n n arbitrary: n) with (induction k ≡ n l ≡ n arbitrary: n). The assumptions will actually become so simple that the pre-simplifier, which is run by the induction method, can derive False from them. As a result, there will be no cases left to prove, and you can replace the whole inner proof–qed block with by (induction k ≡ n l ≡ n arbitrary: n).
I want to be able to prove a statement by induction on n (of type nat). It consists of a conditional whose antecedent is only true for n >= 2. A conditional whose antecedent is false is always true. So I'd like to prove the cases n=0, n=1 and n=2 all separately from the main inductive step. Is it possible to do a proof by induction with three base cases like the following:
lemma "P (n::nat) --> Q"
proof (induct n)
case 0
show ?case sorry
next
case 1
show ?case sorry
next
case 2
show ?case sorry
next
case (Suc n)
show ?case sorry
qed
As it stands, this doesn't seem to work. I could prove "P (n+2) --> Q" by induction instead, but it wouldn't be as strong a statement. I'm considering a case split into "n=0","n=1" and "n>=2", and proving only the last case by induction.
The cleanest way is probably to prove a custom induction rule for the kind of induction that you want, like this:
lemma nat_0_1_2_induct [case_names 0 1 2 step]:
assumes "P 0" "P 1" "P 2" "⋀n. n ≥ 2 ⟹ P n ⟹ P (Suc n)"
shows "P n"
proof (induction n rule: less_induct)
case (less n)
show ?case using assms(4)[OF _ less.IH[of "n - 1"]]
by (cases "n ≤ 2") (insert assms(1-3), auto simp: eval_nat_numeral le_Suc_eq)
qed
lemma "P (n::nat) ⟶ Q"
proof (induction n rule: nat_0_1_2_induct)
In theory, the induction_schema method is also very useful to prove such custom induction rules, but in this case, it doesn't help a lot:
lemma nat_0_1_2_induct [case_names 0 1 2 step]:
"P 0 ⟹ P 1 ⟹ P 2 ⟹ (⋀n. n ≥ 2 ⟹ P n ⟹ P (Suc n)) ⟹ P n"
proof (induction_schema, goal_cases complete wf terminate)
case (complete P n)
thus ?case by (cases n) force+
next
show "wf (Wellfounded.measure id)" by (rule wf_measure)
qed simp_all
You could also use less_induct directly and then do a case distinction within the induction step for the base cases.
I'm trying to proof the theorem that if n > 0 then g n b = True (see below). This is the case, because g (Suc n) b only ever calls g 0 True. Unfortunately, I don't have that fact in my induction when I try to proof g 0 b. How can I finish the proof (what do I have to replace the sorry with)?
fun g :: "nat ⇒ bool ⇒ bool" where
"g (Suc n) b = g n True" |
"g 0 b = b"
theorem
fixes n::nat and b::bool
assumes "n > 0"
shows "g n b"
proof (induct n b rule: g.induct)
fix n
fix b
assume "g n True"
thus "g (Suc n) b" by (metis g.simps(1))
next
fix b
show "g 0 b" sorry
qed
You forgot to use the assumption n > 0 in your induction.
E.g., you may write
theorem
fixes n::nat and b::bool
assumes "n > 0"
shows "g n b"
using assms (* this is important *)
proof (induct n b rule: g.induct)
case (1 n b)
thus ?case by (cases n) auto
next
case (2 b)
thus ?case by auto
qed
Alternatively you may immediately start your theorem like this
and shorten it further:
theorem "n > 0 ==> g n b"
proof (induct n b rule: g.induct)
case (1 n b)
thus ?case by (cases n) auto
qed auto