How do I prove that 4 is even using Isabelle - isabelle

Assuming that I have this inductive definition for Even
inductive_set Even :: "Int.int set"
where null: "0 ∈ Even"
| plus: "x ∈ Even ⟹ x+2 ∈ Even"
| min: "x ∈ Even ⟹ x-2 ∈ Even"
How do I prove this lemma
lemma four_is_even: "4 ∈ Even" ?
I am relatively new to proof assistant.

As #Mathias Fleury informally explained above, there are several ways in which you can prove your lemma:
Using forward-style reasoning
You can first prove the following auxiliary lemma using the OF fact combinator:
lemma four_is_even_fwd': "0+2+2 ∈ Even"
by (fact plus [OF plus [OF null]])
and then let the simplifier take care of proving 0+2+2 = 4:
lemma four_is_even_fwd: "4 ∈ Even"
using four_is_even_fwd' by simp
Also, you can use the Isabelle/Isar proof language to produce a more structured and pedagogical proof:
lemma four_is_even_fwd_str: "4 ∈ Even"
proof -
have "0 ∈ Even"
by (fact null)
then have "0+2 ∈ Even"
by (fact plus)
then have "0+2+2 ∈ Even"
by (fact plus)
then show ?thesis
by simp
qed
Using backward-style reasoning
Similarly to the first example of the forward-style reasoning above, you can prove the following auxiliary lemma using apply-scripts:
lemma four_is_even_bwd': "0+2+2 ∈ Even"
apply (rule plus) (* subgoal: 0+2 ∈ Even *)
apply (rule plus) (* subgoal: 0 ∈ Even *)
apply (rule null) (* no subgoals! *)
done
and then again let the simplifier take care of proving 0+2+2 = 4:
lemma four_is_even_bwd: "4 ∈ Even"
using four_is_even_bwd' by simp
Of course, trying to prove your lemma using Even.min is much more involved.

Related

Nested cases Isar

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

Induction on second argument Isar

inductive T :: "alpha list ⇒ bool" where
Tε : "T []" |
TaTb : "T l ⟹ T r ⟹ T (l # a#(r # [b]))"
lemma Tapp: "⟦T l; T r⟧ ⟹ T (l#r)"
proof (induction r rule: T.induct)
I get 'Failed to apply initial proof method⌂'
In Isabelle one could use rotate_tac I guess to get induction to work on the desired argument, what's the Isar equivalent? Would it help to reformulate the lemma with 'assumes' & 'shows'?
Rule induction is always on the leftmost premise of the goal. Therefore, the Isabelle/Isar solution consists on inverting the order of the premises:
lemma Tapp: "⟦T r; T l⟧ ⟹ T (l#r)"
proof (induction r rule: T.induct)
...
Or, using assumes and shows:
lemma Tapp: assumes "T r" and "T l" shows "T (l#r)"
using assms proof (induction r rule: T.induct)
...

How to prove an element does not belong to an inductive_set

Assuming I have already defined an inductive_set, for example, the inductive set "Even" such that:
inductive_set Even :: "int set"
where ZERO : "0 ∈ Even"
| PLUS :"x ∈ Even ⟹x+2 ∈ Even"
| MIN :"x ∈ Even ⟹ x-2 ∈ Even"
lemma aux : "x= ((x::int)-2) + 2" by simp
It's fairly easy to prove lemma : "2 ∈ Even" by doing a subst to replace 2 by 2-2+2
But I'm wondering how do prove lemma : "1 ∉ Even"?
Edit:
(*Javier Diaz's answer*)
lemma Even_divisible_by_2: "n ∈ Even ⟹ 2 dvd n"
by (induction rule: Even.induct) (simp, presburger+)
lemma "1 ∉ Even"
proof
assume "1 ∈ Even"
then have "2 dvd 1"
using Even_divisible_by_2 by fastforce
then show False
using odd_one by blast
qed
What would be the equivalent way to do it for 3?
lemma "3 ∉ Even"
proof
assume "3 ∈ Even"
then have "2 dvd 3"
(*how to continue?*)
qed
Thanks in advance
I would prove an intermediate result first, namely that each number in your inductive set is divisible by 2:
lemma Even_divisible_by_2: "n ∈ Even ⟹ 2 dvd n"
by (induction rule: Even.induct) simp_all
And then prove your result by contradiction:
lemma "1 ∉ Even"
proof
assume "1 ∈ Even"
then have "2 dvd 1"
using Even_divisible_by_2 by fastforce
then show False
using odd_one by blast
qed
I strongly recommend that you use Isabelle/Isar instead of proof scripts.
NOTE: As request by the post author, I'm adding a proof that 3 ∉ Even in the style of the above proof:
lemma "3 ∉ Even"
proof
assume "3 ∈ Even"
then have "2 dvd 3"
using Even_divisible_by_2 by fastforce
then show False
using odd_numeral by blast
qed
Alternative solution: #user9716869 provided the following more general and efficient solution based on the use of Even_divisible_by_2:
lemma n2k1_not_Even: "odd n ⟹ n ∉ Even"
using Even_divisible_by_2 by auto
lemma "1 ∉ Even" and "3 ∉ Even" and "11 ∉ Even"
by (simp_all add: n2k1_not_Even)

Isabelle/ZF nat inequality

I am new to Isabelle and I tried to prove something like this:
lemma refl_add_help: "[| n:nat; m:nat |] ==> 0 #+ n \<le> m #+ n"
by(rule add_le_mono1, simp)
theorem mult_le_self: "[| 0 < m; n:nat; m:nat |] ==> n \<le> n #* m"
apply(case_tac m, auto)
apply(simp add: refl_add_help)
oops
I also tried to prove a lemma:
lemma "[| n:nat; m:nat |] ==> n \<le> m #+ n"
but I could not success either. Can anyone give me some advice on how to solve the problem? Thank you very much.
By the way, is it not possible to display value in ZF like
value "{m:nat. m < 5}"
I have imported the theory like this:
theory mytheory
imports ZF.Arith
I'm not very familiar with Isabelle/ZF. That said, you can prove your results as follows:
theorem mult_le_self: "⟦ 0 < m; n:nat; m:nat ⟧ ⟹ n ≤ n #* m"
apply (case_tac m, simp)
apply (frule_tac ?m="n #* x" in refl_add_help)
apply (auto simp add: add_commute)
done
lemma "⟦ n:nat; m:nat ⟧ ⟹ n ≤ m #+ n"
by (frule refl_add_help, auto)
For more information regarding the frule and frule_tac methods please refer to The Isabelle/Isar Reference Manual, sections 9.2 and 7.3 respectively. However, I encourage you to use Isabelle/Isar instead of proof scripts. For example, your lemma can be proven as follows:
lemma "⟦ n:nat; m:nat ⟧ ⟹ n ≤ m #+ n"
proof -
assume "n:nat" and "m:nat"
then show ?thesis using refl_add_help by simp
qed
Or, more compactly, as follows:
lemma
assumes "n:nat" and "m:nat"
shows "n ≤ m #+ n"
using assms and refl_add_help by simp
Regarding the value command, I think it does not work in Isabelle/ZF.

Proof by induction with three base cases (Isabelle)

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.

Resources