diff --git a/thys/Graph_Saturation/GraphRewriting.thy b/thys/Graph_Saturation/GraphRewriting.thy --- a/thys/Graph_Saturation/GraphRewriting.thy +++ b/thys/Graph_Saturation/GraphRewriting.thy @@ -1,552 +1,552 @@ section \Graph rewriting and saturation\ text \Here we describe graph rewriting, again without connecting it to semantics.\ theory GraphRewriting imports RulesAndChains "HOL-Library.Infinite_Set" begin (* Algorithm 1 on page 16 *) text \To describe Algorithm 1, we give a single step instead of the recursive call. This allows us to reason about its effect without dealing with non-termination. We define a worklist, saying what work can be done. A valid selection needs to be made in order to ensure fairness. To do a step, we define the function extend, and use it in @{term make_step}. A function that always makes a valid selection is used in this step. \ abbreviation graph_of where "graph_of \ \ X. LG (snd X) {0.. nat" where "nextMax x \ if x = {} then 0 else Suc (Max x)" lemma nextMax_max[intro]: assumes "finite x" "v \ x" shows "v < nextMax x" "v \ nextMax x" using Max.coboundedI[OF assms] assms(2) unfolding nextMax_def by auto definition worklist :: "nat \ ('a \ nat \ nat) set \ (('a, 'b) labeled_graph \ ('a, 'b) labeled_graph) set \ (nat \ ('a, 'b) Graph_PreRule \ ('b \ nat) set) set" where "worklist G Rs \ let G = graph_of G in {(N,R,f). R\ Rs \ graph_homomorphism (fst R) G f \ N = nextMax (Range f) \ \ extensible R G f }" definition valid_selection where "valid_selection Rs G R f \ let wl = worklist G Rs in (nextMax (Range f), R,f) \ wl \ (\ (N,_) \ wl. N \ nextMax (Range f)) \ graph_rule R" lemma valid_selection_exists: assumes "worklist G Rs \ {}" "set_of_graph_rules Rs" shows "\L R f. valid_selection Rs G R f" proof - define wl where "wl = worklist G Rs" hence wl_ne:"wl \ {}" using assms(1) by auto let ?N = "LEAST N. N \ Domain wl" from wl_ne have "\ N. N \ Domain wl" by auto with LeastI2 have "?N \ Domain wl" by metis then obtain L R f where NLRf:"(?N,(L,R),f)\wl" by auto hence N_def:"?N = nextMax (Range f)" and in_Rs: "(L,R) \ Rs" unfolding wl_def worklist_def Let_def by auto from Least_le wl_ne Domain.intros case_prodI2 have min:"(\ (N',_) \ wl. N' \ ?N)" by (metis (no_types, lifting)) from in_Rs have "finite_graph R" "subgraph L R" using assms(2)[unfolded set_of_graph_rules_def] by auto with min NLRf N_def show ?thesis unfolding wl_def[symmetric] valid_selection_def by auto qed definition valid_selector where "valid_selector Rs selector \ \ G. (worklist G Rs \ {} \ (\ (R,f)\UNIV. selector G = Some (R,f) \ valid_selection Rs G R f)) \ (worklist G Rs = {} \ selector G = None)" lemma valid_selectorD[dest]: assumes "valid_selector Rs selector" shows "worklist G Rs = {} \ selector G = None" "selector G = Some (R,f) \ valid_selection Rs G R f" using assms[unfolded valid_selector_def,rule_format,of G] by (cases "worklist G Rs = {}",auto) text \The following gives a valid selector. This selector is not useful as concrete implementation, because it used the choice operation.\ definition non_constructive_selector where "non_constructive_selector Rs G \ let wl = worklist G Rs in if wl = {} then None else Some (SOME (R,f). valid_selection Rs G R f) " lemma non_constructive_selector: assumes "set_of_graph_rules Rs" shows "valid_selector Rs (non_constructive_selector Rs)" unfolding valid_selector_def proof((clarify,standard;clarify),goal_cases) case (1 n E) let ?x = "(SOME (R, f). valid_selection Rs (n, E) R f)" from valid_selection_exists[OF 1 assms] have "\ R f. valid_selection Rs (n, E) R f" by auto hence "\ x. valid_selection Rs (n, E) (fst x) (snd x)" by auto from this prod.case_eq_if tfl_some have "\ valid_selection Rs (n, E) (fst ?x) (snd ?x) \ False" by (metis (mono_tags, lifting)) thus ?case unfolding non_constructive_selector_def Let_def using 1 by (auto simp:prod_eq_iff) qed (auto simp:non_constructive_selector_def) text \The following is used to make a weak pushout step. In the paper, we aren't too specific on how this should be done. Here we are. We work on natural numbers in order to be able to pick fresh elements easily. \ definition extend :: "nat \ ('b, 'a::linorder) Graph_PreRule \ ('a \ nat) set \ ('a \ nat) set" where "extend n R f \ f \ (let V_new = sorted_list_of_set (vertices (snd R) - vertices (fst R)) in set (zip V_new [n..<(n+length V_new)]))" lemma nextMax_set[simp]: assumes "sorted xs" shows "nextMax (set xs) = (if xs = Nil then 0 else Suc (last xs))" using assms proof(induct xs) case Nil show ?case unfolding nextMax_def by auto next case (Cons a list) hence "list \ [] \ fold max list a = last list" using list_sorted_max by (metis last.simps) thus ?case unfolding nextMax_def Max.set_eq_fold by auto qed lemma nextMax_Un_eq[simp]: "finite x \ finite y \ nextMax (x \ y) = max (nextMax x) (nextMax y)" unfolding nextMax_def using Max_Un by auto lemma extend: (* extensible into the new graph *) assumes "graph_homomorphism (fst R) (LG E {0.. extend n R f" defines "G' \ LG ((on_triple g `` (edges (snd R))) \ E) {0.. g" "subgraph (LG E {0.. vertices (snd R)" and gr_R:"graph (snd R)" unfolding subgraph_def graph_union_iff by auto hence fin_R_L[simp]:"finite ?R_L" and fin_L:"finite (vertices (fst R))" using finite_subset by auto from assms have f_dom:"Domain f = vertices (fst R)" and f_uni:"univalent f" unfolding graph_homomorphism_def by auto from assms[unfolded graph_homomorphism_def] have "f `` vertices (fst R) \ vertices (LG E {0.. {0.. n" using f_ran Max_in[OF fin_f] by (simp add:nextMax_def Suc_leI subset_eq) have "x \ Domain ?g \ x \ Domain f" for x unfolding f_dom Let_def by auto - hence g_not_f:"(x,y) \ ?g \ (x,z) \ f" for x y z by auto + hence g_not_f:"(x,y) \ ?g \ (x,z) \ f" for x y z by blast have uni_g':"univalent ?g" "univalent (converse ?g)" unfolding Let_def by auto with f_uni have uni_g:"univalent g" by (auto simp:g_def extend_def g_not_f) from fin_g have "(a,b) \ g \ b < Suc (Max (Range g))" for a b unfolding less_Suc_eq_le by (rule Max.coboundedI) force hence "(a,b) \ g \ b < nextMax (Range g)" for a b unfolding nextMax_def by (cases "Range g = {}",auto) hence in_g:"(a,b) \ g \ b < max n (nextMax (Range g))" for a b by fastforce let ?G = "LG E {0.. E \ b < max n c" "(a, aa, b) \ E \ aa < max n c" for a aa b c by fastforce+ hence gr_G':"graph G'" unfolding G'_def restrict_def using in_g by auto show "subgraph (LG E {0.. g" by (auto simp:g_def extend_def) thus "agree_on (fst R) f g" using f_dom uni_g agree_on_subset equalityE by metis show "weak_universal t R ?G G' f g" proof fix a:: "('b \ 'x) set" fix b G assume a:"graph_homomorphism (snd R) G a" "graph_homomorphism ?G G b" "f O b \ a" hence univ_b:"univalent b" and univ_a:"univalent a" and rng_b:"Range b \ vertices G" and rng_a:"Range a \ vertices G" and ep_b:"edge_preserving b (edges (LG E {0.. b \ n \ y \ False" for y z using dom_b by (metis Domain.DomainI atLeastLessThan_iff not_less) have disj_doms:"Domain b \ Domain (?g\ O a) = {}" using help_dom_b unfolding Let_def by (auto dest!:set_zip_leftD) have "max n (nextMax (Range ?g)) = n + length (sorted_list_of_set ?R_L)" (is "_ = ?len") unfolding Let_def Range_snd set_map[symmetric] map_snd_zip[OF ln] nextMax_set[OF sorted_upt] - by fastforce + by (fastforce simp del: length_sorted_list_of_set) hence n_eq:"?len = max n (nextMax (Range g))" unfolding Range_snd[symmetric] g_def extend_def Range_Un_eq nextMax_Un_eq[OF fin_f fin_g'(2)] max.assoc[symmetric] max_absorb1[OF nextMax_f] by auto let ?h = "b \ ?g\ O a" have dg:"Domain (?g\) = {n.. vertices (fst R))" using dom_a subsLR by auto - also have "\ = ?g `` ?R_L \ ?g `` vertices (fst R)" by auto + also have "\ = ?g `` ?R_L \ ?g `` vertices (fst R)" by blast also have "?g `` vertices (fst R) = {}" apply(rule Image_outside_Domain) unfolding Let_def Domain_set_zip[OF ln] by auto also have "?g `` ?R_L = Range ?g" apply(rule Image_Domain) unfolding Let_def Domain_set_zip[OF ln] by auto finally have dg2:"?g `` Domain a = {n.. O a) = {n.. vertices G" "(?g\ O a) `` vertices G' \ vertices G" using rng_a rng_b by auto hence v2: "?h `` vertices G' \ vertices G" by blast have v3: "univalent ?h" using disj_doms univalent_union[OF univ_b univalent_composes[OF uni_g'(2) univ_a]] by blast (* showing edge preservation *) { fix l x y x' y' assume a2:"(l,x,y) \ edges G'" "(x,x') \ ?h" "(y,y') \ ?h" have "(l,x',y') \ edges G" proof(cases "(l,x,y) \ edges ?G") case True with gr_G[THEN restrictD] have "x \ Domain b" "y \ Domain b" unfolding dom_b by auto hence "x \ Domain (converse ?g O a)" "y \ Domain (converse ?g O a)" using disj_doms by blast+ hence "(x,x') \ b" "(y,y') \ b" using a2 by auto with ep_b True show ?thesis unfolding edge_preserving by auto next have "g O ?h = f O b \ ?g O b \ ((f O ?g\) O a \ (?g O ?g\) O a)" unfolding g_def extend_def by blast also have "(?g O ?g\) = Id_on ?R_L" unfolding univalent_O_converse[OF uni_g'(2)] unfolding Let_def by auto also have "(f O ?g\) = {}" using f_ran unfolding Let_def by (auto dest!:set_zip_leftD) also have "?g O b = {}" using help_dom_b unfolding Let_def by (auto dest!:set_zip_rightD) finally have gOh:"g O ?h \ a" using a(3) by blast case False hence "(l,x,y) \ on_triple g `` edges (snd R)" using a2(1) unfolding G'_def by auto then obtain r_x r_y where r:"(l,r_x,r_y) \ edges (snd R)" "(r_x,x) \ g" "(r_y,y) \ g" by auto hence "(r_x,x') \ a" "(r_y,y') \ a" using gOh a2(2,3) by auto hence "(l,x',y') \ on_triple a `` edges (snd R)" using r(1) unfolding on_triple_def by auto thus ?thesis using ep_a unfolding edge_preserving by auto qed } hence v4: "edge_preserving ?h (edges G') (edges G)" by auto have "graph_homomorphism G' G ?h" by(fact graph_homomorphismI[OF v1 v2 v3 v4 gr_G' v6]) thus "\h. graph_homomorphism G' G h \ b \ h" by auto qed qed text \Showing that the extend function indeed creates a valid pushout.\ lemma selector_pushout: assumes "valid_selector Rs selector" "selector G'' = Some (R,f)" defines "G \ graph_of G''" assumes "graph G" defines "g \ extend (fst G'') R f" defines "G' \ LG (on_triple g `` edges (snd R) \ (snd G'')) {0.. g" "weak_universal t R G G' f g" using extend[OF igh[unfolded G_def],folded g_def,folded G'_def,folded G_def] igh(1) by auto thus ?thesis unfolding pushout_step_def by auto qed text \Making a single step in Algorithm 1. A prerequisite is that its first argument is a @{term valid_selector}.\ definition make_step where "make_step selector S \ case selector S of None \ S | Some (R,f) \ (let g = extend (fst S) R f in (max (fst S) (nextMax (Range g)), (on_triple g `` (edges (snd R))) \ (snd S)))" lemma WPC_through_make_step: assumes "set_of_graph_rules Rs" "graph (graph_of (X 0))" and makestep: "\ i. X (Suc i) = make_step selector (X i)" and selector: "valid_selector Rs selector" shows "Simple_WPC t Rs (\ i. graph_of (X i))" "chain (\ i. graph_of (X i))" proof note ms = makestep[unfolded make_step_def,rule_format] have gr:"graph (graph_of (X i))" for i proof(induct i) case (Suc i) then show ?case proof(cases "selector (X i)") case None then show ?thesis using ms Suc by auto next case (Some a) then obtain R f where Some:"selector (X i) = Some (R,f)" by fastforce then show ?thesis using ms[of i,unfolded Some Let_def] selector_pushout[OF selector Some Suc,of t ,unfolded pushout_step_def subgraph_def] by auto qed qed (fact assms) show "chain (\ i. graph_of (X i))" unfolding chain_def proof(clarify) fix i show "subgraph (graph_of (X i)) (graph_of (X (i + 1)))" proof(cases "selector (X i)") case None then show ?thesis using ms gr by (auto intro!:graph_homomorphismI) next case Some then obtain R f where Some:"selector (X i) = Some (R,f)" by fastforce then show ?thesis using ms selector_pushout[OF selector Some gr,of t] unfolding pushout_step_def Let_def by simp qed qed show "graph_of (X i) = graph_of (X (Suc i)) \ (\R\Rs. pushout_step t R (graph_of (X i)) (graph_of (X (Suc i))))" for i proof(cases "selector (X i)") case None thus ?thesis using ms by auto next case Some then obtain R f where Some:"selector (X i) = Some (R,f)" by fastforce hence "R \ Rs" using valid_selectorD(2)[OF selector,unfolded valid_selection_def worklist_def Let_def] by(cases R,blast) then show ?thesis using ms[of i,unfolded Some Let_def] selector_pushout[OF selector Some gr] unfolding make_step_def by auto qed qed (fact assms)+ lemma N_occurs_finitely_often: assumes "finite Rs" "set_of_graph_rules Rs" "graph (graph_of (X 0))" and makestep: "\ i. X (Suc i) = make_step selector (X i)" and selector: "valid_selector Rs selector" shows "finite {(R,f). \ i. R\ Rs \ graph_homomorphism (fst R) (graph_of (X i)) f \ nextMax (Range f) \ N}" (is "finite {(R,f).?P R f}") proof - have prod_eq : "(\ x \ {(x, y). A x y}. B x) \ (\ x. A (fst x) (snd x) \ B x)" "(x \ {(x, y). A x y}) \ (A (fst x) (snd x))" for A B x by auto let ?S = "{(R,f).?P R f}" let "?Q R f" = "Domain f = vertices (fst (R::('a, 'b) Graph_PreRule)) \ univalent f \ nextMax (Range f) \ N" have seteq:"(\R\Rs. {(R', f). R' = R \ ?Q R f}) = {(R,f). R \ Rs \ ?Q R f}" by auto have "\ R \ Rs. finite {(R',f). R' = R \ ?Q R f}" proof fix R assume "R \ Rs" hence fin:"finite (vertices (fst R))" using assms by auto hence fin2:"finite (Pow (vertices (fst R) \ {0..N}))" by auto have fin:"Domain x = vertices (fst R) \ univalent x \ finite (snd ` x)" for x:: "('b \ nat) set" using fin univalent_finite[of x] by simp hence "Domain f = vertices (fst R) \ univalent f \ (a,b) \ f \ nextMax (Range f) \ N \ b \ N" for f a b unfolding Range_snd using image_eqI nextMax_max(2) snd_conv order.trans by metis hence sub:"{f. ?Q R f} \ Pow (vertices (fst R) \ {0..N})" using nextMax_max[OF fin] by (auto simp:Range_snd image_def) from finite_subset[OF sub fin2] show "finite {(R',f). R' = R \ ?Q R f}" by auto qed from this[folded finite_UN[OF assms(1)],unfolded seteq] have fin:"finite {(R,f). R \ Rs \ ?Q R f}". have "?P R f \ R \ Rs \ ?Q R f" for R f unfolding graph_homomorphism_def by auto hence "?S \ {(R,f). R \ Rs \ ?Q R f}" unfolding subset_eq prod_eq by blast from finite_subset[OF this fin] show ?thesis by auto qed lemma inj_on_infinite: assumes "infinite A" "inj_on f A" "range f \ B" shows "infinite B" proof - from assms[unfolded infinite_iff_countable_subset] obtain g::"nat \ 'a" where g:"inj g \ range g \ A" by blast hence i:"inj (f o g)" using assms(2) using comp_inj_on inj_on_subset by blast have "range (f o g) \ B" using assms(3) by auto with i show ?thesis unfolding infinite_iff_countable_subset by blast qed lemma makestep_makes_selector_inj: assumes "selector (X y) = Some (R,f)" "selector (X x) = Some (R,f)" "valid_selector Rs selector" and step: "\ i. X (Suc i) = make_step selector (X i)" and chain:"chain (\ i. graph_of (X i))" shows "x = y" proof(rule ccontr) assume a:"x \ y" define x' y' where "x' \ min x y" "y' \ max x y" hence xy:"selector (X x') = Some (R, f)" "selector (X y') = Some (R, f)" "x' < y'" using assms(1,2) a unfolding min_def max_def by auto with valid_selectorD assms have "valid_selection Rs (X x') R f" "valid_selection Rs (X y') R f" by auto hence not_ex:"\ extensible R (graph_of (X y')) f" and hom:"graph_homomorphism (fst R) (graph_of (X x')) f" "graph_rule R" unfolding valid_selection_def Let_def worklist_def by auto have X:"X (Suc x') = (max (fst (X x')) (nextMax (Range (extend (fst (X x')) R f))), on_triple (extend (fst (X x')) R f) `` edges (snd R) \ snd (X x'))" unfolding step[unfolded make_step_def Let_def,rule_format] xy by auto let ?ex = "extend (fst (X x')) R f" have hom:"graph_homomorphism (snd R) (graph_of (X (Suc x'))) ?ex" and agr:"agree_on (fst R) f ?ex" using extend(1,2)[OF hom] unfolding X by auto from xy have "Suc x' \ y'" by auto with chain[unfolded chain_def2] have "subgraph (graph_of (X (Suc x'))) (graph_of (X y'))" by auto from subgraph_preserves_hom[OF this hom] have hom:"graph_homomorphism (snd R) (graph_of (X y')) ?ex". with agr have "extensible R (graph_of (X y')) f" unfolding extensible_def by auto thus False using not_ex by auto qed lemma fair_through_make_step: assumes "finite Rs" "set_of_graph_rules Rs" "graph (graph_of (X 0))" (* It should suffice to take infinitely many make_steps, rather than having every step be a make_step, but we focus on the algorithm as in the paper here *) and makestep: "\ i. X (Suc i) = make_step selector (X i)" and selector: "valid_selector Rs selector" shows "fair_chain Rs (\ i. graph_of (X i))" proof show chn:"chain (\i. graph_of (X i))" using WPC_through_make_step assms by blast fix R f i assume Rs:"R \ Rs" and h:"graph_homomorphism (fst R) (graph_of (X i)) f" hence R:"finite (vertices (snd R))" "subgraph (fst R) (snd R)" "finite (vertices (fst R))" using assms by auto hence f:"finite f" "finite (Range f)" "finite (Domain f)" "univalent f" using h unfolding graph_homomorphism_def Range_snd by auto define N where "N \ nextMax (Range f)" fix S let "?Q X' j" = " fst X' \ Rs \ graph_homomorphism (fst (fst X')) (graph_of (X (j+i))) (snd X') \ nextMax (Range (snd X')) \ N" let ?S = "{(R,f). \j. ?Q (R,f) j}" from assms(4) have "\ia. X (Suc ia + i) = make_step selector (X (ia + i))" by auto note r = assms(1,2) chain_then_restrict[OF chn] this assms(5) from N_occurs_finitely_often[of Rs "\ j. X (j + i)",OF r] have fin_S:"finite ?S" by auto { assume a:"\j. \ extensible R (graph_of (X j)) f" let "?P X' j" = "?Q X' j \ Some X' = selector (X (j+i))" { fix j let ?j = "j+i" have "?j \ i" by auto from subgraph_preserves_hom[OF chain[OF chn this] h] have h:"graph_homomorphism (fst R) (graph_of (X ?j)) f". have "\ extensible R (graph_of (X ?j)) f" using a by blast with h Rs have wl:"(nextMax (Range f),R,f) \ worklist (X ?j) Rs" unfolding worklist_def Let_def set_eq_iff by auto hence "worklist (X ?j) Rs \ {}" by auto with valid_selectorD[OF selector] obtain R' f' where sel:"Some (R',f') = selector (X ?j)" "valid_selection Rs (X ?j) R' f'" by auto hence max:"(nextMax (Range f'), R', f') \ worklist (X ?j) Rs" "(\(N, _)\worklist (X ?j) Rs. nextMax (Range f') \ N)" unfolding valid_selection_def Let_def by auto with wl have "nextMax (Range f') \ N" unfolding N_def by auto with max(1)[unfolded worklist_def Let_def mem_Collect_eq prod.case] sel(1) have "\ X'. ?P X' j" by (metis fst_conv snd_conv) } then obtain ch where ch:"\ j. ?P (ch j) j" by metis (* uses 'choice' internally *) have inj:"inj ch" proof fix x y assume "ch x = ch y" with ch[of x] ch[of y] have "selector (X (x + i)) = Some (ch x)" "selector (X (y + i)) = Some (ch x)" by auto with makestep_makes_selector_inj[OF _ _ selector makestep chn] have "x + i = y + i" by (cases "ch x",metis (full_types)) thus "x = y" by auto qed have "ch x \ ?S" for x using ch[of x] unfolding mem_Collect_eq by(intro case_prodI2) metis hence "range ch \ ?S" unfolding UNIV_def by(rule image_Collect_subsetI) with infinite_iff_countable_subset inj have "infinite ?S" by blast with fin_S have "False" by auto } thus "\j. extensible R (graph_of (X j)) f" by auto qed fun mk_chain where "mk_chain sel Rs init 0 = init" | "mk_chain sel Rs init (Suc n) = mk_chain sel Rs (make_step sel init) n" lemma mk_chain: "\ i. mk_chain sel Rs init (Suc i) = make_step sel (mk_chain sel Rs init i)" proof fix i show "mk_chain sel Rs init (Suc i) = make_step sel (mk_chain sel Rs init i)" by (induct i arbitrary:init,auto) qed text \Algorithm 1, abstractly.\ abbreviation the_lcg where "the_lcg sel Rs init \ chain_sup (\i. graph_of (mk_chain sel Rs init i))" lemma mk_chain_edges: assumes "valid_selector Rules sel" "\ ((edges o snd) ` Rules) \ L \ UNIV" "edges (graph_of G) \ L \ UNIV" shows "edges (graph_of (mk_chain sel Rules G i)) \ L \ UNIV" using assms(3) proof(induct i arbitrary:G) case 0 then show ?case using assms(2) by auto next case (Suc i G) hence "edges (graph_of (make_step sel G)) \ L \ UNIV" proof(cases "sel G") case None show ?thesis unfolding None make_step_def using Suc by auto next case (Some a) then obtain R f where Some:"sel G = Some (R, f)" by fastforce hence "(a, x, y) \ edges (snd R) \ a \ L" for a x y using assms(2) valid_selectorD(2)[OF assms(1) Some] unfolding valid_selection_def Let_def worklist_def by auto then show ?thesis unfolding Some make_step_def Let_def using Suc by auto qed thus ?case unfolding mk_chain.simps by(rule Suc) qed lemma the_lcg_edges: assumes "valid_selector Rules sel" "fst ` (\ ((edges o snd) ` Rules)) \ L" (is "fst `?fR \ _") "fst ` snd G \ L" shows "fst ` edges (the_lcg sel Rules G) \ L" proof - from assms have "fst `?fR \ UNIV \ L \ UNIV" "fst `(edges (graph_of G)) \ UNIV \ L \ UNIV" by auto hence "(\ ((edges o snd) ` Rules)) \ L \ UNIV" "edges (graph_of G) \ L \ UNIV" using fst_UNIV[of ?fR] fst_UNIV[of "(edges (graph_of G))"] by blast+ note assms = assms(1) this have "edges (graph_of (mk_chain sel Rules G i)) \ L \ UNIV" for i using mk_chain_edges[OF assms,unfolded Times_subset_cancel2[OF UNIV_I]]. hence "edges (the_lcg sel Rules G) \ L \ UNIV" unfolding chain_sup_def by auto thus ?thesis by auto qed text \Lemma 9.\ lemma lcg_through_make_step: assumes "finite Rs" "set_of_graph_rules Rs" "graph (graph_of init)" "valid_selector Rs sel" shows "least_consequence_graph t Rs (graph_of init) (the_lcg sel Rs init)" proof - from assms have gr:"graph (graph_of (mk_chain sel Rs init 0))" by auto note assms = assms(1,2) this mk_chain assms(4) from set_of_graph_rulesD[OF assms(2)] have "(\R. R \ Rs \ subgraph (fst R) (snd R) \ finite_graph (fst R))" by auto from fair_chain_impl_consequence_graph[OF fair_through_make_step[OF assms] this] wpc_simpl[OF WPC_through_make_step(1)[OF assms(2-)],THEN wpc_least] show ?thesis unfolding least_consequence_graph_def by auto qed end diff --git a/thys/UTP/toolkit/List_Extra.thy b/thys/UTP/toolkit/List_Extra.thy --- a/thys/UTP/toolkit/List_Extra.thy +++ b/thys/UTP/toolkit/List_Extra.thy @@ -1,892 +1,890 @@ (******************************************************************************) (* Project: Isabelle/UTP Toolkit *) (* File: List_Extra.thy *) (* Authors: Simon Foster and Frank Zeyda *) (* Emails: simon.foster@york.ac.uk and frank.zeyda@york.ac.uk *) (******************************************************************************) section \ Lists: extra functions and properties \ theory List_Extra imports "HOL-Library.Sublist" "HOL-Library.Monad_Syntax" "HOL-Library.Prefix_Order" "Optics.Lens_Instances" begin subsection \ Useful Abbreviations \ abbreviation "list_sum xs \ foldr (+) xs 0" subsection \ Folds \ context abel_semigroup begin lemma foldr_snoc: "foldr (\<^bold>*) (xs @ [x]) k = (foldr (\<^bold>*) xs k) \<^bold>* x" by (induct xs, simp_all add: commute left_commute) end subsection \ List Lookup \ text \ The following variant of the standard \nth\ function returns \\\ if the index is out of range. \ primrec nth_el :: "'a list \ nat \ 'a option" ("_\_\\<^sub>l" [90, 0] 91) where "[]\i\\<^sub>l = None" | "(x # xs)\i\\<^sub>l = (case i of 0 \ Some x | Suc j \ xs \j\\<^sub>l)" lemma nth_el_appendl[simp]: "i < length xs \ (xs @ ys)\i\\<^sub>l = xs\i\\<^sub>l" apply (induct xs arbitrary: i) apply simp apply (case_tac i) apply simp_all done lemma nth_el_appendr[simp]: "length xs \ i \ (xs @ ys)\i\\<^sub>l = ys\i - length xs\\<^sub>l" apply (induct xs arbitrary: i) apply simp apply (case_tac i) apply simp_all done subsection \ Extra List Theorems \ subsubsection \ Map \ lemma map_nth_Cons_atLeastLessThan: "map (nth (x # xs)) [Suc m.. Suc" by auto hence "map (nth xs) [m.. Suc) [m.. Sorted Lists \ lemma sorted_last [simp]: "\ x \ set xs; sorted xs \ \ x \ last xs" by (induct xs, auto) lemma sorted_prefix: assumes "xs \ ys" "sorted ys" shows "sorted xs" proof - obtain zs where "ys = xs @ zs" using Prefix_Order.prefixE assms(1) by auto thus ?thesis using assms(2) sorted_append by blast qed lemma sorted_map: "\ sorted xs; mono f \ \ sorted (map f xs)" by (simp add: monoD sorted_iff_nth_mono) lemma sorted_distinct [intro]: "\ sorted (xs); distinct(xs) \ \ (\ i Is the given list a permutation of the given set? \ definition is_sorted_list_of_set :: "('a::ord) set \ 'a list \ bool" where "is_sorted_list_of_set A xs = ((\ i set(xs) = A)" lemma sorted_is_sorted_list_of_set: assumes "is_sorted_list_of_set A xs" shows "sorted(xs)" and "distinct(xs)" using assms proof (induct xs arbitrary: A) show "sorted []" by auto next show "distinct []" by auto next fix A :: "'a set" case (Cons x xs) note hyps = this assume isl: "is_sorted_list_of_set A (x # xs)" hence srt: "(\in. \ n < length (x # xs) - 1 \ (x # xs) ! n < (x # xs) ! (n + 1)) \ set (x # xs) = A" by (meson \is_sorted_list_of_set A (x # xs)\ is_sorted_list_of_set_def) then show ?thesis by (metis \distinct xs\ add.commute add_diff_cancel_left' distinct.simps(2) leD length_Cons length_greater_0_conv length_pos_if_in_set less_le nth_Cons_0 nth_Cons_Suc plus_1_eq_Suc set_ConsD sorted.elims(2) srtd) qed qed lemma is_sorted_list_of_set_alt_def: "is_sorted_list_of_set A xs \ sorted (xs) \ distinct (xs) \ set(xs) = A" apply (auto intro: sorted_is_sorted_list_of_set) apply (auto simp add: is_sorted_list_of_set_def) apply (metis Nat.add_0_right One_nat_def add_Suc_right sorted_distinct) done definition sorted_list_of_set_alt :: "('a::ord) set \ 'a list" where "sorted_list_of_set_alt A = (if (A = {}) then [] else (THE xs. is_sorted_list_of_set A xs))" lemma is_sorted_list_of_set: "finite A \ is_sorted_list_of_set A (sorted_list_of_set A)" - apply (simp add: is_sorted_list_of_set_def) - apply (metis One_nat_def add.right_neutral add_Suc_right sorted_distinct sorted_list_of_set) - done + by (simp add: is_sorted_list_of_set_alt_def) lemma sorted_list_of_set_other_def: "finite A \ sorted_list_of_set(A) = (THE xs. sorted(xs) \ distinct(xs) \ set xs = A)" apply (rule sym) apply (rule the_equality) apply (auto) apply (simp add: sorted_distinct_set_unique) done lemma sorted_list_of_set_alt [simp]: "finite A \ sorted_list_of_set_alt(A) = sorted_list_of_set(A)" apply (rule sym) apply (auto simp add: sorted_list_of_set_alt_def is_sorted_list_of_set_alt_def sorted_list_of_set_other_def) done text \ Sorting lists according to a relation \ definition is_sorted_list_of_set_by :: "'a rel \ 'a set \ 'a list \ bool" where "is_sorted_list_of_set_by R A xs = ((\ i R) \ set(xs) = A)" definition sorted_list_of_set_by :: "'a rel \ 'a set \ 'a list" where "sorted_list_of_set_by R A = (THE xs. is_sorted_list_of_set_by R A xs)" definition fin_set_lexord :: "'a rel \ 'a set rel" where "fin_set_lexord R = {(A, B). finite A \ finite B \ (\ xs ys. is_sorted_list_of_set_by R A xs \ is_sorted_list_of_set_by R B ys \ (xs, ys) \ lexord R)}" lemma is_sorted_list_of_set_by_mono: "\ R \ S; is_sorted_list_of_set_by R A xs \ \ is_sorted_list_of_set_by S A xs" by (auto simp add: is_sorted_list_of_set_by_def) lemma lexord_mono': "\ (\ x y. f x y \ g x y); (xs, ys) \ lexord {(x, y). f x y} \ \ (xs, ys) \ lexord {(x, y). g x y}" by (metis case_prodD case_prodI lexord_take_index_conv mem_Collect_eq) lemma fin_set_lexord_mono [mono]: "(\ x y. f x y \ g x y) \ (xs, ys) \ fin_set_lexord {(x, y). f x y} \ (xs, ys) \ fin_set_lexord {(x, y). g x y}" proof assume fin: "(xs, ys) \ fin_set_lexord {(x, y). f x y}" and hyp: "(\ x y. f x y \ g x y)" from fin have "finite xs" "finite ys" using fin_set_lexord_def by fastforce+ with fin hyp show "(xs, ys) \ fin_set_lexord {(x, y). g x y}" apply (auto simp add: fin_set_lexord_def) apply (rename_tac xs' ys') apply (rule_tac x="xs'" in exI) apply (auto) apply (metis case_prodD case_prodI is_sorted_list_of_set_by_def mem_Collect_eq) apply (metis case_prodD case_prodI is_sorted_list_of_set_by_def lexord_mono' mem_Collect_eq) done qed definition distincts :: "'a set \ 'a list set" where "distincts A = {xs \ lists A. distinct(xs)}" lemma tl_element: "\ x \ set xs; x \ hd(xs) \ \ x \ set(tl(xs))" by (metis in_set_insert insert_Nil list.collapse list.distinct(2) set_ConsD) subsubsection \ List Update \ lemma listsum_update: fixes xs :: "'a::ring list" assumes "i < length xs" shows "list_sum (xs[i := v]) = list_sum xs - xs ! i + v" using assms proof (induct xs arbitrary: i) case Nil then show ?case by (simp) next case (Cons a xs) then show ?case proof (cases i) case 0 thus ?thesis by (simp add: add.commute) next case (Suc i') with Cons show ?thesis by (auto) qed qed subsubsection \ Drop While and Take While \ lemma dropWhile_sorted_le_above: "\ sorted xs; x \ set (dropWhile (\ x. x \ n) xs) \ \ x > n" apply (induct xs) apply (auto) apply (rename_tac a xs) apply (case_tac "a \ n") apply (auto) done lemma set_dropWhile_le: "sorted xs \ set (dropWhile (\ x. x \ n) xs) = {x\set xs. x > n}" apply (induct xs) apply (simp) apply (rename_tac x xs) apply (subgoal_tac "sorted xs") apply (simp) apply (safe) apply (auto) done lemma set_takeWhile_less_sorted: "\ sorted I; x \ set I; x < n \ \ x \ set (takeWhile (\x. x < n) I)" proof (induct I arbitrary: x) case Nil thus ?case by (simp) next case (Cons a I) thus ?case by auto qed lemma nth_le_takeWhile_ord: "\ sorted xs; i \ length (takeWhile (\ x. x \ n) xs); i < length xs \ \ n \ xs ! i" apply (induct xs arbitrary: i, auto) apply (rename_tac x xs i) apply (case_tac "x \ n") apply (auto) apply (metis One_nat_def Suc_eq_plus1 le_less_linear le_less_trans less_imp_le list.size(4) nth_mem set_ConsD) done lemma length_takeWhile_less: "\ a \ set xs; \ P a \ \ length (takeWhile P xs) < length xs" by (metis in_set_conv_nth length_takeWhile_le nat_neq_iff not_less set_takeWhileD takeWhile_nth) lemma nth_length_takeWhile_less: "\ sorted xs; distinct xs; (\ a \ set xs. a \ n) \ \ xs ! length (takeWhile (\x. x < n) xs) \ n" by (induct xs, auto) subsubsection \ Last and But Last \ lemma length_gt_zero_butlast_concat: assumes "length ys > 0" shows "butlast (xs @ ys) = xs @ (butlast ys)" using assms by (metis butlast_append length_greater_0_conv) lemma length_eq_zero_butlast_concat: assumes "length ys = 0" shows "butlast (xs @ ys) = butlast xs" using assms by (metis append_Nil2 length_0_conv) lemma butlast_single_element: shows "butlast [e] = []" by (metis butlast.simps(2)) lemma last_single_element: shows "last [e] = e" by (metis last.simps) lemma length_zero_last_concat: assumes "length t = 0" shows "last (s @ t) = last s" by (metis append_Nil2 assms length_0_conv) lemma length_gt_zero_last_concat: assumes "length t > 0" shows "last (s @ t) = last t" by (metis assms last_append length_greater_0_conv) subsubsection \ Prefixes and Strict Prefixes \ lemma prefix_length_eq: "\ length xs = length ys; prefix xs ys \ \ xs = ys" by (metis not_equal_is_parallel parallel_def) lemma prefix_Cons_elim [elim]: assumes "prefix (x # xs) ys" obtains ys' where "ys = x # ys'" "prefix xs ys'" using assms by (metis append_Cons prefix_def) lemma prefix_map_inj: "\ inj_on f (set xs \ set ys); prefix (map f xs) (map f ys) \ \ prefix xs ys" apply (induct xs arbitrary:ys) apply (simp_all) apply (erule prefix_Cons_elim) apply (auto) apply (metis image_insert insertI1 insert_Diff_if singletonE) done lemma prefix_map_inj_eq [simp]: "inj_on f (set xs \ set ys) \ prefix (map f xs) (map f ys) \ prefix xs ys" using map_mono_prefix prefix_map_inj by blast lemma strict_prefix_Cons_elim [elim]: assumes "strict_prefix (x # xs) ys" obtains ys' where "ys = x # ys'" "strict_prefix xs ys'" using assms by (metis Sublist.strict_prefixE' Sublist.strict_prefixI' append_Cons) lemma strict_prefix_map_inj: "\ inj_on f (set xs \ set ys); strict_prefix (map f xs) (map f ys) \ \ strict_prefix xs ys" apply (induct xs arbitrary:ys) apply (auto) using prefix_bot.bot.not_eq_extremum apply fastforce apply (erule strict_prefix_Cons_elim) apply (auto) apply (metis (hide_lams, full_types) image_insert insertI1 insert_Diff_if singletonE) done lemma strict_prefix_map_inj_eq [simp]: "inj_on f (set xs \ set ys) \ strict_prefix (map f xs) (map f ys) \ strict_prefix xs ys" by (simp add: inj_on_map_eq_map strict_prefix_def) lemma prefix_drop: "\ drop (length xs) ys = zs; prefix xs ys \ \ ys = xs @ zs" by (metis append_eq_conv_conj prefix_def) lemma list_append_prefixD [dest]: "x @ y \ z \ x \ z" using append_prefixD less_eq_list_def by blast lemma prefix_not_empty: assumes "strict_prefix xs ys" and "xs \ []" shows "ys \ []" using Sublist.strict_prefix_simps(1) assms(1) by blast lemma prefix_not_empty_length_gt_zero: assumes "strict_prefix xs ys" and "xs \ []" shows "length ys > 0" using assms prefix_not_empty by auto lemma butlast_prefix_suffix_not_empty: assumes "strict_prefix (butlast xs) ys" shows "ys \ []" using assms prefix_not_empty_length_gt_zero by fastforce lemma prefix_and_concat_prefix_is_concat_prefix: assumes "prefix s t" "prefix (e @ t) u" shows "prefix (e @ s) u" using Sublist.same_prefix_prefix assms(1) assms(2) prefix_order.dual_order.trans by blast lemma prefix_eq_exists: "prefix s t \ (\xs . s @ xs = t)" using prefix_def by auto lemma strict_prefix_eq_exists: "strict_prefix s t \ (\xs . s @ xs = t \ (length xs) > 0)" using prefix_def strict_prefix_def by auto lemma butlast_strict_prefix_eq_butlast: assumes "length s = length t" and "strict_prefix (butlast s) t" shows "strict_prefix (butlast s) t \ (butlast s) = (butlast t)" by (metis append_butlast_last_id append_eq_append_conv assms(1) assms(2) length_0_conv length_butlast strict_prefix_eq_exists) lemma butlast_eq_if_eq_length_and_prefix: assumes "length s > 0" "length z > 0" "length s = length z" "strict_prefix (butlast s) t" "strict_prefix (butlast z) t" shows "(butlast s) = (butlast z)" using assms by (auto simp add:strict_prefix_eq_exists) lemma prefix_imp_length_lteq: assumes "prefix s t" shows "length s \ length t" using assms by (simp add: Sublist.prefix_length_le) lemma prefix_imp_length_not_gt: assumes "prefix s t" shows "\ length t < length s" using assms by (simp add: Sublist.prefix_length_le leD) lemma prefix_and_eq_length_imp_eq_list: assumes "prefix s t" and "length t = length s" shows "s=t" using assms by (simp add: prefix_length_eq) lemma butlast_prefix_imp_length_not_gt: assumes "length s > 0" "strict_prefix (butlast s) t" shows "\ (length t < length s)" using assms prefix_length_less by fastforce lemma length_not_gt_iff_eq_length: assumes "length s > 0" and "strict_prefix (butlast s) t" shows "(\ (length s < length t)) = (length s = length t)" proof - have "(\ (length s < length t)) = ((length t < length s) \ (length s = length t))" by (metis not_less_iff_gr_or_eq) also have "... = (length s = length t)" using assms by (simp add:butlast_prefix_imp_length_not_gt) finally show ?thesis . qed text \ Greatest common prefix \ fun gcp :: "'a list \ 'a list \ 'a list" where "gcp [] ys = []" | "gcp (x # xs) (y # ys) = (if (x = y) then x # gcp xs ys else [])" | "gcp _ _ = []" lemma gcp_right [simp]: "gcp xs [] = []" by (induct xs, auto) lemma gcp_append [simp]: "gcp (xs @ ys) (xs @ zs) = xs @ gcp ys zs" by (induct xs, auto) lemma gcp_lb1: "prefix (gcp xs ys) xs" apply (induct xs arbitrary: ys, auto) apply (case_tac ys, auto) done lemma gcp_lb2: "prefix (gcp xs ys) ys" apply (induct ys arbitrary: xs, auto) apply (case_tac xs, auto) done interpretation prefix_semilattice: semilattice_inf gcp prefix strict_prefix proof fix xs ys :: "'a list" show "prefix (gcp xs ys) xs" by (induct xs arbitrary: ys, auto, case_tac ys, auto) show "prefix (gcp xs ys) ys" by (induct ys arbitrary: xs, auto, case_tac xs, auto) next fix xs ys zs :: "'a list" assume "prefix xs ys" "prefix xs zs" thus "prefix xs (gcp ys zs)" by (simp add: prefix_def, auto) qed subsubsection \ Lexicographic Order \ lemma lexord_append: assumes "(xs\<^sub>1 @ ys\<^sub>1, xs\<^sub>2 @ ys\<^sub>2) \ lexord R" "length(xs\<^sub>1) = length(xs\<^sub>2)" shows "(xs\<^sub>1, xs\<^sub>2) \ lexord R \ (xs\<^sub>1 = xs\<^sub>2 \ (ys\<^sub>1, ys\<^sub>2) \ lexord R)" using assms proof (induct xs\<^sub>2 arbitrary: xs\<^sub>1) case (Cons x\<^sub>2 xs\<^sub>2') note hyps = this from hyps(3) obtain x\<^sub>1 xs\<^sub>1' where xs\<^sub>1: "xs\<^sub>1 = x\<^sub>1 # xs\<^sub>1'" "length(xs\<^sub>1') = length(xs\<^sub>2')" by (auto, metis Suc_length_conv) with hyps(2) have xcases: "(x\<^sub>1, x\<^sub>2) \ R \ (xs\<^sub>1' @ ys\<^sub>1, xs\<^sub>2' @ ys\<^sub>2) \ lexord R" by (auto) show ?case proof (cases "(x\<^sub>1, x\<^sub>2) \ R") case True with xs\<^sub>1 show ?thesis by (auto) next case False with xcases have "(xs\<^sub>1' @ ys\<^sub>1, xs\<^sub>2' @ ys\<^sub>2) \ lexord R" by (auto) with hyps(1) xs\<^sub>1 have dichot: "(xs\<^sub>1', xs\<^sub>2') \ lexord R \ (xs\<^sub>1' = xs\<^sub>2' \ (ys\<^sub>1, ys\<^sub>2) \ lexord R)" by (auto) have "x\<^sub>1 = x\<^sub>2" using False hyps(2) xs\<^sub>1(1) by auto with dichot xs\<^sub>1 show ?thesis by (simp) qed next case Nil thus ?case by auto qed lemma strict_prefix_lexord_rel: "strict_prefix xs ys \ (xs, ys) \ lexord R" by (metis Sublist.strict_prefixE' lexord_append_rightI) lemma strict_prefix_lexord_left: assumes "trans R" "(xs, ys) \ lexord R" "strict_prefix xs' xs" shows "(xs', ys) \ lexord R" by (metis assms lexord_trans strict_prefix_lexord_rel) lemma prefix_lexord_right: assumes "trans R" "(xs, ys) \ lexord R" "strict_prefix ys ys'" shows "(xs, ys') \ lexord R" by (metis assms lexord_trans strict_prefix_lexord_rel) lemma lexord_eq_length: assumes "(xs, ys) \ lexord R" "length xs = length ys" shows "\ i. (xs!i, ys!i) \ R \ i < length xs \ (\ j R") case True with ys show ?thesis by (rule_tac x="0" in exI, simp) next case False with ys hyps(2) have xy: "x = y" "(xs, ys') \ lexord R" by auto with hyps(1,3) ys obtain i where "(xs!i, ys'!i) \ R" "i < length xs" "(\ j i" "length ys > i" "(xs!i, ys!i) \ R" "\ j lexord R" using assms proof (induct i arbitrary: xs ys) case 0 thus ?case by (auto, metis lexord_cons_cons list.exhaust nth_Cons_0) next case (Suc i) note hyps = this then obtain x' y' xs' ys' where "xs = x' # xs'" "ys = y' # ys'" by (metis Suc_length_conv Suc_lessE) moreover with hyps(5) have "\j Distributed Concatenation \ definition uncurry :: "('a \ 'b \ 'c) \ ('a \ 'b \ 'c)" where [simp]: "uncurry f = (\(x, y). f x y)" definition dist_concat :: "'a list set \ 'a list set \ 'a list set" (infixr "\<^sup>\" 100) where "dist_concat ls1 ls2 = (uncurry (@) ` (ls1 \ ls2))" lemma dist_concat_left_empty [simp]: "{} \<^sup>\ ys = {}" by (simp add: dist_concat_def) lemma dist_concat_right_empty [simp]: "xs \<^sup>\ {} = {}" by (simp add: dist_concat_def) lemma dist_concat_insert [simp]: "insert l ls1 \<^sup>\ ls2 = ((@) l ` ( ls2)) \ (ls1 \<^sup>\ ls2)" by (auto simp add: dist_concat_def) subsection \ List Domain and Range \ abbreviation seq_dom :: "'a list \ nat set" ("dom\<^sub>l") where "seq_dom xs \ {0.. 'a set" ("ran\<^sub>l") where "seq_ran xs \ set xs" subsection \ Extracting List Elements \ definition seq_extract :: "nat set \ 'a list \ 'a list" (infix "\\<^sub>l" 80) where "seq_extract A xs = nths xs A" lemma seq_extract_Nil [simp]: "A \\<^sub>l [] = []" by (simp add: seq_extract_def) lemma seq_extract_Cons: "A \\<^sub>l (x # xs) = (if 0 \ A then [x] else []) @ {j. Suc j \ A} \\<^sub>l xs" by (simp add: seq_extract_def nths_Cons) lemma seq_extract_empty [simp]: "{} \\<^sub>l xs = []" by (simp add: seq_extract_def) lemma seq_extract_ident [simp]: "{0..\<^sub>l xs = xs" unfolding list_eq_iff_nth_eq by (auto simp add: seq_extract_def length_nths atLeast0LessThan) lemma seq_extract_split: assumes "i \ length xs" shows "{0..\<^sub>l xs @ {i..\<^sub>l xs = xs" using assms proof (induct xs arbitrary: i) case Nil thus ?case by (simp add: seq_extract_def) next case (Cons x xs) note hyp = this have "{j. Suc j < i} = {0.. Suc j \ j < length xs} = {i - 1..\<^sub>l (xs @ ys) = (A \\<^sub>l xs) @ ({j. j + length xs \ A} \\<^sub>l ys)" by (simp add: seq_extract_def nths_append) lemma seq_extract_range: "A \\<^sub>l xs = (A \ dom\<^sub>l(xs)) \\<^sub>l xs" apply (auto simp add: seq_extract_def nths_def) apply (metis (no_types, lifting) atLeastLessThan_iff filter_cong in_set_zip nth_mem set_upt) done lemma seq_extract_out_of_range: "A \ dom\<^sub>l(xs) = {} \ A \\<^sub>l xs = []" by (metis seq_extract_def seq_extract_range nths_empty) lemma seq_extract_length [simp]: "length (A \\<^sub>l xs) = card (A \ dom\<^sub>l(xs))" proof - have "{i. i < length(xs) \ i \ A} = (A \ {0..\<^sub>l (x # xs) = (if (m = 0) then x # ({0..\<^sub>l xs) else {m-1..\<^sub>l xs)" proof - have "{j. Suc j < n} = {0.. Suc j \ Suc j < n} = {m - Suc 0..\<^sub>l xs = [xs ! i]" using assms apply (induct xs arbitrary: i) apply (auto simp add: seq_extract_Cons) apply (rename_tac xs i) apply (subgoal_tac "{j. Suc j = i} = {i - 1}") apply (auto) done lemma seq_extract_as_map: assumes "m < n" "n \ length xs" shows "{m..\<^sub>l xs = map (nth xs) [m.. (\ i\length(xs). ys = {0..\<^sub>l xs \ zs = {i..\<^sub>l xs)" proof assume xs: "xs = ys @ zs" moreover have "ys = {0..\<^sub>l (ys @ zs)" by (simp add: seq_extract_append) moreover have "zs = {length ys..\<^sub>l (ys @ zs)" proof - have "{length ys.. {0.. i\length(xs). ys = {0..\<^sub>l xs \ zs = {i..\<^sub>l xs)" by (rule_tac x="length ys" in exI, auto) next assume "\i\length xs. ys = {0..\<^sub>l xs \ zs = {i..\<^sub>l xs" thus "xs = ys @ zs" by (auto simp add: seq_extract_split) qed subsection \ Filtering a list according to a set \ definition seq_filter :: "'a list \ 'a set \ 'a list" (infix "\\<^sub>l" 80) where "seq_filter xs A = filter (\ x. x \ A) xs" lemma seq_filter_Cons_in [simp]: "x \ cs \ (x # xs) \\<^sub>l cs = x # (xs \\<^sub>l cs)" by (simp add: seq_filter_def) lemma seq_filter_Cons_out [simp]: "x \ cs \ (x # xs) \\<^sub>l cs = (xs \\<^sub>l cs)" by (simp add: seq_filter_def) lemma seq_filter_Nil [simp]: "[] \\<^sub>l A = []" by (simp add: seq_filter_def) lemma seq_filter_empty [simp]: "xs \\<^sub>l {} = []" by (simp add: seq_filter_def) lemma seq_filter_append: "(xs @ ys) \\<^sub>l A = (xs \\<^sub>l A) @ (ys \\<^sub>l A)" by (simp add: seq_filter_def) lemma seq_filter_UNIV [simp]: "xs \\<^sub>l UNIV = xs" by (simp add: seq_filter_def) lemma seq_filter_twice [simp]: "(xs \\<^sub>l A) \\<^sub>l B = xs \\<^sub>l (A \ B)" by (simp add: seq_filter_def) subsection \ Minus on lists \ instantiation list :: (type) minus begin text \ We define list minus so that if the second list is not a prefix of the first, then an arbitrary list longer than the combined length is produced. Thus we can always determined from the output whether the minus is defined or not. \ definition "xs - ys = (if (prefix ys xs) then drop (length ys) xs else [])" instance .. end lemma minus_cancel [simp]: "xs - xs = []" by (simp add: minus_list_def) lemma append_minus [simp]: "(xs @ ys) - xs = ys" by (simp add: minus_list_def) lemma minus_right_nil [simp]: "xs - [] = xs" by (simp add: minus_list_def) lemma list_concat_minus_list_concat: "(s @ t) - (s @ z) = t - z" by (simp add: minus_list_def) lemma length_minus_list: "y \ x \ length(x - y) = length(x) - length(y)" by (simp add: less_eq_list_def minus_list_def) lemma map_list_minus: "xs \ ys \ map f (ys - xs) = map f ys - map f xs" by (simp add: drop_map less_eq_list_def map_mono_prefix minus_list_def) lemma list_minus_first_tl [simp]: "[x] \ xs \ (xs - [x]) = tl xs" by (metis Prefix_Order.prefixE append.left_neutral append_minus list.sel(3) not_Cons_self2 tl_append2) text \ Extra lemmas about @{term prefix} and @{term strict_prefix} \ lemma prefix_concat_minus: assumes "prefix xs ys" shows "xs @ (ys - xs) = ys" using assms by (metis minus_list_def prefix_drop) lemma prefix_minus_concat: assumes "prefix s t" shows "(t - s) @ z = (t @ z) - s" using assms by (simp add: Sublist.prefix_length_le minus_list_def) lemma strict_prefix_minus_not_empty: assumes "strict_prefix xs ys" shows "ys - xs \ []" using assms by (metis append_Nil2 prefix_concat_minus strict_prefix_def) lemma strict_prefix_diff_minus: assumes "prefix xs ys" and "xs \ ys" shows "(ys - xs) \ []" using assms by (simp add: strict_prefix_minus_not_empty) lemma length_tl_list_minus_butlast_gt_zero: assumes "length s < length t" and "strict_prefix (butlast s) t" and "length s > 0" shows "length (tl (t - (butlast s))) > 0" using assms by (metis Nitpick.size_list_simp(2) butlast_snoc hd_Cons_tl length_butlast length_greater_0_conv length_tl less_trans nat_neq_iff strict_prefix_minus_not_empty prefix_order.dual_order.strict_implies_order prefix_concat_minus) lemma list_minus_butlast_eq_butlast_list: assumes "length t = length s" and "strict_prefix (butlast s) t" shows "t - (butlast s) = [last t]" using assms by (metis append_butlast_last_id append_eq_append_conv butlast.simps(1) length_butlast less_numeral_extra(3) list.size(3) prefix_order.dual_order.strict_implies_order prefix_concat_minus prefix_length_less) lemma butlast_strict_prefix_length_lt_imp_last_tl_minus_butlast_eq_last: assumes "length s > 0" "strict_prefix (butlast s) t" "length s < length t" shows "last (tl (t - (butlast s))) = (last t)" using assms by (metis last_append last_tl length_tl_list_minus_butlast_gt_zero less_numeral_extra(3) list.size(3) append_minus strict_prefix_eq_exists) lemma tl_list_minus_butlast_not_empty: assumes "strict_prefix (butlast s) t" and "length s > 0" and "length t > length s" shows "tl (t - (butlast s)) \ []" using assms length_tl_list_minus_butlast_gt_zero by fastforce lemma tl_list_minus_butlast_empty: assumes "strict_prefix (butlast s) t" and "length s > 0" and "length t = length s" shows "tl (t - (butlast s)) = []" using assms by (simp add: list_minus_butlast_eq_butlast_list) lemma concat_minus_list_concat_butlast_eq_list_minus_butlast: assumes "prefix (butlast u) s" shows "(t @ s) - (t @ (butlast u)) = s - (butlast u)" using assms by (metis append_assoc prefix_concat_minus append_minus) lemma tl_list_minus_butlast_eq_empty: assumes "strict_prefix (butlast s) t" and "length s = length t" shows "tl (t - (butlast s)) = []" using assms by (metis list.sel(3) list_minus_butlast_eq_butlast_list) (* this can be shown using length_tl, but care is needed when list is empty? *) lemma prefix_length_tl_minus: assumes "strict_prefix s t" shows "length (tl (t-s)) = (length (t-s)) - 1" by (auto) lemma length_list_minus: assumes "strict_prefix s t" shows "length(t - s) = length(t) - length(s)" using assms by (simp add: minus_list_def prefix_order.dual_order.strict_implies_order) subsection \ Laws on @{term take}, @{term drop}, and @{term nths} \ lemma take_prefix: "m \ n \ take m xs \ take n xs" by (metis Prefix_Order.prefixI append_take_drop_id min_absorb2 take_append take_take) lemma nths_atLeastAtMost_0_take: "nths xs {0..m} = take (Suc m) xs" by (metis atLeast0AtMost lessThan_Suc_atMost nths_upt_eq_take) lemma nths_atLeastLessThan_0_take: "nths xs {0.. n \ nths xs {0..m} \ nths xs {0..n}" by (simp add: nths_atLeastAtMost_0_take take_prefix) lemma sorted_nths_atLeastAtMost_0: "\ m \ n; sorted (nths xs {0..n}) \ \ sorted (nths xs {0..m})" using nths_atLeastAtMost_prefix sorted_prefix by blast lemma sorted_nths_atLeastLessThan_0: "\ m \ n; sorted (nths xs {0.. \ sorted (nths xs {0.. list_augment xs k x = list_update xs k x" by (metis list_augment_def list_augment_idem list_update_overwrite) lemma nths_list_update_out: "k \ A \ nths (list_update xs k x) A = nths xs A" apply (induct xs arbitrary: k x A) apply (auto) apply (rename_tac a xs k x A) apply (case_tac k) apply (auto simp add: nths_Cons) done lemma nths_list_augment_out: "\ k < length xs; k \ A \ \ nths (list_augment xs k x) A = nths xs A" by (simp add: list_augment_as_update nths_list_update_out) end \ No newline at end of file