How to prove an element does not belong to an inductive_set - isabelle

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)

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 do I prove that 4 is even using 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.

Proving basic properties of recursive "less than" definition for naturals in Isabelle

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

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