Theory RTranCl

(*  Author:  Gertrud Bauer, Tobias Nipkow  *)

section ‹Transitive Closure of Successor List Function›

theory RTranCl
imports Main
begin

text‹The reflexive transitive closure of a relation induced by a
function of type @{typ"'a ⇒ 'a list"}. Instead of defining the closure
again it would have been simpler to take @{term"{(x,y) . y ∈ set(f x)}*"}.›

abbreviation (input)
  in_set :: "'a ⇒ ('a ⇒ 'b list) ⇒ 'b ⇒ bool" (‹_ [_]→ _› [55,0,55] 50) where
  "g [succs]→ g' == g' ∈ set (succs g)"

inductive_set
  RTranCl :: "('a ⇒ 'a list) ⇒ ('a * 'a) set"
  and in_RTranCl :: "'a ⇒ ('a ⇒ 'a list) ⇒ 'a ⇒ bool"
    (‹_ [_]→* _› [55,0,55] 50)
  for succs :: "'a ⇒ 'a list"
where
  "g [succs]→* g' ≡ (g,g') ∈ RTranCl succs"
| refl: "g [succs]→* g"
| succs: "g [succs]→ g' ⟹ g' [succs]→* g'' ⟹ g [succs]→* g''"

inductive_cases RTranCl_elim: "(h,h') : RTranCl succs"

lemma RTranCl_induct(*<*) [induct set: RTranCl, consumes 1, case_names refl succs] (*>*):
 "(h, h') ∈ RTranCl succs ⟹ 
  P h ⟹ 
  (⋀g g'. g' ∈ set (succs g) ⟹ P g ⟹ P g') ⟹ 
  P h'"
proof -
  assume s: "⋀g g'. g' ∈ set (succs g) ⟹ P g ⟹ P g'"
  assume "(h, h') ∈ RTranCl succs" "P h"
  then show "P h'"
  proof (induct rule: RTranCl.induct)
    fix g assume "P g" then show "P g" . 
  next
    fix g g' g''
    assume IH: "P g' ⟹ P g''"
    assume "g' ∈ set(succs g)" "P g"
    then have "P g'" by (rule s)
    then show "P g''" by (rule IH)
  qed
qed

definition invariant :: "('a ⇒ bool) ⇒ ('a ⇒ 'a list) ⇒ bool" where
"invariant P succs ≡ ∀g g'. g' ∈ set(succs g) ⟶ P g ⟶ P g'"

lemma invariantE:
  "invariant P succs  ⟹ g [succs]→ g' ⟹ P g ⟹ P g'"
by(simp add:invariant_def)

lemma inv_subset:
 "invariant P f ⟹ (⋀g. P g ⟹ set(f' g) ⊆ set(f g)) ⟹ invariant P f'"
by(auto simp:invariant_def)

lemma RTranCl_inv:
  "invariant P succs ⟹ (g,g') ∈ RTranCl succs ⟹ P g ⟹ P g'"
by (erule RTranCl_induct)(auto simp:invariant_def)

lemma RTranCl_subset2:
assumes a: "(s,g) : RTranCl f"
shows "(⋀g. (s,g) ∈ RTranCl f ⟹ set(f g) ⊆ set(h g)) ⟹ (s,g) : RTranCl h"
using a
proof (induct rule: RTranCl.induct)
  case refl show ?case by(rule RTranCl.intros)
next
  case succs thus ?case by(blast intro: RTranCl.intros)
qed

end