# HG changeset patch # User krauss # Date 1182268849 -7200 # Node ID b73a6b72f706613ad0655df357311e6c4ae34d67 # Parent 9dad8095bd430b510a469a0acd7ed42e69056c40 generalized proofs so that call graphs can have any node type. diff -r 9dad8095bd43 -r b73a6b72f706 src/HOL/Library/Graphs.thy --- a/src/HOL/Library/Graphs.thy Tue Jun 19 00:02:16 2007 +0200 +++ b/src/HOL/Library/Graphs.thy Tue Jun 19 18:00:49 2007 +0200 @@ -3,7 +3,7 @@ Author: Alexander Krauss, TU Muenchen *) -header "" (* FIXME proper header *) +header {* General Graphs as Sets *} theory Graphs imports Main SCT_Misc Kleene_Algebras ExecutableSet @@ -215,7 +215,6 @@ unfolding graph_pow_def by simp_all qed - lemma graph_leqI: assumes "\n e n'. has_edge G n e n' \ has_edge H n e n'" shows "G \ H" @@ -223,7 +222,6 @@ unfolding graph_leq_def has_edge_def by auto - lemma in_graph_plusE: assumes "has_edge (G + H) n e n'" assumes "has_edge G n e n' \ P" @@ -232,6 +230,13 @@ using assms by (auto simp: in_grplus) +lemma in_graph_compE: + assumes GH: "has_edge (G * H) n e n'" + obtains e1 k e2 + where "has_edge G n e1 k" "has_edge H k e2 n'" "e = e1 * e2" + using GH + by (auto simp: in_grcomp) + lemma assumes "x \ S k" shows "x \ (\k. S k)" diff -r 9dad8095bd43 -r b73a6b72f706 src/HOL/Library/Kleene_Algebras.thy --- a/src/HOL/Library/Kleene_Algebras.thy Tue Jun 19 00:02:16 2007 +0200 +++ b/src/HOL/Library/Kleene_Algebras.thy Tue Jun 19 18:00:49 2007 +0200 @@ -382,15 +382,29 @@ definition "tcl (x::'a::kleene) = star x * x" - lemma tcl_zero: "tcl (0::'a::kleene) = 0" unfolding tcl_def by simp +lemma tcl_unfold_right: "tcl a = a + tcl a * a" +proof - + from star_unfold_right[of a] + have "a * (1 + star a * a) = a * star a" by simp + from this[simplified right_distrib, simplified] + show ?thesis + by (simp add:tcl_def star_commute mult_ac) +qed + +lemma less_tcl: "a \ tcl a" +proof - + have "a \ a + tcl a * a" by simp + also have "\ = tcl a" by (rule tcl_unfold_right[symmetric]) + finally show ?thesis . +qed subsection {* Naive Algorithm to generate the transitive closure *} -function (default "\x. 0", tailrec) +function (default "\x. 0", tailrec, domintros) mk_tcl :: "('a::{plus,times,ord,zero}) \ 'a \ 'a" where "mk_tcl A X = (if X * A \ X then X else mk_tcl A (X + X * A))" diff -r 9dad8095bd43 -r b73a6b72f706 src/HOL/Library/SCT_Definition.thy --- a/src/HOL/Library/SCT_Definition.thy Tue Jun 19 00:02:16 2007 +0200 +++ b/src/HOL/Library/SCT_Definition.thy Tue Jun 19 18:00:49 2007 +0200 @@ -3,7 +3,7 @@ Author: Alexander Krauss, TU Muenchen *) -header "" (* FIXME proper header *) +header {* The Size-Change Principle (Definition) *} theory SCT_Definition imports Graphs Infinite_Set @@ -32,7 +32,10 @@ lemma sedge_UNIV: "UNIV = { LESS, LEQ }" - by auto (case_tac x, auto) (*FIXME*) +proof (intro equalityI subsetI) + fix x show "x \ { LESS, LEQ }" + by (cases x) auto +qed auto instance sedge :: finite proof @@ -43,8 +46,8 @@ lemmas [code func] = sedge_UNIV -types scg = "(nat, sedge) graph" -types acg = "(nat, scg) graph" +types 'a scg = "('a, sedge) graph" +types 'a acg = "('a, 'a scg) graph" subsection {* Size-Change Termination *} @@ -59,46 +62,46 @@ "eq G i j \ has_edge G i LEQ j" abbreviation - eql :: "scg \ nat \ nat \ bool" + eql :: "'a scg \ 'a \ 'a \ bool" ("_ \ _ \ _") where "eql G i j \ has_edge G i LESS j \ has_edge G i LEQ j" -abbreviation (input) descat :: "(nat, scg) ipath \ nat sequence \ nat \ bool" +abbreviation (input) descat :: "('a, 'a scg) ipath \ 'a sequence \ nat \ bool" where "descat p \ i \ has_edge (snd (p i)) (\ i) LESS (\ (Suc i))" -abbreviation (input) eqat :: "(nat, scg) ipath \ nat sequence \ nat \ bool" +abbreviation (input) eqat :: "('a, 'a scg) ipath \ 'a sequence \ nat \ bool" where "eqat p \ i \ has_edge (snd (p i)) (\ i) LEQ (\ (Suc i))" -abbreviation eqlat :: "(nat, scg) ipath \ nat sequence \ nat \ bool" +abbreviation (input) eqlat :: "('a, 'a scg) ipath \ 'a sequence \ nat \ bool" where "eqlat p \ i \ (has_edge (snd (p i)) (\ i) LESS (\ (Suc i)) \ has_edge (snd (p i)) (\ i) LEQ (\ (Suc i)))" -definition is_desc_thread :: "nat sequence \ (nat, scg) ipath \ bool" +definition is_desc_thread :: "'a sequence \ ('a, 'a scg) ipath \ bool" where "is_desc_thread \ p = ((\n.\i\n. eqlat p \ i) \ (\\<^sub>\i. descat p \ i))" -definition SCT :: "acg \ bool" +definition SCT :: "'a acg \ bool" where "SCT \ = (\p. has_ipath \ p \ (\\. is_desc_thread \ p))" -definition no_bad_graphs :: "acg \ bool" +definition no_bad_graphs :: "'a acg \ bool" where "no_bad_graphs A = (\n G. has_edge A n G n \ G * G = G \ (\p. has_edge G p LESS p))" -definition SCT' :: "acg \ bool" +definition SCT' :: "'a acg \ bool" where "SCT' A = no_bad_graphs (tcl A)" diff -r 9dad8095bd43 -r b73a6b72f706 src/HOL/Library/SCT_Examples.thy --- a/src/HOL/Library/SCT_Examples.thy Tue Jun 19 00:02:16 2007 +0200 +++ b/src/HOL/Library/SCT_Examples.thy Tue Jun 19 18:00:49 2007 +0200 @@ -3,7 +3,7 @@ Author: Alexander Krauss, TU Muenchen *) -header "" (* FIXME proper header *) +header {* Examples for Size-Change Termination *} theory SCT_Examples imports Size_Change_Termination @@ -23,9 +23,8 @@ apply (tactic "Sct.abs_rel_tac") (* Build call descriptors *) apply (rule ext, rule ext, simp) (* Show that they are correct *) apply (tactic "Sct.mk_call_graph") (* Build control graph *) - apply (rule LJA_apply) (* Apply main theorem *) - apply (simp add:finite_acg_ins finite_acg_empty) (* show finiteness *) - apply (rule SCT'_exec) + apply (rule SCT_Main) (* Apply main theorem *) + apply (simp add:finite_acg_simps) (* show finiteness *) by eval (* Evaluate to true *) function p :: "nat \ nat \ nat \ nat" @@ -41,10 +40,9 @@ apply (tactic "Sct.abs_rel_tac") apply (rule ext, rule ext, simp) apply (tactic "Sct.mk_call_graph") - apply (rule LJA_apply) - apply (simp add:finite_acg_ins finite_acg_empty) - apply (rule SCT'_exec) - by eval + apply (rule SCT_Main) + apply (simp add:finite_acg_ins finite_acg_empty finite_graph_def) (* show finiteness *) + by eval function foo :: "bool \ nat \ nat \ nat" where @@ -60,10 +58,10 @@ apply (tactic "Sct.abs_rel_tac") apply (rule ext, rule ext, simp) apply (tactic "Sct.mk_call_graph") - apply (rule LJA_apply) - apply (simp add:finite_acg_ins finite_acg_empty) - apply (rule SCT'_exec) - by eval + apply (rule SCT_Main) + apply (simp add:finite_acg_ins finite_acg_empty finite_graph_def) (* show finiteness *) + by eval + function (sequential) bar :: "nat \ nat \ nat \ nat" @@ -78,8 +76,8 @@ apply (tactic "Sct.abs_rel_tac") apply (rule ext, rule ext, simp) apply (tactic "Sct.mk_call_graph") - apply (rule LJA_apply) - apply (simp add:finite_acg_ins finite_acg_empty) - by (rule SCT'_empty) + apply (rule SCT_Main) + apply (simp add:finite_acg_ins finite_acg_empty finite_graph_def) (* show finiteness *) + by (simp only:sctTest_simps cong: sctTest_congs) end diff -r 9dad8095bd43 -r b73a6b72f706 src/HOL/Library/SCT_Implementation.thy --- a/src/HOL/Library/SCT_Implementation.thy Tue Jun 19 00:02:16 2007 +0200 +++ b/src/HOL/Library/SCT_Implementation.thy Tue Jun 19 18:00:49 2007 +0200 @@ -3,10 +3,10 @@ Author: Alexander Krauss, TU Muenchen *) -header "" (* FIXME proper header *) +header {* Implemtation of the SCT criterion *} theory SCT_Implementation -imports ExecutableSet SCT_Definition +imports ExecutableSet SCT_Definition SCT_Theorem begin fun edges_match :: "('n \ 'e \ 'n) \ ('n \ 'e \ 'n) \ bool" @@ -23,29 +23,101 @@ "grcomp (Graph G) (Graph H) = Graph (connect_edges ` { x \ G\H. edges_match x })" by (rule graph_ext) (auto simp:graph_mult_def has_edge_def image_def) -definition test_SCT :: "acg \ bool" + +lemma mk_tcl_finite_terminates: + fixes A :: "'a acg" + assumes fA: "finite_acg A" + shows "mk_tcl_dom (A, A)" +proof - + from fA have fin_tcl: "finite_acg (tcl A)" + by (simp add:finite_tcl) + + hence "finite (dest_graph (tcl A))" + unfolding finite_acg_def finite_graph_def .. + + let ?count = "\G. card (dest_graph G)" + let ?N = "?count (tcl A)" + let ?m = "\X. ?N - (?count X)" + + let ?P = "\X. mk_tcl_dom (A, X)" + + { + fix X + assume "X \ tcl A" + then + have "mk_tcl_dom (A, X)" + proof (induct X rule:measure_induct_rule[of ?m]) + case (less X) + show ?case + proof (cases "X * A \ X") + case True + with mk_tcl.domintros show ?thesis by auto + next + case False + then have l: "X < X + X * A" + unfolding graph_less_def graph_leq_def graph_plus_def + by auto + + from `X \ tcl A` + have "X * A \ tcl A * A" by (simp add:mult_mono) + also have "\ \ A + tcl A * A" by simp + also have "\ = tcl A" by (simp add:tcl_unfold_right[symmetric]) + finally have "X * A \ tcl A" . + with `X \ tcl A` + have "X + X * A \ tcl A + tcl A" + by (rule add_mono) + hence less_tcl: "X + X * A \ tcl A" by simp + hence "X < tcl A" + using l `X \ tcl A` by auto + + from less_tcl fin_tcl + have "finite_acg (X + X * A)" by (rule finite_acg_subset) + hence "finite (dest_graph (X + X * A))" + unfolding finite_acg_def finite_graph_def .. + + hence X: "?count X < ?count (X + X * A)" + using l[simplified graph_less_def graph_leq_def] + by (rule psubset_card_mono) + + have "?count X < ?N" + apply (rule psubset_card_mono) + by fact (rule `X < tcl A`[simplified graph_less_def]) + + with X have "?m (X + X * A) < ?m X" by arith + + from less.hyps this less_tcl + have "mk_tcl_dom (A, X + X * A)" . + with mk_tcl.domintros show ?thesis . + qed + qed + } + from this less_tcl show ?thesis . +qed + + +lemma mk_tcl_finite_tcl: + fixes A :: "'a acg" + assumes fA: "finite_acg A" + shows "mk_tcl A A = tcl A" + using mk_tcl_finite_terminates[OF fA] + by (simp only: tcl_def mk_tcl_correctness star_commute) + +definition test_SCT :: "nat acg \ bool" where "test_SCT \ = (let \ = mk_tcl \ \ - in (\ \ 0 \ - (\(n,G,m)\dest_graph \. + in (\(n,G,m)\dest_graph \. n \ m \ G * G \ G \ - (\(p::nat,e,q)\dest_graph G. p = q \ e = LESS))))" + (\(p::nat,e,q)\dest_graph G. p = q \ e = LESS)))" lemma SCT'_exec: - assumes a: "test_SCT \" - shows "SCT' \" -proof - - from mk_tcl_correctness2 a - have "mk_tcl \ \ = tcl \" - unfolding test_SCT_def Let_def by auto - - with a - show ?thesis - unfolding SCT'_def no_bad_graphs_def test_SCT_def Let_def has_edge_def - by auto -qed + assumes fin: "finite_acg A" + shows "SCT' A = test_SCT A" + using mk_tcl_finite_tcl[OF fin] + unfolding test_SCT_def Let_def + unfolding SCT'_def no_bad_graphs_def has_edge_def + by force code_modulename SML Implementation Graphs @@ -75,7 +147,7 @@ subsection {* Witness checking *} -definition test_SCT_witness :: "acg \ acg \ bool" +definition test_SCT_witness :: "nat acg \ nat acg \ bool" where "test_SCT_witness A T = (A \ T \ A * T \ T \ diff -r 9dad8095bd43 -r b73a6b72f706 src/HOL/Library/SCT_Interpretation.thy --- a/src/HOL/Library/SCT_Interpretation.thy Tue Jun 19 00:02:16 2007 +0200 +++ b/src/HOL/Library/SCT_Interpretation.thy Tue Jun 19 18:00:49 2007 +0200 @@ -3,7 +3,7 @@ Author: Alexander Krauss, TU Muenchen *) -header "" (* FIXME proper header *) +header {* Applying SCT to function definitions *} theory SCT_Interpretation imports Main SCT_Misc SCT_Definition @@ -92,11 +92,8 @@ qed - -types ('q, 'a) interpr = "('a, 'q) cdesc \ (nat \ 'a \ nat)" types 'a measures = "nat \ 'a \ nat" - fun stepP :: "('a, 'q) cdesc \ ('a, 'q) cdesc \ ('a \ nat) \ ('a \ nat) \ (nat \ nat \ bool) \ bool" where @@ -188,7 +185,7 @@ definition - approx :: "scg \ ('a, 'q) cdesc \ ('a, 'q) cdesc + approx :: "nat scg \ ('a, 'q) cdesc \ ('a, 'q) cdesc \ 'a measures \ 'a measures \ bool" where "approx G C C' M M' @@ -240,7 +237,7 @@ by (cases c1, cases c2) (auto simp: no_step_def) definition - sound_int :: "acg \ ('a, 'q) cdesc list + sound_int :: "nat acg \ ('a, 'q) cdesc list \ 'a measures list \ bool" where "sound_int \ RDs M = diff -r 9dad8095bd43 -r b73a6b72f706 src/HOL/Library/SCT_Misc.thy --- a/src/HOL/Library/SCT_Misc.thy Tue Jun 19 00:02:16 2007 +0200 +++ b/src/HOL/Library/SCT_Misc.thy Tue Jun 19 18:00:49 2007 +0200 @@ -3,7 +3,7 @@ Author: Alexander Krauss, TU Muenchen *) -header "" (* FIXME proper header *) +header {* Miscellaneous Tools for Size-Change Termination *} theory SCT_Misc (* FIXME proper name *) imports Main diff -r 9dad8095bd43 -r b73a6b72f706 src/HOL/Library/SCT_Theorem.thy --- a/src/HOL/Library/SCT_Theorem.thy Tue Jun 19 00:02:16 2007 +0200 +++ b/src/HOL/Library/SCT_Theorem.thy Tue Jun 19 18:00:49 2007 +0200 @@ -3,7 +3,7 @@ Author: Alexander Krauss, TU Muenchen *) -header "" (* FIXME proper header *) +header "Proof of the Size-Change Principle" theory SCT_Theorem imports Main Ramsey SCT_Misc SCT_Definition @@ -11,17 +11,17 @@ subsection {* The size change criterion SCT *} -definition is_thread :: "nat \ nat sequence \ (nat, scg) ipath \ bool" +definition is_thread :: "nat \ 'a sequence \ ('a, 'a scg) ipath \ bool" where "is_thread n \ p = (\i\n. eqlat p \ i)" definition is_fthread :: - "nat sequence \ (nat, scg) ipath \ nat \ nat \ bool" + "'a sequence \ ('a, 'a scg) ipath \ nat \ nat \ bool" where "is_fthread \ mp i j = (\k\{i.. k)" definition is_desc_fthread :: - "nat sequence \ (nat, scg) ipath \ nat \ nat \ bool" + "'a sequence \ ('a, 'a scg) ipath \ nat \ nat \ bool" where "is_desc_fthread \ mp i j = (is_fthread \ mp i j \ @@ -36,163 +36,7 @@ (\\. is_desc_fthread \ p i j \ \ i = n \ \ j = m)" -subsection {* Bounded graphs and threads *} - -definition - "bounded_scg (P::nat) (G::scg) = - (\p e p'. has_edge G p e p' \ p < P \ p' < P)" - -definition - "bounded_acg P ACG = - (\n G n'. has_edge ACG n G n' \ n < P \ n' < P \ bounded_scg P G)" - -definition - "bounded_mp P mp = (\i. bounded_scg P (snd (mp i)))" - -definition (* = finite (range \) *) - "bounded_th (P::nat) n \ = (\i>n. \ i < P)" - -definition - "finite_scg (G::scg) = (\P. bounded_scg P G)" - -definition - "finite_acg (A::acg) = (\P. bounded_acg P A)" - -lemma "finite (insert x A) = finite A" -by simp - - -lemma finite_scg_finite[simp]: "finite_scg (Graph G) = finite G" -proof - assume "finite_scg (Graph G)" - thm bounded_scg_def - - then obtain P where bounded: "bounded_scg P (Graph G)" - by (auto simp:finite_scg_def) - - show "finite G" - proof (rule finite_subset) - from bounded - show "G \ {0 .. P - 1} \ { LESS, LEQ } \ { 0 .. P - 1}" - apply (auto simp:bounded_scg_def has_edge_def) - apply force - apply (case_tac "aa", auto) - apply force - done - - show "finite \" - by (auto intro: finite_cartesian_product finite_atLeastAtMost) - qed -next - assume "finite G" - thus "finite_scg (Graph G)" - proof induct - show "finite_scg (Graph {})" - unfolding finite_scg_def bounded_scg_def has_edge_def by auto - next - fix x G - assume "finite G" "x \ G" "finite_scg (Graph G)" - then obtain P - where bG: "bounded_scg P (Graph G)" - by (auto simp:finite_scg_def) - - obtain p e p' where x: "x = (p, e, p')" by (cases x, auto) - - let ?Q = "max P (max (Suc p) (Suc p'))" - have "P \ ?Q" "Suc p \ ?Q" "Suc p' \ ?Q" by auto - with bG - have "bounded_scg ?Q (Graph (insert x G))" - unfolding x bounded_scg_def has_edge_def - apply simp - apply (intro allI, elim allE) - by auto - thus "finite_scg (Graph (insert x G))" - by (auto simp:finite_scg_def) - qed -qed - -lemma finite_acg_empty: - "finite_acg (Graph {})" -unfolding finite_acg_def bounded_acg_def has_edge_def -by auto - -lemma bounded_scg_up: "bounded_scg P G \ P \ Q \ bounded_scg Q G" - unfolding bounded_scg_def - by force - -lemma bounded_up: "bounded_acg P G \ P \ Q \ bounded_acg Q G" - unfolding bounded_acg_def - apply auto - apply force+ - apply (rule bounded_scg_up) - by auto - -lemma bacg_insert: - assumes "bounded_acg P (Graph A)" - assumes "n < P" "m < P" "bounded_scg P G" - shows "bounded_acg P (Graph (insert (n, G, m) A))" - using prems - unfolding bounded_acg_def has_edge_def - by auto - -lemma finite_acg_ins: - "finite_acg (Graph (insert (n,G,m) A)) = - (finite_scg G \ finite_acg (Graph A))" (is "?A = (?B \ ?C)") -proof - assume "?A" - thus "?B \ ?C" - unfolding finite_acg_def bounded_acg_def finite_scg_def has_edge_def - by auto -next - assume "?B \ ?C" - thus ?A - proof - assume "?B" "?C" - - from `?C` - obtain P where bA: "bounded_acg P (Graph A)" by (auto simp:finite_acg_def) - from `?B` - obtain P' where bG: "bounded_scg P' G" by (auto simp:finite_scg_def) - - let ?Q = "max (max P P') (max (Suc n) (Suc m))" - have "P \ ?Q" "n < ?Q" "m < ?Q" by auto - have "bounded_acg ?Q (Graph (insert (n, G, m) A))" - apply (rule bacg_insert) - apply (rule bounded_up) - apply (rule bA) - apply auto - apply (rule bounded_scg_up) - apply (rule bG) - by auto - thus "finite_acg (Graph (insert (n, G, m) A))" - by (auto simp:finite_acg_def) - qed -qed - - -lemma bounded_mpath: - assumes "has_ipath acg mp" - and "bounded_acg P acg" - shows "bounded_mp P mp" - using prems - unfolding bounded_acg_def bounded_mp_def has_ipath_def - by blast - -lemma bounded_th: - assumes th: "is_thread n \ mp" - and mp: "bounded_mp P mp" - shows "bounded_th P n \" - unfolding bounded_th_def -proof (intro allI impI) - fix i assume "n < i" - - from mp have "bounded_scg P (snd (mp i))" unfolding bounded_mp_def .. - moreover - from th `n < i` have "eqlat mp \ i" unfolding is_thread_def by auto - ultimately - show "\ i < P" unfolding bounded_scg_def by auto -qed - +subsection {* Everything is finite *} lemma finite_range: fixes f :: "nat \ 'a" @@ -216,117 +60,345 @@ with neq[of "f m" m] show ?thesis by blast qed - -lemma bounded_th_infinite_visit: - fixes \ :: "nat sequence" - assumes b: "bounded_th P n \" - shows "\p. \\<^sub>\i. \ i = p" +lemma finite_range_ignore_prefix: + fixes f :: "nat \ 'a" + assumes fA: "finite A" + assumes inA: "\x\n. f x \ A" + shows "finite (range f)" proof - - have split: "range \ = (\ ` {0 .. n}) \ (\ ` {i. n < i})" + have a: "UNIV = {0 ..< (n::nat)} \ { x. n \ x }" by auto + have b: "range f = f ` {0 ..< n} \ f ` { x. n \ x }" (is "\ = ?A \ ?B") - unfolding image_Un[symmetric] by auto - - have "finite ?A" by (rule finite_imageI) auto + by (unfold a) (simp add:image_Un) + + have "finite ?A" by (rule finite_imageI) simp moreover - have "finite ?B" - proof (rule finite_subset) - from b - show "?B \ { 0 ..< P }" - unfolding bounded_th_def - by auto - show "finite \" by auto - qed - - ultimately have "finite (range \)" - unfolding split by auto - - with finite_range show ?thesis . + from inA have "?B \ A" by auto + from this fA have "finite ?B" by (rule finite_subset) + ultimately show ?thesis using b by simp qed -lemma bounded_scgcomp: - "bounded_scg P A - \ bounded_scg P B - \ bounded_scg P (A * B)" - unfolding bounded_scg_def - by (auto simp:in_grcomp) + + +definition + "finite_graph G = finite (dest_graph G)" +definition + "all_finite G = (\n H m. has_edge G n H m \ finite_graph H)" +definition + "finite_acg A = (finite_graph A \ all_finite A)" +definition + "nodes G = fst ` dest_graph G \ snd ` snd ` dest_graph G" +definition + "edges G = fst ` snd ` dest_graph G" +definition + "smallnodes G = \(nodes ` edges G)" + +lemma thread_image_nodes: + assumes th: "is_thread n \ p" + shows "\i\n. \ i \ nodes (snd (p i))" +using prems +unfolding is_thread_def has_edge_def nodes_def +by force + +lemma finite_nodes: "finite_graph G \ finite (nodes G)" + unfolding finite_graph_def nodes_def + by auto + +lemma nodes_subgraph: "A \ B \ nodes A \ nodes B" + unfolding graph_leq_def nodes_def + by auto + +lemma finite_edges: "finite_graph G \ finite (edges G)" + unfolding finite_graph_def edges_def + by auto + +lemma edges_sum[simp]: "edges (A + B) = edges A \ edges B" + unfolding edges_def graph_plus_def + by auto + +lemma nodes_sum[simp]: "nodes (A + B) = nodes A \ nodes B" + unfolding nodes_def graph_plus_def + by auto + +lemma finite_acg_subset: + "A \ B \ finite_acg B \ finite_acg A" + unfolding finite_acg_def finite_graph_def all_finite_def + has_edge_def graph_leq_def + by (auto elim:finite_subset) -lemma bounded_acgcomp: - "bounded_acg P A - \ bounded_acg P B - \ bounded_acg P (A * B)" - unfolding bounded_acg_def - by (auto simp:in_grcomp intro!:bounded_scgcomp) +lemma scg_finite: + fixes G :: "'a scg" + assumes fin: "finite (nodes G)" + shows "finite_graph G" + unfolding finite_graph_def +proof (rule finite_subset) + show "dest_graph G \ nodes G \ UNIV \ nodes G" (is "_ \ ?P") + unfolding nodes_def + by force + show "finite ?P" + by (intro finite_cartesian_product fin finite) +qed + +lemma smallnodes_sum[simp]: + "smallnodes (A + B) = smallnodes A \ smallnodes B" + unfolding smallnodes_def + by auto + +lemma in_smallnodes: + fixes A :: "'a acg" + assumes e: "has_edge A x G y" + shows "nodes G \ smallnodes A" +proof - + have "fst (snd (x, G, y)) \ fst ` snd ` dest_graph A" + unfolding has_edge_def + by (rule imageI)+ (rule e[unfolded has_edge_def]) + then have "G \ edges A" + unfolding edges_def by simp + thus ?thesis + unfolding smallnodes_def + by blast +qed + +lemma finite_smallnodes: + assumes fA: "finite_acg A" + shows "finite (smallnodes A)" + unfolding smallnodes_def edges_def +proof + from fA + show "finite (nodes ` fst ` snd ` dest_graph A)" + unfolding finite_acg_def finite_graph_def + by simp + + fix M assume "M \ nodes ` fst ` snd ` dest_graph A" + then obtain n G m + where M: "M = nodes G" and nGm: "(n,G,m) \ dest_graph A" + by auto + + from fA + have "all_finite A" unfolding finite_acg_def by simp + with nGm have "finite_graph G" + unfolding all_finite_def has_edge_def by auto + with finite_nodes + show "finite M" + unfolding finite_graph_def M . +qed + +lemma nodes_tcl: + "nodes (tcl A) = nodes A" +proof + show "nodes A \ nodes (tcl A)" + apply (rule nodes_subgraph) + by (subst tcl_unfold_right) simp + + show "nodes (tcl A) \ nodes A" + proof + fix x assume "x \ nodes (tcl A)" + then obtain z G y + where z: "z \ dest_graph (tcl A)" + and dis: "z = (x, G, y) \ z = (y, G, x)" + unfolding nodes_def + by auto force+ -lemma bounded_acgpow: - "bounded_acg P A - \ bounded_acg P (A ^ (Suc n))" - by (induct n, simp add:power_Suc) - (subst power_Suc, blast intro:bounded_acgcomp) + from dis + show "x \ nodes A" + proof + assume "z = (x, G, y)" + with z have "has_edge (tcl A) x G y" unfolding has_edge_def by simp + then obtain n where "n > 0 " and An: "has_edge (A ^ n) x G y" + unfolding in_tcl by auto + then obtain n' where "n = Suc n'" by (cases n, auto) + hence "A ^ n = A * A ^ n'" by (simp add:power_Suc) + with An obtain e k + where "has_edge A x e k" by (auto simp:in_grcomp) + thus "x \ nodes A" unfolding has_edge_def nodes_def + by force + next + assume "z = (y, G, x)" + with z have "has_edge (tcl A) y G x" unfolding has_edge_def by simp + then obtain n where "n > 0 " and An: "has_edge (A ^ n) y G x" + unfolding in_tcl by auto + then obtain n' where "n = Suc n'" by (cases n, auto) + hence "A ^ n = A ^ n' * A" by (simp add:power_Suc power_commutes) + with An obtain e k + where "has_edge A k e x" by (auto simp:in_grcomp) + thus "x \ nodes A" unfolding has_edge_def nodes_def + by force + qed + qed +qed + +lemma smallnodes_tcl: + fixes A :: "'a acg" + shows "smallnodes (tcl A) = smallnodes A" +proof (intro equalityI subsetI) + fix n assume "n \ smallnodes (tcl A)" + then obtain x G y where edge: "has_edge (tcl A) x G y" + and "n \ nodes G" + unfolding smallnodes_def edges_def has_edge_def + by auto + + from `n \ nodes G` + have "n \ fst ` dest_graph G \ n \ snd ` snd ` dest_graph G" + (is "?A \ ?B") + unfolding nodes_def by blast + thus "n \ smallnodes A" + proof + assume ?A + then obtain m e where A: "has_edge G n e m" + unfolding has_edge_def by auto + + have "tcl A = A * star A" + unfolding tcl_def + by (simp add: star_commute[of A A A, simplified]) + + with edge + have "has_edge (A * star A) x G y" by simp + then obtain H H' z + where AH: "has_edge A x H z" and G: "G = H * H'" + by (auto simp:in_grcomp) + from A + obtain m' e' where "has_edge H n e' m'" + by (auto simp:G in_grcomp) + hence "n \ nodes H" unfolding nodes_def has_edge_def + by force + with in_smallnodes[OF AH] show "n \ smallnodes A" .. + next + assume ?B + then obtain m e where B: "has_edge G m e n" + unfolding has_edge_def by auto -lemma bounded_plus: - assumes b: "bounded_acg P acg" - shows "bounded_acg P (tcl acg)" - unfolding bounded_acg_def -proof (intro allI impI conjI) - fix n G m - assume "tcl acg \ n \\<^bsup>G\<^esup> m" - then obtain i where "0 < i" and i: "acg ^ i \ n \\<^bsup>G\<^esup> m" - unfolding in_tcl by auto (* FIXME: Disambiguate \ Grammar *) - from b have "bounded_acg P (acg ^ (Suc (i - 1)))" - by (rule bounded_acgpow) - with `0 < i` have "bounded_acg P (acg ^ i)" by simp - with i - show "n < P" "m < P" "bounded_scg P G" - unfolding bounded_acg_def - by auto + with edge + have "has_edge (star A * A) x G y" by (simp add:tcl_def) + then obtain H H' z + where AH': "has_edge A z H' y" and G: "G = H * H'" + by (auto simp:in_grcomp) + from B + obtain m' e' where "has_edge H' m' e' n" + by (auto simp:G in_grcomp) + hence "n \ nodes H'" unfolding nodes_def has_edge_def + by force + with in_smallnodes[OF AH'] show "n \ smallnodes A" .. + qed +next + fix x assume "x \ smallnodes A" + then show "x \ smallnodes (tcl A)" + by (subst tcl_unfold_right) simp +qed + +lemma finite_nodegraphs: + assumes F: "finite F" + shows "finite { G::'a scg. nodes G \ F }" (is "finite ?P") +proof (rule finite_subset) + show "?P \ Graph ` (Pow (F \ UNIV \ F))" (is "?P \ ?Q") + proof + fix x assume xP: "x \ ?P" + obtain S where x[simp]: "x = Graph S" + by (cases x) auto + from xP + show "x \ ?Q" + apply (simp add:nodes_def) + apply (rule imageI) + apply (rule PowI) + apply force + done + qed + show "finite ?Q" + by (auto intro:finite_imageI finite_cartesian_product F finite) +qed + +lemma finite_graphI: + fixes A :: "'a acg" + assumes fin: "finite (nodes A)" "finite (smallnodes A)" + shows "finite_graph A" +proof - + obtain S where A[simp]: "A = Graph S" + by (cases A) auto + + have "finite S" + proof (rule finite_subset) + show "S \ nodes A \ { G::'a scg. nodes G \ smallnodes A } \ nodes A" + (is "S \ ?T") + proof + fix x assume xS: "x \ S" + obtain a b c where x[simp]: "x = (a, b, c)" + by (cases x) auto + + then have edg: "has_edge A a b c" + unfolding has_edge_def using xS + by simp + + hence "a \ nodes A" "c \ nodes A" + unfolding nodes_def has_edge_def by force+ + moreover + from edg have "nodes b \ smallnodes A" by (rule in_smallnodes) + hence "b \ { G :: 'a scg. nodes G \ smallnodes A }" by simp + ultimately show "x \ ?T" by simp + qed + + show "finite ?T" + by (intro finite_cartesian_product fin finite_nodegraphs) + qed + thus ?thesis + unfolding finite_graph_def by simp qed -lemma bounded_scg_def': - "bounded_scg P G = (\(p,e,p')\dest_graph G. p < P \ p' < P)" - unfolding bounded_scg_def has_edge_def +lemma smallnodes_allfinite: + fixes A :: "'a acg" + assumes fin: "finite (smallnodes A)" + shows "all_finite A" + unfolding all_finite_def +proof (intro allI impI) + fix n H m assume "has_edge A n H m" + then have "nodes H \ smallnodes A" + by (rule in_smallnodes) + then have "finite (nodes H)" + by (rule finite_subset) (rule fin) + thus "finite_graph H" by (rule scg_finite) +qed + +lemma finite_tcl: + fixes A :: "'a acg" + shows "finite_acg (tcl A) \ finite_acg A" +proof + assume f: "finite_acg A" + from f have g: "finite_graph A" and "all_finite A" + unfolding finite_acg_def by auto + + from g have "finite (nodes A)" by (rule finite_nodes) + then have "finite (nodes (tcl A))" unfolding nodes_tcl . + moreover + from f have "finite (smallnodes A)" by (rule finite_smallnodes) + then have fs: "finite (smallnodes (tcl A))" unfolding smallnodes_tcl . + ultimately + have "finite_graph (tcl A)" by (rule finite_graphI) + + moreover from fs have "all_finite (tcl A)" + by (rule smallnodes_allfinite) + ultimately show "finite_acg (tcl A)" unfolding finite_acg_def .. +next + assume a: "finite_acg (tcl A)" + have "A \ tcl A" by (rule less_tcl) + thus "finite_acg A" using a + by (rule finite_acg_subset) +qed + +lemma finite_acg_empty: "finite_acg (Graph {})" + unfolding finite_acg_def finite_graph_def all_finite_def + has_edge_def + by simp + +lemma finite_acg_ins: + assumes fA: "finite_acg (Graph A)" + assumes fG: "finite G" + shows "finite_acg (Graph (insert (a, Graph G, b) A))" + using fA fG + unfolding finite_acg_def finite_graph_def all_finite_def + has_edge_def by auto - -lemma finite_bounded_scg: "finite { G. bounded_scg P G }" -proof (rule finite_subset) - show "{G. bounded_scg P G} \ - Graph ` (Pow ({0 .. P - 1} \ UNIV \ {0 .. P - 1}))" - proof (rule, simp) - fix G - - assume b: "bounded_scg P G" - - show "G \ Graph ` Pow ({0..P - Suc 0} \ UNIV \ {0..P - Suc 0})" - proof (cases G) - fix G' assume [simp]: "G = Graph G'" - - from b show ?thesis - by (auto simp:bounded_scg_def' image_def) - qed - qed - - show "finite \" - apply (rule finite_imageI) - apply (unfold finite_Pow_iff) - by (intro finite_cartesian_product finite_atLeastAtMost - finite_class.finite) -qed - -lemma bounded_finite: - assumes bounded: "bounded_acg P A" - shows "finite (dest_graph A)" -proof (rule finite_subset) - - from bounded - show "dest_graph A \ {0 .. P - 1} \ { G. bounded_scg P G } \ { 0 .. P - 1}" - by (auto simp:bounded_acg_def has_edge_def) force+ - - show "finite \" - by (intro finite_cartesian_product finite_atLeastAtMost finite_bounded_scg) -qed - +lemmas finite_acg_simps = finite_acg_empty finite_acg_ins finite_graph_def subsection {* Contraction and more *} @@ -750,8 +822,6 @@ with krng show "\k\section s i. descat p (connect s \s) k" .. qed - - lemma mk_inf_thread: assumes [simp]: "increasing s" assumes fths: "\i. i > n \ is_fthread \ p (s i) (s (Suc i))" @@ -779,8 +849,9 @@ unfolding is_desc_thread_def proof (intro exI conjI) - from mk_inf_thread[of s n] is_thread_def fths - show "\i\s (Suc n). eqlat p \ i" by simp + from mk_inf_thread[of s n \ p] fths + show "\i\s (Suc n). eqlat p \ i" + by (fold is_thread_def) simp show "\\<^sub>\l. descat p \ l" unfolding INF_nat @@ -1169,40 +1240,41 @@ subsection {* Main Result *} + theorem LJA_Theorem4: - assumes "bounded_acg P \" - shows "SCT \ \ SCT' \" + assumes "finite_acg A" + shows "SCT A \ SCT' A" proof - assume "SCT \" + assume "SCT A" - show "SCT' \" + show "SCT' A" proof (rule classical) - assume "\ SCT' \" + assume "\ SCT' A" then obtain n G - where in_closure: "(tcl \) \ n \\<^bsup>G\<^esup> n" + where in_closure: "(tcl A) \ n \\<^bsup>G\<^esup> n" and idemp: "G * G = G" and no_strict_arc: "\p. \(G \ p \\<^bsup>\\<^esup> p)" unfolding SCT'_def no_bad_graphs_def by auto from in_closure obtain k - where k_pow: "\ ^ k \ n \\<^bsup>G\<^esup> n" + where k_pow: "A ^ k \ n \\<^bsup>G\<^esup> n" and "0 < k" unfolding in_tcl by auto from power_induces_path k_pow obtain loop where loop_props: - "has_fpath \ loop" + "has_fpath A loop" "n = fst loop" "n = end_node loop" "G = prod loop" "k = length (snd loop)" . with `0 < k` and path_loop_graph - have "has_ipath \ (omega loop)" by blast - with `SCT \` + have "has_ipath A (omega loop)" by blast + with `SCT A` have thread: "\\. is_desc_thread \ (omega loop)" by (auto simp:SCT_def) let ?s = "\i. k * i" - let ?cp = "\i. (n, G)" + let ?cp = "\i::nat. (n, G)" from loop_props have "fst loop = end_node loop" by auto with `0 < k` `k = length (snd loop)` @@ -1226,19 +1298,20 @@ unfolding is_desc_thread_def is_thread_def by auto - have "bounded_th P n \" - proof - - from `bounded_acg P \` - have "bounded_acg P (tcl \)" by (rule bounded_plus) - with in_closure have "bounded_scg P G" - unfolding bounded_acg_def by simp - hence "bounded_mp P ?cp" - unfolding bounded_mp_def by simp - with thr bounded_th - show ?thesis by auto + have "finite (range \)" + proof (rule finite_range_ignore_prefix) + + from `finite_acg A` + have "finite_acg (tcl A)" by (simp add:finite_tcl) + with in_closure have "finite_graph G" + unfolding finite_acg_def all_finite_def by blast + thus "finite (nodes G)" by (rule finite_nodes) + + from thread_image_nodes[OF thr] + show "\i\n. \ i \ nodes G" by simp qed - with bounded_th_infinite_visit - obtain p where inf_visit: "\\<^sub>\i. \ i = p" by blast + with finite_range + obtain p where inf_visit: "\\<^sub>\i. \ i = p" by auto then obtain i where "n < i" "\ i = p" by (auto simp:INF_nat) @@ -1252,7 +1325,9 @@ from inf_visit obtain k where "j < k" "\ k = p" by (auto simp:INF_nat) - from `i < j` `j < k` `n < i` thr fin_from_inf `descat ?cp \ j` + from `i < j` `j < k` `n < i` thr + fin_from_inf[of n \ ?cp] + `descat ?cp \ j` have "is_desc_fthread \ ?cp i k" unfolding is_desc_fthread_def by auto @@ -1271,38 +1346,39 @@ by (simp add:sub_path_def upt_rec[of i k] idemp) qed - with `i < j` `j < k` dfth Lemma7b + with `i < j` `j < k` dfth Lemma7b[of i k ?cp p p] have "dsc G p p" by auto with no_strict_arc have False by auto thus ?thesis .. qed next - assume "SCT' \" + assume "SCT' A" - show "SCT \" + show "SCT A" proof (rule classical) - assume "\ SCT \" + assume "\ SCT A" with SCT_def obtain p - where ipath: "has_ipath \ p" + where ipath: "has_ipath A p" and no_desc_th: "\ (\\. is_desc_thread \ p)" - by auto + by blast - from `bounded_acg P \` - have "finite (dest_graph (tcl \))" (is "finite ?AG") - by (intro bounded_finite bounded_plus) + from `finite_acg A` + have "finite_acg (tcl A)" by (simp add: finite_tcl) + hence "finite (dest_graph (tcl A))" (is "finite ?AG") + by (simp add: finite_acg_def finite_graph_def) from pdesc_acgplus[OF ipath] - have a: "\x y. x pdesc p\x,y\ \ dest_graph (tcl \)" + have a: "\x y. x pdesc p\x,y\ \ dest_graph (tcl A)" unfolding has_edge_def . obtain S G - where "infinite S" "G \ dest_graph (tcl \)" + where "infinite S" "G \ dest_graph (tcl A)" and all_G: "\x y. \ x \ S; y \ S; x < y\ \ pdesc (p\x,y\) = G" apply (rule RamseyNatpairs[of ?AG "\(x,y). pdesc p\x, y\"]) - apply (rule `finite (dest_graph (tcl \))`) + apply (rule `finite ?AG`) by (simp only:split_conv, rule a, auto) obtain n H m where @@ -1318,14 +1394,14 @@ note increasing_bij[OF this, simp] from ipath_contract inc ipath - have "has_ipath (tcl \) ?q" . + have "has_ipath (tcl A) ?q" . from all_G G_struct have all_H: "\i. (snd (?q i)) = H" unfolding contract_def by simp - have loop: "(tcl \) \ n \\<^bsup>H\<^esup> n" + have loop: "(tcl A) \ n \\<^bsup>H\<^esup> n" and idemp: "H * H = H" proof - let ?i = "?s 0" and ?j = "?s (Suc 0)" and ?k = "?s (Suc (Suc 0))" @@ -1345,8 +1421,8 @@ by auto hence "m = n" by simp - thus "tcl \ \ n \\<^bsup>H\<^esup> n" - using G_struct `G \ dest_graph (tcl \)` + thus "tcl A \ n \\<^bsup>H\<^esup> n" + using G_struct `G \ dest_graph (tcl A)` by (simp add:has_edge_def) from sub_path_prod[of ?i ?j ?k p] @@ -1355,7 +1431,7 @@ qed moreover have "\k. \dsc H k k" proof - fix k :: nat assume "dsc H k k" + fix k :: 'a assume "dsc H k k" with all_H repeated_edge have "\\. is_desc_thread \ ?q" by fast @@ -1366,22 +1442,10 @@ qed ultimately have False - using `SCT' \`[unfolded SCT'_def no_bad_graphs_def] + using `SCT' A`[unfolded SCT'_def no_bad_graphs_def] by blast thus ?thesis .. qed qed - -lemma LJA_apply: - assumes fin: "finite_acg A" - assumes "SCT' A" - shows "SCT A" -proof - - from fin obtain P where b: "bounded_acg P A" - unfolding finite_acg_def .. - show ?thesis using LJA_Theorem4[OF b] and `SCT' A` - by simp -qed - end diff -r 9dad8095bd43 -r b73a6b72f706 src/HOL/Library/Size_Change_Termination.thy --- a/src/HOL/Library/Size_Change_Termination.thy Tue Jun 19 00:02:16 2007 +0200 +++ b/src/HOL/Library/Size_Change_Termination.thy Tue Jun 19 18:00:49 2007 +0200 @@ -3,7 +3,7 @@ Author: Alexander Krauss, TU Muenchen *) -header "" (* FIXME proper header *) +header "Size-Change Termination" theory Size_Change_Termination imports SCT_Theorem SCT_Interpretation SCT_Implementation @@ -102,4 +102,10 @@ lemmas sctTest_congs = if_weak_cong let_weak_cong setbcomp_cong + +lemma SCT_Main: + "finite_acg A \ test_SCT A \ SCT A" + using LJA_Theorem4 SCT'_exec + by auto + end diff -r 9dad8095bd43 -r b73a6b72f706 src/HOL/Library/sct.ML --- a/src/HOL/Library/sct.ML Tue Jun 19 00:02:16 2007 +0200 +++ b/src/HOL/Library/sct.ML Tue Jun 19 18:00:49 2007 +0200 @@ -18,8 +18,8 @@ fun map_matrix f xss = map (map f) xss -val scgT = @{typ scg} -val acgT = @{typ acg} +val scgT = @{typ "nat scg"} +val acgT = @{typ "nat acg"} fun edgeT nT eT = HOLogic.mk_prodT (nT, HOLogic.mk_prodT (eT, nT)) fun graphT nT eT = Type ("Graphs.graph", [nT, eT])