Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/Isabelle/Archive-of-Formal-Proofs/thys/Resolution_FOL/   (Sammlung formaler Beweise Version 2026-5©)  Datei vom 31.4.2026 mit Größe 30 kB image not shown  

Quelle  Tree.thy

  Sprache: Isabelle
 

section Trees

theory Tree imports Main begin

text Sometimes it is nice to think of @{typ bool}s as directions in a binary tree
hide_const (open) Left Right
type_synonym dir = bool
definition Left :: bool where "Left = True"
definition Right :: bool where "Right = False"
declare Left_def [simp]
declare Right_def [simp]

datatype tree =
  Leaf
| Branching (ltree: tree) (rtree: tree) 


subsection Sizes

fun treesize :: "tree ==> nat" where
  "treesize Leaf = 0"
"treesize (Branching l r) = 1 + treesize l + treesize r"

lemma treesize_Leaf:
  assumes "treesize T = 0"
  shows "T = Leaf"
  using assms by (cases T) auto

lemma treesize_Branching:
  assumes "treesize T = Suc n"
  shows "l r. T = Branching l r" 
  using assms by (cases T) auto


subsection Paths

fun path :: "dir list ==> tree ==> bool" where
  "path [] T True"
"path (d#ds) (Branching T1 T2) (if d then path ds T1 else path ds T2)"
"path _ _ False"

lemma path_inv_Leaf: "path p Leaf p = []"
  by (induction p)  auto

lemma path_inv_Cons: "path (a#ds) T (l r. T=Branching l r)"
  by  (cases T) (auto simp add: path_inv_Leaf)


lemma path_inv_Branching_Left: "path (Left#p) (Branching l r) path p l"
  using Left_def Right_def path.cases by (induction p) auto

lemma path_inv_Branching_Right: "path (Right#p) (Branching l r) path p r"
using Left_def Right_def path.cases by (induction p)  auto


lemma path_inv_Branching: 
  "path p (Branching l r) (p=[] (a p'. p=a#p' (a path p' l) (¬a path p' r)))" (is "?L ?R")
proof
  assume ?L then show ?R by (induction p) auto
next
  assume r: ?R
  then show ?L
    proof
      assume "p = []" then show ?L by auto
    next
      assume "a p'. p=a#p' (a path p' l) (¬a path p' r)"
      then obtain a p' where "p=a#p' (a path p' l) (¬a path p' r)" by auto
      then show ?L by (cases a) auto
    qed
qed

lemma path_prefix: 
  assumes "path (ds1@ds2) T"
  shows "path ds1 T"
using assms proof (induction ds1 arbitrary: T)
  case (Cons a ds1)
  then have "l r. T = Branching l r" using path_inv_Leaf by (cases T) auto
  then obtain l r where p_lr: "T = Branching l r" by auto
  show ?case
    proof (cases a)
      assume atrue: "a"
      then have "path ((ds1) @ ds2) l" using p_lr Cons(2) path_inv_Branching by auto
      then have "path ds1 l" using Cons(1by auto
      then show "path (a # ds1) T" using p_lr atrue by auto
    next
      assume afalse: "¬a"
      then have "path ((ds1) @ ds2) r" using p_lr Cons(2) path_inv_Branching by auto
      then have "path ds1 r" using Cons(1by auto
      then show "path (a # ds1) T" using p_lr afalse by auto
    qed
next
  case (Nil) then show ?case  by auto
qed


subsection Branches

fun branch :: "dir list ==> tree ==> bool" where
  "branch [] Leaf True"    
"branch (d # ds) (Branching l r) (if d then branch ds l else branch ds r)"
"branch _ _ False"

lemma has_branch: "b. branch b T"
proof (induction T)
  case (Leaf) 
  have "branch [] Leaf" by auto
  then show ?case by blast
next
  case (Branching T1 T2)
  then obtain b where "branch b T1" by auto
  then have "branch (Left#b) (Branching T1 T2)"  by auto
  then show ?case by blast
qed

lemma branch_inv_Leaf: "branch b Leaf b = []"
by (cases b) auto

lemma branch_inv_Branching_Left:  
  "branch (Left#b) (Branching l r) branch b l"
by auto

lemma branch_inv_Branching_Right: 
  "branch (Right#b) (Branching l r) branch b r"
by auto

lemma branch_inv_Branching: 
  "branch b (Branching l r)
     (a b'. b=a#b' (a branch b' l) (¬a branch b' r))"
by (induction b) auto

lemma branch_inv_Leaf2:
  "T = Leaf (b. branch b T b = [])"
proof -
  {
    assume "T=Leaf"
    then have "b. branch b T b = []" using branch_inv_Leaf by auto
  }
  moreover 
  {
    assume "b. branch b T b = []"
    then have "b. branch b T ¬(a b'. b = a # b')" by auto
    then have "b. branch b T ¬(l r. branch b (Branching l r))" 
      using branch_inv_Branching by auto
    then have "T=Leaf" using has_branch[of T] by (metis branch.elims(2))
  }
  ultimately show "T = Leaf (b. branch b T b = [])" by auto
qed

lemma branch_is_path: 
  assumes"branch ds T"
  shows "path ds T"
using assms proof (induction T arbitrary: ds)
  case Leaf
  then have "ds = []" using branch_inv_Leaf by auto
  then show ?case  by auto
next
  case (Branching T1 T2
  then obtain a b where ds_p: "ds = a # b (a branch b T1) (¬ a branch b T2)" using branch_inv_Branching[of ds] by blast
  then have "(a path b T1) (¬a path b T2)" using Branching by auto
  then show "?case" using ds_p by (cases a) auto
qed

lemma Branching_Leaf_Leaf_Tree:
  assumes "T = Branching T1 T2"
  shows "(B. branch (B@[True]) T branch (B@[False]) T)"
using assms proof (induction T arbitrary: T1 T2)
  case Leaf then show ?case by auto
next
  case (Branching T1' T2')
  {
    assume "T1'=Leaf T2'=Leaf"
    then have "branch ([] @ [True]) (Branching T1' T2') branch ([] @ [False]) (Branching T1' T2')" by auto
    then have ?case by metis
  }
  moreover
  {
    fix T11 T12
    assume "T1' = Branching T11 T12"
    then obtain B where "branch (B @ [True]) T1'
                        branch (B @ [False]) T1'" using Branching by blast
    then have "branch (([True] @ B) @ [True]) (Branching T1' T2')
              branch (([True] @ B) @ [False]) (Branching T1' T2')" by auto
    then have ?case by blast
  }
  moreover
  {
    fix T11 T12
    assume "T2' = Branching T11 T12"
    then obtain B where "branch (B @ [True]) T2'
                        branch (B @ [False]) T2'" using Branching by blast
    then have "branch (([False] @ B) @ [True]) (Branching T1' T2')
              branch (([False] @ B) @ [False]) (Branching T1' T2')" by auto
    then have ?case by blast
  }
  ultimately show ?case using tree.exhaust by blast
qed


subsection Internal Paths

fun internal :: "dir list ==> tree ==> bool" where
  "internal [] (Branching l r) True"
"internal (d#ds) (Branching l r) (if d then internal ds l else internal ds r)"
"internal _ _ False"

lemma internal_inv_Leaf: "¬internal b Leaf" using internal.simps by blast

lemma internal_inv_Branching_Left:  
  "internal (Left#b) (Branching l r) internal b l" by auto

lemma internal_inv_Branching_Right: 
  "internal (Right#b) (Branching l r) internal b r"
by auto

lemma internal_inv_Branching: 
  "internal p (Branching l r) (p=[] (a p'. p=a#p' (a internal p' l) (¬a internal p' r)))" (is "?L ?R")
proof
  assume ?L then show ?R by (metis internal.simps(2) neq_Nil_conv) 
next
  assume r: ?R
  then show ?L
    proof
      assume "p = []" then show ?L by auto
    next
      assume "a p'. p=a#p' (a internal p' l) (¬a internal p' r)"
      then obtain a p' where "p=a#p' (a internal p' l) (¬a internal p' r)" by auto
      then show ?L by (cases a) auto
    qed
qed

lemma internal_is_path: 
  assumes "internal ds T"
  shows "path ds T"
using assms proof (induction T arbitrary: ds)
  case Leaf
  then have "False" using internal_inv_Leaf by auto
  then show ?case by auto
next
  case (Branching T1 T2
  then obtain a b where ds_p: "ds=[] ds = a # b (a internal b T1) (¬ a internal b T2)" using internal_inv_Branching by blast
  then have "ds = [] (a path b T1) (¬a path b T2)" using Branching by auto
  then show "?case" using ds_p by (cases a) auto
qed

lemma internal_prefix:
  assumes "internal (ds1@ds2@[d]) T"
  shows "internal ds1 T" (* more or less copy paste of path_prefix *)
using assms proof (induction ds1 arbitrary: T)
  case (Cons a ds1)
  then have "l r. T = Branching l r" using internal_inv_Leaf by (cases T) auto
  then obtain l r where p_lr: "T = Branching l r" by auto
  show ?case
    proof (cases a)
      assume atrue: "a"
      then have "internal ((ds1) @ ds2 @[d]) l" using p_lr Cons(2) internal_inv_Branching by auto
      then have "internal ds1 l" using Cons(1by auto
      then show "internal (a # ds1) T" using p_lr atrue by auto
    next
      assume afalse: "~a"
      then have "internal ((ds1) @ ds2 @[d]) r" using p_lr Cons(2) internal_inv_Branching by auto
      then have "internal ds1 r" using Cons(1by auto
      then show "internal (a # ds1) T" using p_lr afalse by auto
    qed
next
  case (Nil)
  then have "l r. T = Branching l r" using internal_inv_Leaf by (cases T) auto 
  then show ?case by auto
qed


lemma internal_branch:
  assumes "branch (ds1@ds2@[d]) T"
  shows "internal ds1 T" (* more or less copy paste of path_prefix *)
using assms proof (induction ds1 arbitrary: T)
  case (Cons a ds1)
  then have "l r. T = Branching l r" using branch_inv_Leaf by (cases T) auto
  then obtain l r where p_lr: "T = Branching l r" by auto
  show ?case
    proof (cases a)
      assume atrue: "a"
      then have "branch (ds1 @ ds2 @ [d]) l" using p_lr Cons(2) branch_inv_Branching by auto
      then have "internal ds1 l" using Cons(1by auto
      then show "internal (a # ds1) T" using p_lr atrue by auto
    next
      assume afalse: "~a"
      then have "branch ((ds1) @ ds2 @[d]) r" using p_lr Cons(2) branch_inv_Branching by auto
      then have "internal ds1 r" using Cons(1by auto
      then show "internal (a # ds1) T" using p_lr afalse by auto
    qed
next
  case (Nil)
  then have "l r. T = Branching l r" using branch_inv_Leaf by (cases T) auto 
  then show ?case by auto
qed


fun parent :: "dir list ==> dir list" where
  "parent ds = tl ds"


subsection Deleting Nodes

fun delete :: "dir list ==> tree ==> tree" where
  "delete [] T = Leaf"
"delete (True#ds) (Branching T1 T2) = Branching (delete ds T1) T2"
"delete (False#ds) (Branching T1 T2) = Branching T1 (delete ds T2)"
"delete (a#ds) Leaf = Leaf"

lemma delete_Leaf: "delete T Leaf = Leaf" by (cases T) auto

lemma path_delete: 
  assumes "path p (delete ds T)"
  shows "path p T " (* What a huge proof... But the four cases can be proven shorter *)
using assms proof (induction p arbitrary: T ds)
  case Nil 
  then show ?case by simp
next
  case (Cons a p)
  then obtain b ds' where bds'_p: "ds=b#ds'" by (cases ds) auto

  have "dT1 dT2. delete ds T = Branching dT1 dT2" using Cons path_inv_Cons by auto
  then obtain dT1 dT2 where "delete ds T = Branching dT1 dT2" by auto

  then have "T1 T2. T=Branching T1 T2" (* Is there a lemma hidden here that I could extract? *)
        by (cases T; cases ds) auto
  then obtain T1 T2 where T1T2_p: "T=Branching T1 T2" by auto

  {
    assume a_p: "a"
    assume b_p: "¬b"
    have "path (a # p) (delete ds T)" using Cons by -
    then have "path (a # p) (Branching (T1) (delete ds' T2))" using b_p bds'_p T1T2_p by auto
    then have "path p T1" using a_p by auto
    then have ?case using T1T2_p a_p by auto
  }
  moreover
  {
    assume a_p: "¬a"
    assume b_p: "b"
    have "path (a # p) (delete ds T)" using Cons by -
    then have "path (a # p) (Branching (delete ds' T1) T2)" using b_p bds'_p T1T2_p by auto
    then have "path p T2" using a_p by auto
    then have ?case using T1T2_p a_p by auto
  }
  moreover
  {
    assume a_p: "a"
    assume b_p: "b"
    have "path (a # p) (delete ds T)" using Cons by -
    then have "path (a # p) (Branching (delete ds' T1) T2)" using b_p bds'_p T1T2_p by auto
    then have "path p (delete ds' T1)" using a_p by auto
    then have "path p T1" using Cons by auto
    then have ?case using T1T2_p a_p by auto
  }
  moreover
  {
    assume a_p: "¬a"
    assume b_p: "¬b"
    have "path (a # p) (delete ds T)" using Cons by -
    then have "path (a # p) (Branching T1 (delete ds' T2))" using b_p bds'_p T1T2_p by auto
    then have "path p (delete ds' T2)" using a_p by auto
    then have "path p T2" using Cons by auto
    then have ?case using T1T2_p a_p by auto
  }
  ultimately show ?case by blast
qed

lemma branch_delete:
  assumes "branch p (delete ds T)"
  shows "branch p T p=ds" (* Adapted from above *)
using assms proof (induction p arbitrary: T ds)
  case Nil 
  then have "delete ds T = Leaf" by (cases "delete ds T") auto
  then have "ds = [] T = Leaf" using delete.elims by blast 
  then show ?case by auto
next
  case (Cons a p)
  then obtain b ds' where bds'_p: "ds=b#ds'" by (cases ds) auto

  have "dT1 dT2. delete ds T = Branching dT1 dT2" using Cons path_inv_Cons branch_is_path by blast
  then obtain dT1 dT2 where "delete ds T = Branching dT1 dT2" by auto

  then have "T1 T2. T=Branching T1 T2" (* Is there a lemma hidden here that I could extract? *)
        by (cases T; cases ds) auto
  then obtain T1 T2 where T1T2_p: "T=Branching T1 T2" by auto

  {
    assume a_p: "a"
    assume b_p: "¬b"
    have "branch (a # p) (delete ds T)" using Cons by -
    then have "branch (a # p) (Branching (T1) (delete ds' T2))" using b_p bds'_p T1T2_p by auto
    then have "branch p T1" using a_p by auto
    then have ?case using T1T2_p a_p by auto
  }
  moreover
  {
    assume a_p: "¬a"
    assume b_p: "b"
    have "branch (a # p) (delete ds T)" using Cons by -
    then have "branch (a # p) (Branching (delete ds' T1) T2)" using b_p bds'_p T1T2_p by auto
    then have "branch p T2" using a_p by auto
    then have ?case using T1T2_p a_p by auto
  }
  moreover
  {
    assume a_p: "a"
    assume b_p: "b"
    have "branch (a # p) (delete ds T)" using Cons by -
    then have "branch (a # p) (Branching (delete ds' T1) T2)" using b_p bds'_p T1T2_p by auto
    then have "branch p (delete ds' T1)" using a_p by auto
    then have "branch p T1 p = ds'" using Cons by metis
    then have ?case using T1T2_p a_p using bds'_p a_p b_p by auto
  }
  moreover
  {
    assume a_p: "¬a"
    assume b_p: "¬b"
    have "branch (a # p) (delete ds T)" using Cons by -
    then have "branch (a # p) (Branching T1 (delete ds' T2))" using b_p bds'_p T1T2_p by auto
    then have "branch p (delete ds' T2)" using a_p by auto
    then have "branch p T2 p = ds'" using Cons by metis
    then have ?case using T1T2_p a_p using bds'_p a_p b_p by auto
  }
  ultimately show ?case by blast
qed
  

lemma branch_delete_postfix: 
  assumes "path p (delete ds T)"
  shows "¬(c cs. p = ds @ c#cs)" (* Adapted from previous proof *)
using assms proof (induction p arbitrary: T ds)
  case Nil then show ?case by simp
next
  case (Cons a p)
  then obtain b ds' where bds'_p: "ds=b#ds'" by (cases ds) auto

  have "dT1 dT2. delete ds T = Branching dT1 dT2" using Cons path_inv_Cons by auto
  then obtain dT1 dT2 where "delete ds T = Branching dT1 dT2" by auto

  then have "T1 T2. T=Branching T1 T2" (* Is there a lemma hidden here that I could extract? *)
        by (cases T; cases ds) auto
  then obtain T1 T2 where T1T2_p: "T=Branching T1 T2" by auto

  {
    assume a_p: "a"
    assume b_p: "¬b"
    then have ?case using T1T2_p a_p b_p bds'_p by auto
  }
  moreover
  {
    assume a_p: "¬a"
    assume b_p: "b"
    then have ?case using T1T2_p a_p b_p bds'_p by auto
  }
  moreover
  {
    assume a_p: "a"
    assume b_p: "b"
    have "path (a # p) (delete ds T)" using Cons by -
    then have "path (a # p) (Branching (delete ds' T1) T2)" using b_p bds'_p T1T2_p by auto
    then have "path p (delete ds' T1)" using a_p by auto
    then have "¬ (c cs. p = ds' @ c # cs)" using Cons by auto
    then have ?case using T1T2_p a_p b_p bds'_p by auto
  }
  moreover
  {
    assume a_p: "¬a"
    assume b_p: "¬b"
    have "path (a # p) (delete ds T)" using Cons by -
    then have "path (a # p) (Branching T1 (delete ds' T2))" using b_p bds'_p T1T2_p by auto
    then have "path p (delete ds' T2)" using a_p by auto
    then have "¬ (c cs. p = ds' @ c # cs)" using Cons by auto
    then have ?case using T1T2_p a_p b_p bds'_p by auto
  }
  ultimately show ?case by blast
qed

lemma treezise_delete: 
  assumes "internal p T"
  shows "treesize (delete p T) < treesize T"
using assms proof (induction p arbitrary: T)
  case (Nil)
  then have "T1 T2. T = Branching T1 T2" by (cases T) auto
  then obtain T1 T2 where T1T2_p: "T = Branching T1 T2" by auto 
  then show ?case by auto
next
  case (Cons a p) 
  then have "T1 T2. T = Branching T1 T2" using path_inv_Cons internal_is_path by blast
  then obtain T1 T2 where T1T2_p: "T = Branching T1 T2" by auto
  show ?case
    proof (cases a)
      assume a_p: a
      from a_p have "delete (a#p) T = (Branching (delete p T1) T2)" using T1T2_p by auto
      moreover
      from a_p have "internal p T1" using T1T2_p Cons by auto
      then have "treesize (delete p T1) < treesize T1" using Cons by auto
      ultimately
      show ?thesis using T1T2_p by auto
    next
      assume a_p: "¬a"
      from a_p have "delete (a#p) T = (Branching T1 (delete p T2))" using T1T2_p by auto
      moreover
      from a_p have "internal p T2" using T1T2_p Cons by auto
      then have "treesize (delete p T2) < treesize T2" using Cons by auto
      ultimately
      show ?thesis using T1T2_p by auto
    qed
qed


fun cutoff :: "(dir list ==> bool) ==> dir list ==> tree ==> tree" where
  "cutoff red ds (Branching T1 T2) =
     (if red ds then Leaf else Branching (cutoff red (ds@[Left]) T1) (cutoff red (ds@[Right]) T2))"
"cutoff red ds Leaf = Leaf"
text Initially you should call @{const cutoff} with @{term "ds = []"}.
 If all branches are red, then @{const cutoff} gives a subtree.
 If all branches are red, then so are the ones in @{const cutoff}.
 The internal paths of @{const cutoff} are not red.


lemma treesize_cutoff: "treesize (cutoff red ds T) treesize T"
proof (induction T arbitrary: ds)
  case Leaf then show ?case by auto
next
  case (Branching T1 T2) 
  then have "treesize (cutoff red (ds@[Left]) T1) + treesize (cutoff red (ds@[Right]) T2) treesize T1 + treesize T2" using add_mono by blast
  then show ?case by auto
qed

abbreviation anypath :: "tree ==> (dir list ==> bool) ==> bool" where
  "anypath T P p. path p T P p"

abbreviation anybranch :: "tree ==> (dir list ==> bool) ==> bool" where
  "anybranch T P p. branch p T P p"

abbreviation anyinternal :: "tree ==> (dir list ==> bool) ==> bool" where
  "anyinternal T P p. internal p T P p"

lemma cutoff_branch': 
  assumes "anybranch T (λb. red(ds@b))"
  shows "anybranch (cutoff red ds T) (λb. red(ds@b))"
using assms proof (induction T arbitrary: ds) (* This proof seems a bit excessive for such a simple theorem *)
  case (Leaf) 
  let ?T = "cutoff red ds Leaf"
  {
    fix b
    assume "branch b ?T"
    then have "branch b Leaf" by auto
    then have "red(ds@b)" using Leaf by auto
  }
  then show ?case by simp
next
  case (Branching T1 T2)
  let ?T = "cutoff red ds (Branching T1 T2)"
  from Branching have "p. branch (Left#p) (Branching T1 T2) red (ds @ (Left#p))" by blast
  then have "p. branch p T1 red (ds @ (Left#p))"  by auto
  then have "anybranch T1 (λp. red ((ds @ [Left]) @ p))" by auto
  then have aa: "anybranch (cutoff red (ds @ [Left]) T1) (λp. red ((ds @ [Left]) @ p))
         " using Branching by blast

  from Branching have "p. branch (Right#p) (Branching T1 T2) red (ds @ (Right#p))" by blast
  then have "p. branch p T2 red (ds @ (Right#p))" by auto
  then have "anybranch T2 (λp. red ((ds @ [Right]) @ p))" by auto
  then have bb: "anybranch (cutoff red (ds @ [Right]) T2) (λp. red ((ds @ [Right]) @ p))
         " using Branching by blast
  {           
    fix b
    assume b_p: "branch b ?T"
    have "red ds ¬red ds" by auto
    then have "red(ds@b)"
      proof
        assume ds_p: "red ds"
        then have "?T = Leaf" by auto
        then have "b = []" using b_p branch_inv_Leaf by auto
        then show "red(ds@b)" using ds_p by auto
      next
        assume ds_p: "¬red ds"
        let ?T1' = "cutoff red (ds@[Left]) T1"
        let ?T2' = "cutoff red (ds@[Right]) T2"
        from ds_p have "?T = Branching ?T1' ?T2'" by auto
        from this b_p obtain a b' where "b = a # b' (a branch b' ?T1') (¬a branch b' ?T2' )" using branch_inv_Branching[of b ?T1' ?T2'] by auto
        then show "red(ds@b)" using aa bb by (cases a) auto
      qed
  }
  then show ?case by blast
qed

lemma cutoff_branch: 
  assumes "anybranch T (λp. red p)"
  shows "anybranch (cutoff red [] T) (λp. red p)" 
  using assms cutoff_branch'[of T red "[]"by auto

lemma cutoff_internal': 
  assumes "anybranch T (λb. red(ds@b))" 
  shows "anyinternal (cutoff red ds T) (λb. ¬red(ds@b))"
using assms proof (induction T arbitrary: ds) (* This proof seems a bit excessive for such a simple theorem *)
  case (Leaf) then show ?case using internal_inv_Leaf by simp
next                                                     
  case (Branching T1 T2)
  let ?T = "cutoff red ds (Branching T1 T2)"
  from Branching have "p. branch (Left#p) (Branching T1 T2) red (ds @ (Left#p))" by blast
  then have "p. branch p T1 red (ds @ (Left#p))" by auto
  then have "anybranch T1 (λp. red ((ds @ [Left]) @ p))" by auto
  then have aa: "anyinternal (cutoff red (ds @ [Left]) T1) (λp. ¬ red ((ds @ [Left]) @ p))" using Branching by blast

  from Branching have "p. branch (Right#p) (Branching T1 T2) red (ds @ (Right#p))" by blast
  then have "p. branch p T2 red (ds @ (Right#p))" by auto
  then have "anybranch T2 (λp. red ((ds @ [Right]) @ p))" by auto
  then have bb: "anyinternal (cutoff red (ds @ [Right]) T2) (λp. ¬ red ((ds @ [Right]) @ p))" using Branching by blast
  {
    fix p
    assume b_p: "internal p ?T"
    then have ds_p: "¬red ds" using internal_inv_Leaf by auto
    have "p=[] p[]" by auto
    then have "¬red(ds@p)"
      proof
        assume "p=[]" then show "¬red(ds@p)" using ds_p by auto
      next
        let ?T1' = "cutoff red (ds@[Left]) T1"
        let ?T2' = "cutoff red (ds@[Right]) T2"
        assume "p[]"
        moreover
        have "?T = Branching ?T1' ?T2'" using ds_p by auto
        ultimately
        obtain a p' where b_p: "p = a # p'
             (a internal p' (cutoff red (ds @ [Left]) T1))
             (¬ a internal p' (cutoff red (ds @ [Right]) T2))" 
          using b_p internal_inv_Branching[of p ?T1' ?T2'] by auto
        then have "¬red(ds @ [a] @ p')" using aa bb by (cases a) auto
        then show "¬red(ds @ p)" using b_p by simp
      qed
  }
  then show ?case by blast
qed

lemma cutoff_internal:
  assumes  "anybranch T red"
  shows "anyinternal (cutoff red [] T) (λp. ¬red p)" 
  using assms cutoff_internal'[of T red "[]"by auto

lemma cutoff_branch_internal': 
  assumes "anybranch T red"
  shows "anyinternal (cutoff red [] T) (λp. ¬red p) anybranch (cutoff red [] T) (λp. red p)" 
  using assms cutoff_internal[of T] cutoff_branch[of T] by blast

lemma cutoff_branch_internal: 
  assumes "anybranch T red"
  shows "T'. anyinternal T' (λp. ¬red p) anybranch T' (λp. red p)" 
  using assms cutoff_branch_internal' by blast


section Possibly Infinite Trees
text Possibly infinite trees are of type @{typ "dir list set"}.

abbreviation wf_tree :: "dir list set ==> bool" where
  "wf_tree T (ds d. (ds @ d) T ds T)"

text The subtree in with root r
fun subtree :: "dir list set ==> dir list ==> dir list set" where 
  "subtree T r = {ds T. ds'. ds = r @ ds'}" 

text A subtree of a tree is either in the left branch, the right branch, or is the tree itself
lemma subtree_pos: 
  "subtree T ds subtree T (ds @ [Left]) subtree T (ds @ [Right]) {ds}"
proof (rule subsetI; rule Set.UnCI)
  let ?subtree = "subtree T"
  fix x
  assume asm: "x ?subtree ds"
  assume "x {ds}"
  then have "x ds" by simp
  then have "e d. x = ds @ [d] @ e" using asm list.exhaust by auto
  then have "(e. x = ds @ [Left] @ e) (e. x = ds @ [Right] @ e)" using bool.exhausby auto
  then show "x ?subtree (ds @ [Left]) ?subtree (ds @ [Right])" using asm by auto
qed


subsection Infinite Paths

abbreviation wf_infpath :: "(nat ==> 'a list) ==> bool" where
  "wf_infpath f (f 0 = []) (n. a. f (Suc n) = (f n) @ [a])"

lemma infpath_length:
  assumes "wf_infpath f"
  shows "length (f n) = n"
using assms proof (induction n)
  case 0 then show ?case by auto
next
  case (Suc n) then show ?case by (metis length_append_singleton)
qed

lemma chain_prefix: 
  assumes "wf_infpath f"
  assumes "n1 n2"
  shows "a. (f n1) @ a = (f n2)"
using assms proof (induction n2)
  case (Suc n2)
  then have "n1 n2 n1 = Suc n2" by auto
  then show ?case
    proof
      assume "n1 n2"
      then obtain a where a: "f n1 @ a = f n2" using Suc by auto
      have b: "b. f (Suc n2) = f n2 @ [b]" using Suc by auto 
      from a b have "b. f n1 @ (a @ [b]) = f (Suc n2)" by auto
      then show "c. f n1 @ c = f (Suc n2)" by blast
    next
      assume "n1 = Suc n2"
      then have "f n1 @ [] = f (Suc n2)" by auto
      then show "a. f n1 @ a = f (Suc n2)" by auto
    qed
qed auto

text If we make a lookup in a list, then looking up in an extension gives us the same value.
lemma ith_in_extension:
  assumes chain: "wf_infpath f"
  assumes smalli: "i < length (f n1)"
  assumes n1n2"n1 n2"
  shows "f n1 ! i = f n2 ! i"
proof -
  from chain n1n2 have "a. f n1 @ a = f n2" using chain_prefix by blast
  then obtain a where a_p: "f n1 @ a = f n2" by auto
  have "(f n1 @ a) ! i = f n1 ! i" using smalli by (simp add: nth_append) 
  then show ?thesis using a_p by auto
qed


section König's Lemma

lemma inf_subs: 
  assumes inf: "¬finite(subtree T ds)"
  shows "¬finite(subtree T (ds @ [Left])) ¬finite(subtree T (ds @ [Right]))"
proof -
  let ?subtree = "subtree T"
  {
    assume asms: "finite(?subtree(ds @ [Left]))"
                 "finite(?subtree(ds @ [Right]))"
    have "?subtree ds ?subtree (ds @ [Left] ) ?subtree (ds @ [Right]) {ds} " 
      using subtree_pos by auto
    then have "finite(?subtree (ds))" using asms by (simp add: finite_subset)
  } 
  then show "¬finite(?subtree (ds @ [Left])) ¬finite(?subtree (ds @ [Right]))" using inf by auto
qed

fun buildchain :: "(dir list ==> dir list) ==> nat ==> dir list" where
  "buildchain next 0 = []"
"buildchain next (Suc n) = next (buildchain next n)"

lemma konig:
  assumes inf: "¬finite T"
  assumes wellformed: "wf_tree T"
  shows "c. wf_infpath c (n. (c n) T)"
proof
  let ?subtree = "subtree T"
  let ?nextnode = "λds. (if ¬finite (?subtree (ds @ [Left])) then ds @ [Left] else ds @ [Right])" 

  let ?c = "buildchain ?nextnode"

  have is_chain: "wf_infpath ?c" by auto

  from wellformed have prefix: "ds d. (ds @ d) T ds T" by blast

  { 
    fix n
    have "(?c n) T ¬finite (?subtree (?c n))"
      proof (induction n)
        case 0
        have "ds. ds T" using inf by (simp add: not_finite_existsD)
        then obtain ds where "ds T" by auto
        then have "([]@ds) T" by auto
        then have "[] T" using prefix by blast 
        then show ?case using inf by auto
      next
        case (Suc n)
        from Suc have next_in:  "(?c n) T" by auto
        from Suc have next_inf: "¬finite (?subtree (?c n))" by auto

        from next_inf have next_next_inf:
           "¬finite (?subtree (?nextnode (?c n)))" 
              using inf_subs by auto
        then have "ds. ds ?subtree (?nextnode (?c n))"
          by (simp add: not_finite_existsD)
        then obtain ds where dss: "ds ?subtree (?nextnode (?c n))" by auto
        then have "ds T" "suf. ds = (?nextnode (?c n)) @ suf" by auto
        then obtain suf where "ds T ds = (?nextnode (?c n)) @ suf" by auto
        then have "(?nextnode (?c n)) T"
          using prefix by blast
              
        then have "(?c (Suc n)) T" by auto
        then show ?case using next_next_inf by auto
      qed
  }
  then show "wf_infpath ?c (n. (?c n) T) " using is_chain by auto
qed

end

Messung V0.5 in Prozent
C=78 H=96 G=87

¤ Dauer der Verarbeitung: 0.16 Sekunden  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.