CookBook/Package/Ind_Examples.thy
author Christian Urban <urbanc@in.tum.de>
Fri, 13 Feb 2009 14:15:28 +0000
changeset 115 039845fc96bd
parent 114 13fd0a83d3c3
child 116 c9ff326e3ce5
permissions -rw-r--r--
some update of the package introduction

theory Ind_Examples
imports Main LaTeXsugar
begin

section{* Examples of Inductive Definitions \label{sec:ind-examples} *}

text {*
  Let us first give three examples showing how to define inductive predicates
  by hand and then how to prove characteristic properties about them, such as 
  introduction rules and an induction principle. From these examples, we will 
  figure out a 
  general method for defining inductive predicates.  The aim in this section is 
  not to write proofs that are as beautiful as possible, but as close as 
  possible to the ML-code producing the proofs that we will develop later.

  As a first example, let us consider the transitive closure of a relation @{text
  R}. It is an inductive predicate characterized by the two introduction rules

  \begin{center}
  @{term[mode=Axiom] "trcl R x x"} \hspace{5mm}
  @{term[mode=Rule] "R x y \<Longrightarrow> trcl R y z \<Longrightarrow> trcl R x z"}
  \end{center}

  (FIXME first rule should be an ``axiom'')

  Note that the @{text trcl} predicate has two different kinds of parameters: the
  first parameter @{text R} stays \emph{fixed} throughout the definition, whereas
  the second and third parameter changes in the ``recursive call''.

  Since an inductively defined predicate is the least predicate closed under
  a collection of introduction rules, we define the predicate @{text "trcl R x y"} in
  such a way that it holds if and only if @{text "P x y"} holds for every predicate
  @{text P} closed under the rules above. This gives rise to the definition 
*}

definition "trcl R x y \<equiv> 
      \<forall>P. (\<forall>x. P x x) \<longrightarrow> (\<forall>x y z. R x y \<longrightarrow> P y z \<longrightarrow> P x z) \<longrightarrow> P x y"

text {*
  where we quantify over the predicate @{text P}. Note that we have to use the
  object implication @{text "\<longrightarrow>"} and object quantification @{text "\<forall>"} for stating
  this definition. The introduction rules and induction principles derived later
  should use the corresponding meta-connectives since they simplify the reasoning for
  the user.

  With this definition, the proof of the induction theorem for the transitive
  closure is almost immediate. It suffices to convert all the meta-level
  connectives in the induction rule to object-level connectives using the
  @{text atomize} proof method (Line 4), expand the definition of @{text trcl}
  (Line 5 and 6), eliminate the universal quantifier contained in it (Line 7),
  and then solve the goal by assumption (Line 8).

*}

lemma %linenos trcl_induct:
  assumes asm: "trcl R x y"
  shows "(\<And>x. P x x) \<Longrightarrow> (\<And>x y z. R x y \<Longrightarrow> P y z \<Longrightarrow> P x z) \<Longrightarrow> P x y"
apply(atomize (full))
apply(cut_tac asm)
apply(unfold trcl_def)
apply(drule spec[where x=P])
apply(assumption)
done

text {*
  The proofs for the introduction are slightly more complicated. We need to prove
  the goals @{prop "trcl R x x"} and @{prop "R x y \<Longrightarrow> trcl R y z \<Longrightarrow> trcl R x z"}.
  In order to prove the first goal, we again unfold the definition and
  then apply the introdution rules for @{text "\<forall>"} and @{text "\<longrightarrow>"} as often as possible.
  We then end up in the goal state

*}

(*<*)lemma "trcl R x x"
apply (unfold trcl_def)
apply (rule allI impI)+(*>*)
txt {* @{subgoals [display]} *}
(*<*)oops(*>*)

text {*
  The two assumptions correspond to the introduction rules, where @{text "trcl
  R"} has been replaced by P. Thus, all we have to do is to eliminate the
  universal quantifier in front of the first assumption, and then solve the
  goal by assumption. Thus the proof is:
*}

lemma trcl_base: "trcl R x x"
apply(unfold trcl_def)
apply(rule allI impI)+
apply(drule spec)
apply(assumption)
done

text {*
  Since the second introduction rule has premises, its proof is not as easy. After unfolding 
  the definitions and applying the introduction rules for @{text "\<forall>"} and @{text "\<longrightarrow>"}, we 
  get the goal state
*}

(*<*)lemma "R x y \<Longrightarrow> trcl R y z \<Longrightarrow> trcl R x z"
apply (unfold trcl_def)
apply (rule allI impI)+(*>*)
txt {*@{subgoals [display]} *}
(*<*)oops(*>*)

text {*
  The third and fourth assumption corresponds to the first and second
  introduction rule, respectively, whereas the first and second assumption
  corresponds to the pre\-mises of the introduction rule. Since we want to prove
  the second introduction rule, we apply the fourth assumption to the goal
  @{term "P x z"}. In order for the assumption to be applicable as a rule, we have to
  eliminate the universal quantifier and turn the object-level implications
  into meta-level ones. This can be accomplished using the @{text rule_format}
  attribute. Applying the assumption produces the two new subgoals
*}

(*<*)lemma "R x y \<Longrightarrow> trcl R y z \<Longrightarrow> trcl R x z"
apply (unfold trcl_def)
apply (rule allI impI)+
proof -
  case (goal1 P)
  have a4: "\<forall>x y z. R x y \<longrightarrow> P y z \<longrightarrow> P x z" by fact
  show ?case
    apply (rule a4[rule_format])(*>*)
txt {*@{subgoals [display]} *}
(*<*)oops(*>*)

text {* 
  which can be
  solved using the first and second assumption. The second assumption again
  involves a quantifier and an implications that have to be eliminated before it
  can be applied. To avoid potential problems with higher-order unification, 
  we should explcitly instantiate the universally quantified
  predicate variable to @{text "P"} and also match explicitly the implications
  with the the third and fourth assumption. This gives the proof:
*}


lemma trcl_step: "R x y \<Longrightarrow> trcl R y z \<Longrightarrow> trcl R x z"
apply(unfold trcl_def)
apply(rule allI impI)+
proof -
  case (goal1 P)
  have a1: "R x y" by fact
  have a2: "\<forall>P. (\<forall>x. P x x) 
                  \<longrightarrow> (\<forall>x y z. R x y \<longrightarrow> P y z \<longrightarrow> P x z) \<longrightarrow> P y z" by fact
  have a3: "\<forall>x. P x x" by fact
  have a4: "\<forall>x y z. R x y \<longrightarrow> P y z \<longrightarrow> P x z" by fact
  show "P x z"
    apply(rule a4[rule_format])
    apply(rule a1)
    apply(rule a2 [THEN spec[where x=P], THEN mp, THEN mp, OF a3, OF a4])
    done
qed

text {*
  It might be surprising that we are not using the automatic tactics in
  Isabelle in order to prove the lemmas we are after. After all @{text "blast"}
  would easily dispense of the lemmas.
*}

lemma trcl_step_blast: "R x y \<Longrightarrow> trcl R y z \<Longrightarrow> trcl R x z"
apply(unfold trcl_def)
apply(blast)
done

text {*
  Experience has shown that it is generally a bad idea to rely heavily on @{term blast}
  and the like in automated proofs. The reason is that you do not have precise control 
  over them (the user can, for example, declare new intro- or simplification rules that 
  can throw automatic tactics off course) and also it is very hard to debug
  proofs involving automatic tactics. Therefore whenever possible, automatic tactics
  should be avoided or constrained. 
  

  This method of defining inductive predicates generalises also to mutually inductive
  predicates. The next example defines the predicates @{text even} and @{text odd} 
  characterised by the following rules:
 
  \begin{center}
  @{term[mode=Axiom] "even (0::nat)"} \hspace{5mm}
  @{term[mode=Rule] "odd m \<Longrightarrow> even (Suc m)"} \hspace{5mm}
  @{term[mode=Rule] "even m \<Longrightarrow> odd (Suc m)"}
  \end{center}
  
  Since the predicates are mutually inductive, each definition 
  quantifies over both predicates, below named @{text P} and @{text Q}.
*}

definition "even n \<equiv> 
  \<forall>P Q. P 0 \<longrightarrow> (\<forall>m. Q m \<longrightarrow> P (Suc m)) 
             \<longrightarrow> (\<forall>m. P m \<longrightarrow> Q (Suc m)) \<longrightarrow> P n"

definition "odd n \<equiv>
  \<forall>P Q. P 0 \<longrightarrow> (\<forall>m. Q m \<longrightarrow> P (Suc m)) 
             \<longrightarrow> (\<forall>m. P m \<longrightarrow> Q (Suc m)) \<longrightarrow> Q n"

text {*
  For proving the induction rule, we use exactly the same technique as in the transitive
  closure example:
*}

lemma even_induct:
  assumes asm: "even n"
  shows "P 0 \<Longrightarrow> 
             (\<And>m. Q m \<Longrightarrow> P (Suc m)) \<Longrightarrow> (\<And>m. P m \<Longrightarrow> Q (Suc m)) \<Longrightarrow> P n"
apply(atomize (full))
apply(cut_tac asm)
apply(unfold even_def)
apply(drule spec[where x=P])
apply(drule spec[where x=Q])
apply(assumption)
done

text {*
  We omit the other induction rule having @{term "Q n"} as conclusion.
  The proofs of the introduction rules are also very similar to the ones in the
  @{text "trcl"}-example. We only show the proof of the second introduction rule:
*}

lemma evenS: "odd m \<Longrightarrow> even (Suc m)"
apply (unfold odd_def even_def)
apply (rule allI impI)+
proof -
  case (goal1 P)
  have a1: "\<forall>P Q. P 0 \<longrightarrow> (\<forall>m. Q m \<longrightarrow> P (Suc m)) 
                             \<longrightarrow> (\<forall>m. P m \<longrightarrow> Q (Suc m)) \<longrightarrow> Q m" by fact
  have a2: "P 0" by fact
  have a3: "\<forall>m. Q m \<longrightarrow> P (Suc m)" by fact
  have a4: "\<forall>m. P m \<longrightarrow> Q (Suc m)" by fact
  show "P (Suc m)"
    apply(rule a3[rule_format])
    apply(rule a1[THEN spec[where x=P], THEN spec[where x=Q],
	THEN mp, THEN mp, THEN mp, OF a2, OF a3, OF a4])
    done
qed

text {*
  As a final example, we definethe accessible part of a relation @{text R} characterised 
  by the introduction rule
  
  \begin{center}
  @{term[mode=Rule] "(\<forall>y. R y x \<longrightarrow> accpart R y) \<Longrightarrow> accpart R x"}
  \end{center}

  whose premise involves a universal quantifier and an implication. The
  definition of @{text accpart} is as follows:
*}

definition "accpart R x \<equiv> \<forall>P. (\<forall>x. (\<forall>y. R y x \<longrightarrow> P y) \<longrightarrow> P x) \<longrightarrow> P x"

text {*
  The proof of the induction theorem is again straightforward.
*}

lemma accpart_induct:
  assumes asm: "accpart R x"
  shows "(\<And>x. (\<forall>y. R y x \<longrightarrow> P y) \<Longrightarrow> P x) \<Longrightarrow> P x"
apply(atomize (full))
apply(cut_tac asm)
apply(unfold accpart_def)
apply(drule spec[where x=P])
apply(assumption)
done

text {*
  Proving the introduction rule is a little more complicated, because the quantifier
  and the implication in the premise. We first convert the meta-level universal quantifier
  and implication to their object-level counterparts. Unfolding the definition of
  @{text accpart} and applying the introduction rules for @{text "\<forall>"} and @{text "\<longrightarrow>"}
  yields the following proof state:
*}

(*<*)lemma accpartI: "(\<forall>y. R y x \<longrightarrow> accpart R y) \<Longrightarrow> accpart R x"
apply (unfold accpart_def)
apply (rule allI impI)+(*>*)
txt {* @{subgoals [display]} *}
(*<*)oops(*>*)

text {*
  Applying the second assumption produces a proof state with the new local assumption
  @{term "R y x"}, which will then be used to solve the goal @{term "P y"} using the
  first assumption.
*}

lemma %small accpartI: "(\<forall>y. R y x \<longrightarrow> accpart R y) \<Longrightarrow> accpart R x"
apply (unfold accpart_def)
apply (rule allI impI)+
proof -
  case (goal1 P)
  have a1: "\<forall>y. R y x \<longrightarrow> 
                   (\<forall>P. (\<forall>x. (\<forall>y. R y x \<longrightarrow> P y) \<longrightarrow> P x) \<longrightarrow> P y)" by fact
  have a2: "\<forall>x. (\<forall>y. R y x \<longrightarrow> P y) \<longrightarrow> P x" by fact
  show "P x"
    apply(rule a2[rule_format])
    proof -
      case (goal1 y)
      have a3: "R y x" by fact
      show "P y"
      apply(rule a1[THEN spec[where x=y], THEN mp, OF a3, 
            THEN spec[where x=P], THEN mp, OF a2])
      done
  qed
qed

text {*
  Now the point is to figure out what the automatic proofs should do. For
  this it might be instructive to look at the general construction principle
  of inductive definitions, which we shall do next.
*}

end