From: Bianca Lutz <bianca.lutz@gmx.net>
Hello,
I have some problems concerning customized induction schemes in
conjunction with structured induction proofs using the induct method.
Consider the following two datatypes:
term = T1 term | T2 term | ...
var = string
a primrec function op :: [term, var] => term
and an inductively defined relation
R :: [term, term] => bool
where
R1: [[ ALL x. Q x --> R (op t1 x) (op t2 x) ]] ==> R (T1 t1) (T1 t2)
| R2: [[ ALL x. Q x --> R (op t1 x) (op t2 x) ]] ==> R (T2 t1) (T2 t2)
| ...
whereas Q is a rather long statement concerning elements of type var.
The induction scheme R.induct has the following shape:
[[ R t1 t2;
/\t1 t2. [[ALL x. Q x --> R (op t1 x) (op t2 x) & ?P (op t1 x) (op t2 x)]]
==> ?P (T1 t1) (T1 t2);
/\t1 t2. [[ALL x. Q x --> R (op t1 x) (op t2 x) & ?P (op t1 x) (op t2 x)]]
==> ?P (T2 t1) (T2 t2);
...
]] ==> ?P t1 t2
Usually there is some predicate P2 t1 t2 following from
ALL x. Q x --> R (op t1 x) (op t2 x) & P (op t1 x) (op t2 x)
that solves both R1 and R2.
Therefore, I proved the following customized induction scheme
lemma R_induct:
[[ R t1 t2;
/\t1 t2. [[?P2 t1 t2]] ==> ?P1 (T1 t1) (T1 t2);
/\t1 t2. [[?P2 t1 t2]] ==> ?P1 (T2 t1) (T2 t2);
/\t1 t2. [[ALL x. Q x --> R (op t1 x) (op t2 x) & ?P1 (op t1 x) (op t2 x)]]
==> ?P2 t1 t2;
...
]] ==> ?P1 t1 t2
Unfortunately, when I use this as shown below Isabelle fails at the last line:
*** Illegal schematic variable(s) in case "2"
*** at command "case"
although there is no schematic variable in case "2" (at least
according to Isabelle->Show me...->cases), since I instantiated ?P2
with some appropriate predicate beforehand ...
lemma
assumes "R t1 t2"
shows "P1 t1 t2"
proof (induct rule: R_induct[of t1 t2 P2 P1])
case 1 thus ?case by (simp add: assms) (* R t1 t2 *)
next
case 2
I have no idea how to avoid this. Any suggestions?
Thanks,
Bianca.
From: Johannes Hölzl <hoelzl@in.tum.de>
Hi Bianca,
Am Dienstag, den 26.01.2010, 16:35 +0100 schrieb Bianca Lutz:
[..]
The induction scheme R.induct has the following shape:
[[ R t1 t2;
/\t1 t2. [[ALL x. Q x --> R (op t1 x) (op t2 x) & ?P (op t1 x) (op t2 x)]]
==> ?P (T1 t1) (T1 t2);
/\t1 t2. [[ALL x. Q x --> R (op t1 x) (op t2 x) & ?P (op t1 x) (op t2 x)]]
==> ?P (T2 t1) (T2 t2);
...
]] ==> ?P t1 t2
Here ?P is an quantified variable which can be arbitrary instantiated
when R.induct is used.
Usually there is some predicate P2 t1 t2 following from
ALL x. Q x --> R (op t1 x) (op t2 x) & P (op t1 x) (op t2 x)
that solves both R1 and R2.Therefore, I proved the following customized induction scheme
lemma R_induct:
[[ R t1 t2;
/\t1 t2. [[?P2 t1 t2]] ==> ?P1 (T1 t1) (T1 t2);
/\t1 t2. [[?P2 t1 t2]] ==> ?P1 (T2 t1) (T2 t2);
/\t1 t2. [[ALL x. Q x --> R (op t1 x) (op t2 x) & ?P1 (op t1 x) (op t2 x)]]
==> ?P2 t1 t2;
...
]] ==> ?P1 t1 t2
When Isabelle reads variables with question marks in theorems they are
interpreted as existentially quantified variables. Just don't write them
with question marks, Isabelle interprets each identifier which is not
defined as constant as all quantified variable.
So write:
lemma R_induct:
"[[ R t1 t2;
/\t1 t2. [[P2 t1 t2]] ==> P1 (T1 t1) (T1 t2);
/\t1 t2. [[P2 t1 t2]] ==> P1 (T2 t1) (T2 t2);
/\t1 t2. [[ALL x. Q x --> R (op t1 x) (op t2 x) & ?P1 (op t1 x) (op t2 x)]]
==> P2 t1 t2;
...
]] ==> P1 t1 t2"
unfortunately when Isabelle writes theorems (like "thm R_induct") the
all quantified variables are shown with question marks.
By the way you can provide names to the cases with:
lemma R_induct[case_names Name1 Name2 Name3]:
....
Unfortunately, when I use this as shown below Isabelle fails at the last line:
*** Illegal schematic variable(s) in case "2"
*** at command "case"
I hope this solves your problem,
Johannes
From: Andreas Lochbihler <andreas.lochbihler@kit.edu>
Hi Bianca,
unfortunately, I am not able to reproduce your error, but here are some
more hints on using the induct method:
In your example:
lemma R_induct[consumes 1]: ...
lemma R_lc:
fixes t1 t2
assumes "R t1 t2"
shows "lc t1 & lc t2"
using assms
proof (induct rule: R_induct)
If you combine this with the case_names attribute, use consumes first.
Consumed assumptions are not counted when providing names.
In your example:
lemma R_induct[consumes 1, case_names P1_T1 P1_T2 ...]
...
using assms
proof (induct t1 t2 rule: R_induct)
...
using assms
proof (induct t1 t2
taking: "%t1 t2. (ALL x. Q x --> lc (op t1 x) & lc (op t2 x))"
rule: R_induct)
You can find more documentation on the induct method in the
Isabelle/Isar Reference Manual, Sec. 6.6.
I hope this helps.
Regards,
Andreas
Last updated: Nov 21 2024 at 12:39 UTC