How to fix “Illegal schematic variable(s)” in mutu

2019-07-16 20:43发布

问题:

In Isabelle, I'm trying to do rule induction on mutually recursive inductive definitions. Here's the simplest example I was able to create:

theory complex_exprs
imports Main
begin

datatype A = NumA int
           | AB B
and B = NumB int
      | BA A

inductive eval_a :: "A ⇒ int ⇒ bool" and eval_b :: "B ⇒ int ⇒ bool" where
eval_num_a: "eval_a (NumA i) i" |
eval_a_b:   "eval_b b i ⟹ eval_a (AB b) i" |
eval_num_b: "eval_b (NumB i) i" |
eval_b_a:   "eval_a a i ⟹ eval_b (BA a) i"

lemma foo:
  assumes "eval_a a result"
  shows   "True"
using assms
proof (induction a)
  case (NumA x)
    show ?case by auto
  case (AB x)

At this point, Isabelle stops with 'Illegal schematic variable(s) in case "AB"'. Indeed the current goal is ⋀x. ?P2.2 x ⟹ eval_a (AB x) result ⟹ True which contains the assumption ?P2.2 x. Is that the 'schematic variable' Isabelle is talking about? Where does it come from, and how can I get rid of it?

I get the same problem if I try to do the induction on the rules:

proof (induction)
  case (eval_num_a i)
    show ?case by auto
  case (eval_a_b b i)

Again, the goal is ⋀b i. eval_b b i ⟹ ?P2.0 b i ⟹ True with the unknown ?P2.0 b i, and I can't continue.

As a related question: I tried to do the induction using

proof (induction rule: eval_a_eval_b.induct)

but Isabelle doesn't accept this, saying 'Failed to apply initial proof method'.

How do I make this induction go through? (In my actual application, I do actually need induction because the goal is more complex than True.)

回答1:

Proofs about mutually recursive definitions, be they datatypes, functions or inductive predicates, must be mutually recursive themselves. However, in your lemma, you only state the inductive property for eval_a, but not for eval_b. In the case for AB, you obviously want to use the induction hypothesis for eval_b, but as the lemma does not state the inductive property for eval_b, Isabelle does not know what it is. So it leaves it as a schematic variable ?P2.0.

So, you have to state two goals, say

lemma
  shows "eval_a a result ==> True"
  and "eval_b b result ==> True"

Then, the method induction a b will figure out that the first statement corresponds to A and the second to B.

The induction rule for the inductive predicates fails because this rule eliminates the inductive predicate (induction over datatypes only "eliminates" the type information, but this is not a HOL formula) and it cannot find the assumption for the second inductive predicate.

More examples on induction over mutually recursive objects can be found in src/HOL/Induct/Common_Patterns.thy.