diff --git a/thys/CakeML_Codegen/Rewriting/Rewriting_Nterm.thy b/thys/CakeML_Codegen/Rewriting/Rewriting_Nterm.thy --- a/thys/CakeML_Codegen/Rewriting/Rewriting_Nterm.thy +++ b/thys/CakeML_Codegen/Rewriting/Rewriting_Nterm.thy @@ -1,774 +1,773 @@ section \Higher-order term rewriting using explicit bound variable names\ theory Rewriting_Nterm imports Rewriting_Term Higher_Order_Terms.Term_to_Nterm "../Terms/Strong_Term" begin subsection \Definitions\ type_synonym nrule = "term \ nterm" abbreviation nrule :: "nrule \ bool" where "nrule \ basic_rule" fun (in constants) not_shadowing :: "nrule \ bool" where "not_shadowing (lhs, rhs) \ \ shadows_consts lhs \ \ shadows_consts rhs" locale nrules = constants C_info "heads_of rs" for C_info and rs :: "nrule fset" + assumes all_rules: "fBall rs nrule" assumes arity: "arity_compatibles rs" assumes fmap: "is_fmap rs" assumes patterns: "pattern_compatibles rs" assumes nonempty: "rs \ {||}" assumes not_shadows: "fBall rs not_shadowing" assumes welldefined_rs: "fBall rs (\(_, rhs). welldefined rhs)" subsection \Matching and rewriting\ inductive nrewrite :: "nrule fset \ nterm \ nterm \ bool" ("_/ \\<^sub>n/ _ \/ _" [50,0,50] 50) for rs where step: "r |\| rs \ r \ t \ u \ rs \\<^sub>n t \ u" | beta: "rs \\<^sub>n ((\\<^sub>n x. t) $\<^sub>n t') \ subst t (fmap_of_list [(x, t')])" | "fun": "rs \\<^sub>n t \ t' \ rs \\<^sub>n t $\<^sub>n u \ t' $\<^sub>n u" | arg: "rs \\<^sub>n u \ u' \ rs \\<^sub>n t $\<^sub>n u \ t $\<^sub>n u'" global_interpretation nrewrite: rewriting "nrewrite rs" for rs by standard (auto intro: nrewrite.intros simp: app_nterm_def)+ abbreviation nrewrite_rt :: "nrule fset \ nterm \ nterm \ bool" ("_/ \\<^sub>n/ _ \*/ _" [50,0,50] 50) where "nrewrite_rt rs \ (nrewrite rs)\<^sup>*\<^sup>*" lemma (in nrules) nrewrite_closed: assumes "rs \\<^sub>n t \ t'" "closed t" shows "closed t'" using assms proof induction case (step r t u) obtain lhs rhs where "r = (lhs, rhs)" by force with step have "nrule (lhs, rhs)" using all_rules by blast hence "frees rhs |\| frees lhs" by simp have "(lhs, rhs) \ t \ u" using step unfolding \r = _\ by simp show ?case apply (rule rewrite_step_closed) apply fact+ done next case beta show ?case apply simp apply (subst closed_except_def) apply (subst subst_frees) using beta unfolding closed_except_def by auto qed (auto simp: closed_except_def) corollary (in nrules) nrewrite_rt_closed: assumes "rs \\<^sub>n t \* t'" "closed t" shows "closed t'" using assms by induction (auto intro: nrewrite_closed) subsection \Translation from @{typ term} to @{typ nterm}\ context begin private lemma term_to_nterm_all_vars0: assumes "wellformed' (length \) t" shows "\T. all_frees (fst (run_state (term_to_nterm \ t) x)) |\| fset_of_list \ |\| frees t |\| T \ fBall T (\y. y > x)" using assms proof (induction \ t arbitrary: x rule: term_to_nterm_induct) case (bound \ i) hence "\ ! i |\| fset_of_list \" by (simp add: fset_of_list_elem) with bound show ?case by (auto simp: State_Monad.return_def) next case (abs \ t) obtain T where "all_frees (fst (run_state (term_to_nterm (next x # \) t) (next x))) |\| fset_of_list (next x # \) |\| frees t |\| T" and "fBall T ((<) (next x))" apply atomize_elim apply (rule abs(1)) using abs by auto show ?case apply (simp add: split_beta create_alt_def) apply (rule exI[where x = "finsert (next x) T"]) apply (intro conjI) subgoal by auto subgoal using \all_frees (fst (run_state _ (next x))) |\| _\ by simp subgoal apply simp apply (rule conjI) apply (rule next_ge) using \fBall T ((<) (next x))\ by (metis fBallE fBallI fresh_class.next_ge order.strict_trans) done next case (app \ t\<^sub>1 t\<^sub>2 x\<^sub>1) obtain t\<^sub>1' x\<^sub>2 where "run_state (term_to_nterm \ t\<^sub>1) x\<^sub>1 = (t\<^sub>1', x\<^sub>2)" by fastforce moreover obtain T\<^sub>1 where "all_frees (fst (run_state (term_to_nterm \ t\<^sub>1) x\<^sub>1)) |\| fset_of_list \ |\| frees t\<^sub>1 |\| T\<^sub>1" and "fBall T\<^sub>1 ((<) x\<^sub>1)" apply atomize_elim apply (rule app(1)) using app by auto ultimately have "all_frees t\<^sub>1' |\| fset_of_list \ |\| frees t\<^sub>1 |\| T\<^sub>1" by simp obtain T\<^sub>2 where "all_frees (fst (run_state (term_to_nterm \ t\<^sub>2) x\<^sub>2)) |\| fset_of_list \ |\| frees t\<^sub>2 |\| T\<^sub>2" and "fBall T\<^sub>2 ((<) x\<^sub>2)" apply atomize_elim apply (rule app(2)) using app by auto moreover obtain t\<^sub>2' x' where "run_state (term_to_nterm \ t\<^sub>2) x\<^sub>2 = (t\<^sub>2', x')" by fastforce ultimately have "all_frees t\<^sub>2' |\| fset_of_list \ |\| frees t\<^sub>2 |\| T\<^sub>2" by simp have "x\<^sub>1 \ x\<^sub>2" apply (rule state_io_relD[OF term_to_nterm_mono]) apply fact done show ?case apply simp unfolding \run_state (term_to_nterm \ t\<^sub>1) x\<^sub>1 = _\ apply simp unfolding \run_state (term_to_nterm \ t\<^sub>2) x\<^sub>2 = _\ apply simp apply (rule exI[where x = "T\<^sub>1 |\| T\<^sub>2"]) apply (intro conjI) subgoal using \all_frees t\<^sub>1' |\| _\ by auto subgoal using \all_frees t\<^sub>2' |\| _\ by auto subgoal apply auto using \fBall T\<^sub>1 ((<) x\<^sub>1)\ apply auto[] using \fBall T\<^sub>2 ((<) x\<^sub>2)\ \x\<^sub>1 \ x\<^sub>2\ by (meson fBallE less_le_not_le order_trans) done qed auto lemma term_to_nterm_all_vars: assumes "wellformed t" "fdisjnt (frees t) S" shows "fdisjnt (all_frees (fresh_frun (term_to_nterm [] t) (T |\| S))) S" proof - let ?\ = "[]" let ?x = "fresh_fNext (T |\| S)" from assms have "wellformed' (length ?\) t" by simp then obtain F where "all_frees (fst (run_state (term_to_nterm ?\ t) ?x)) |\| fset_of_list ?\ |\| frees t |\| F" and "fBall F (\y. y > ?x)" by (metis term_to_nterm_all_vars0) have "fdisjnt F (T |\| S)" if "S \ {||}" apply (rule fdisjnt_ge_max) apply (rule fBall_pred_weaken[OF _ \fBall F (\y. y > ?x)\]) apply (rule less_trans) apply (rule fNext_ge_max) using that by auto show ?thesis apply (rule fdisjnt_subset_left) apply (subst fresh_frun_def) apply (subst fresh_fNext_def[symmetric]) apply fact apply simp apply (rule fdisjnt_union_left) apply fact using \_ \ fdisjnt F (T |\| S)\ by (auto simp: fdisjnt_alt_def) qed end fun translate_rule :: "name fset \ rule \ nrule" where "translate_rule S (lhs, rhs) = (lhs, fresh_frun (term_to_nterm [] rhs) (frees lhs |\| S))" lemma translate_rule_alt_def: "translate_rule S = (\(lhs, rhs). (lhs, fresh_frun (term_to_nterm [] rhs) (frees lhs |\| S)))" by auto definition compile' where "compile' C_info rs = translate_rule (pre_constants.all_consts C_info (heads_of rs)) |`| rs" context rules begin definition compile :: "nrule fset" where "compile = translate_rule all_consts |`| rs" lemma compile'_compile_eq[simp]: "compile' C_info rs = compile" unfolding compile'_def compile_def .. lemma compile_heads: "heads_of compile = heads_of rs" unfolding compile_def translate_rule_alt_def head_def[abs_def] by force lemma compile_rules: "nrules C_info compile" proof have "fBall compile (\(lhs, rhs). nrule (lhs, rhs))" proof safe fix lhs rhs assume "(lhs, rhs) |\| compile" then obtain rhs' where "(lhs, rhs') |\| rs" and rhs: "rhs = fresh_frun (term_to_nterm [] rhs') (frees lhs |\| all_consts)" unfolding compile_def by force then have rule: "rule (lhs, rhs')" using all_rules by blast show "nrule (lhs, rhs)" proof from rule show "linear lhs" "is_const (fst (strip_comb lhs))" "\ is_const lhs" by auto have "frees rhs |\| frees rhs'" unfolding rhs using rule by (metis rule.simps term_to_nterm_vars) also have "frees rhs' |\| frees lhs" using rule by auto finally show "frees rhs |\| frees lhs" . qed qed thus "fBall compile nrule" by fast next show "arity_compatibles compile" proof safe fix lhs\<^sub>1 rhs\<^sub>1 lhs\<^sub>2 rhs\<^sub>2 assume "(lhs\<^sub>1, rhs\<^sub>1) |\| compile" "(lhs\<^sub>2, rhs\<^sub>2) |\| compile" then obtain rhs\<^sub>1' rhs\<^sub>2' where "(lhs\<^sub>1, rhs\<^sub>1') |\| rs" "(lhs\<^sub>2, rhs\<^sub>2') |\| rs" unfolding compile_def by force thus "arity_compatible lhs\<^sub>1 lhs\<^sub>2" using arity by (blast dest: fpairwiseD) qed next have "is_fmap rs" using fmap by simp thus "is_fmap compile" unfolding compile_def translate_rule_alt_def by (rule is_fmap_image) next have "pattern_compatibles rs" using patterns by simp thus "pattern_compatibles compile" unfolding compile_def translate_rule_alt_def by (auto dest: fpairwiseD) next show "fdisjnt (heads_of compile) C" using disjnt by (simp add: compile_heads) next have "fBall compile not_shadowing" proof safe fix lhs rhs assume "(lhs, rhs) |\| compile" then obtain rhs' where "rhs = fresh_frun (term_to_nterm [] rhs') (frees lhs |\| all_consts)" and "(lhs, rhs') |\| rs" unfolding compile_def translate_rule_alt_def by auto hence "rule (lhs, rhs')" "\ shadows_consts lhs" using all_rules not_shadows by blast+ moreover hence "wellformed rhs'" "frees rhs' |\| frees lhs" "fdisjnt all_consts (frees lhs)" unfolding shadows_consts_def by simp+ moreover have "\ shadows_consts rhs" apply (subst shadows_consts_def) apply simp unfolding \rhs = _\ apply (rule fdisjnt_swap) apply (rule term_to_nterm_all_vars) apply fact apply (rule fdisjnt_subset_left) apply fact apply (rule fdisjnt_swap) apply fact done ultimately show "not_shadowing (lhs, rhs)" unfolding compile_heads by simp qed thus "fBall compile (constants.not_shadowing C_info (heads_of compile))" unfolding compile_heads . have "fBall compile (\(_, rhs). welldefined rhs)" unfolding compile_heads unfolding compile_def ball_simps apply (rule fBall_pred_weaken[OF _ welldefined_rs]) subgoal for x apply (cases x) apply simp apply (subst fresh_frun_def) apply (subst term_to_nterm_consts[THEN pred_state_run_state]) by auto done thus "fBall compile (\(_, rhs). consts rhs |\| pre_constants.all_consts C_info (heads_of compile))" unfolding compile_heads . next show "compile \ {||}" using nonempty unfolding compile_def by auto next show "distinct all_constructors" by (fact distinct_ctr) qed sublocale rules_as_nrules: nrules C_info compile by (fact compile_rules) end subsection \Correctness of translation\ theorem (in rules) compile_correct: assumes "compile \\<^sub>n u \ u'" "closed u" shows "rs \ nterm_to_term' u \ nterm_to_term' u'" using assms proof (induction u u') case (step r u u') moreover obtain pat rhs' where "r = (pat, rhs')" by force ultimately obtain nenv where "match pat u = Some nenv" "u' = subst rhs' nenv" by auto then obtain env where "nrelated.P_env [] env nenv" "match pat (nterm_to_term [] u) = Some env" by (metis nrelated.match_rel option.exhaust option.rel_distinct(1) option.rel_inject(2)) have "closed_env nenv" using step \match pat u = Some nenv\ by (intro closed.match) from step obtain rhs where "rhs' = fresh_frun (term_to_nterm [] rhs) (frees pat |\| all_consts)" "(pat, rhs) |\| rs" unfolding \r = _\ compile_def by auto with assms have "rule (pat, rhs)" using all_rules by blast hence "rhs = nterm_to_term [] rhs'" unfolding \rhs' = _\ by (simp add: term_to_nterm_nterm_to_term fresh_frun_def) have "compile \\<^sub>n u \ u'" using step by (auto intro: nrewrite.step) hence "closed u'" by (rule rules_as_nrules.nrewrite_closed) fact show ?case proof (rule rewrite.step) show "(pat, rhs) \ nterm_to_term [] u \ nterm_to_term [] u'" apply (subst nterm_to_term_eq_closed) apply fact apply simp apply (rule exI[where x = env]) apply (rule conjI) apply fact unfolding \rhs = _\ apply (subst nrelated_subst) apply fact apply fact unfolding fdisjnt_alt_def apply simp unfolding \u' = subst rhs' nenv\ by simp qed fact next case beta show ?case apply simp apply (subst subst_single_eq[symmetric, simplified]) apply (subst nterm_to_term_subst_replace_bound[where n = 0]) subgoal using beta by (simp add: closed_except_def) subgoal by simp subgoal by simp subgoal by simp (rule rewrite.beta) done qed (auto intro: rewrite.intros simp: closed_except_def) subsection \Completeness of translation\ context rules begin context notes [simp] = closed_except_def fdisjnt_alt_def begin private lemma compile_complete0: assumes "rs \ t \ t'" "closed t" "wellformed t" obtains u' where "compile \\<^sub>n fst (run_state (term_to_nterm [] t) s) \ u'" "u' \\<^sub>\ fst (run_state (term_to_nterm [] t') s')" apply atomize_elim using assms proof (induction t t' arbitrary: s s') case (step r t t') let ?t\<^sub>n = "fst (run_state (term_to_nterm [] t) s)" let ?t\<^sub>n' = "fst (run_state (term_to_nterm [] t') s')" from step have "closed t" "closed ?t\<^sub>n" using term_to_nterm_vars0[where \ = "[]"] by force+ from step have "nterm_to_term' ?t\<^sub>n = t" - find_theorems nterm_to_term fdisjnt by (auto intro!: term_to_nterm_nterm_to_term0) obtain pat rhs' where "r = (pat, rhs')" by fastforce with step obtain env' where "match pat t = Some env'" "t' = subst rhs' env'" by fastforce with \_ = t\ have "rel_option (nrelated.P_env []) (match pat t) (match pat (?t\<^sub>n))" by (metis nrelated.match_rel) with step \_ = Some env'\ obtain env where "nrelated.P_env [] env' env" "match pat ?t\<^sub>n = Some env" by (metis (no_types, lifting) option_rel_Some1) with \closed ?t\<^sub>n\ have "closed_env env" by (blast intro: closed.match) from step obtain rhs where "rhs = fresh_frun (term_to_nterm [] rhs') (frees pat |\| all_consts)" "(pat, rhs) |\| compile" unfolding \r = _\ compile_def by force with step have "rule (pat, rhs')" unfolding \r = _\ using all_rules by fast hence "nterm_to_term' rhs = rhs'" unfolding \rhs = _\ by (simp add: fresh_frun_def term_to_nterm_nterm_to_term) obtain u' where "subst rhs env = u'" by simp have "t' = nterm_to_term' u'" unfolding \t' = _\ unfolding \_ = rhs'\[symmetric] apply (subst nrelated_subst) apply fact+ using \_ = u'\ by simp+ have "compile \\<^sub>n ?t\<^sub>n \ u'" apply (rule nrewrite.step) apply fact apply simp apply (intro conjI exI) apply fact+ done with \closed ?t\<^sub>n\ have "closed u'" by (blast intro:rules_as_nrules.nrewrite_closed) with \t' = nterm_to_term' _\ have "u' \\<^sub>\ ?t\<^sub>n'" by (force intro: nterm_to_term_term_to_nterm[where \ = "[]" and \' = "[]",simplified]) show ?case apply (intro conjI exI) apply (rule nrewrite.step) apply fact apply simp apply (intro conjI exI) apply fact+ done next case (beta t t') let ?name = "next s" let ?t\<^sub>n = "fst (run_state (term_to_nterm [?name] t) (?name))" let ?t\<^sub>n' = "fst (run_state (term_to_nterm [] t') (snd (run_state (term_to_nterm [?name] t) (?name))))" from beta have "closed t" "closed (t [t']\<^sub>\)" "closed (\ t $ t')" "closed t'" using replace_bound_frees by fastforce+ moreover from beta have "wellformed' (Suc 0) t" "wellformed t'" by simp+ ultimately have "t = nterm_to_term [?name] ?t\<^sub>n" and "t' = nterm_to_term' ?t\<^sub>n'" and *:"frees ?t\<^sub>n = {|?name|} \ frees ?t\<^sub>n = fempty" and "closed ?t\<^sub>n'" using term_to_nterm_vars0[where \ = "[?name]"] using term_to_nterm_vars0[where \ = "[]"] by (force simp: term_to_nterm_nterm_to_term0)+ hence **:"t [t']\<^sub>\ = nterm_to_term' (subst_single ?t\<^sub>n ?name ?t\<^sub>n')" by (auto simp: nterm_to_term_subst_replace_bound[where n = 0]) from \closed ?t\<^sub>n'\ have "closed_env (fmap_of_list [(?name, ?t\<^sub>n')])" by auto show ?case apply (rule exI) apply (auto simp: split_beta create_alt_def) apply (rule nrewrite.beta) apply (subst subst_single_eq[symmetric]) apply (subst **) apply (rule nterm_to_term_term_to_nterm[where \ = "[]" and \' = "[]", simplified]) apply (subst subst_single_eq) apply (subst subst_frees[OF \closed_env _\]) using * by force next case ("fun" t t' u) hence "closed t" "closed u" "closed (t $ u)" and wellform:"wellformed t" "wellformed u" by fastforce+ from "fun" obtain u' where "compile \\<^sub>n fst (run_state (term_to_nterm [] t) s) \ u'" "u' \\<^sub>\ fst (run_state (term_to_nterm [] t') s')" by force show ?case apply (rule exI) apply (auto simp: split_beta create_alt_def) apply (rule nrewrite.fun) apply fact apply rule apply fact apply (subst term_to_nterm_alpha_equiv[of "[]" "[]", simplified]) using \closed u\ \wellformed u\ by auto next case (arg u u' t) hence "closed t" "closed u" "closed (t $ u)" and wellform:"wellformed t" "wellformed u" by fastforce+ from arg obtain t' where "compile \\<^sub>n fst (run_state (term_to_nterm [] u) (snd (run_state (term_to_nterm [] t) s))) \ t'" "t' \\<^sub>\ fst (run_state (term_to_nterm [] u') (snd (run_state (term_to_nterm [] t) s')))" by force show ?case apply (rule exI) apply (auto simp: split_beta create_alt_def) apply rule apply fact apply rule apply (subst term_to_nterm_alpha_equiv[of "[]" "[]", simplified]) using \closed t\ \wellformed t\ apply force+ by fact qed lemma compile_complete: assumes "rs \ t \ t'" "closed t" "wellformed t" obtains u' where "compile \\<^sub>n term_to_nterm' t \ u'" "u' \\<^sub>\ term_to_nterm' t'" unfolding term_to_nterm'_def using assms by (metis compile_complete0) end end subsection \Splitting into constants\ type_synonym crules = "(term list \ nterm) fset" type_synonym crule_set = "(name \ crules) fset" abbreviation arity_compatibles :: "(term list \ 'a) fset \ bool" where "arity_compatibles \ fpairwise (\(pats\<^sub>1, _) (pats\<^sub>2, _). length pats\<^sub>1 = length pats\<^sub>2)" lemma arity_compatible_length: assumes "arity_compatibles rs" "(pats, rhs) |\| rs" shows "length pats = arity rs" proof - have "fBall rs (\(pats\<^sub>1, _). fBall rs (\(pats\<^sub>2, _). length pats\<^sub>1 = length pats\<^sub>2))" using assms unfolding fpairwise_alt_def by blast hence "fBall rs (\x. fBall rs (\y. (length \ fst) x = (length \ fst) y))" by force hence "(length \ fst) (pats, rhs) = arity rs" using assms(2) unfolding arity_def fthe_elem'_eq by (rule singleton_fset_holds) thus ?thesis by simp qed locale pre_crules = constants C_info "fst |`| rs" for C_info and rs :: "crule_set" locale crules = pre_crules + assumes fmap: "is_fmap rs" assumes nonempty: "rs \ {||}" assumes inner: "fBall rs (\(_, crs). arity_compatibles crs \ is_fmap crs \ patterns_compatibles crs \ crs \ {||} \ fBall crs (\(pats, rhs). linears pats \ pats \ [] \ fdisjnt (freess pats) all_consts \ \ shadows_consts rhs \ frees rhs |\| freess pats \ welldefined rhs))" lemma (in pre_crules) crulesI: assumes "\name crs. (name, crs) |\| rs \ arity_compatibles crs" assumes "\name crs. (name, crs) |\| rs \ is_fmap crs" assumes "\name crs. (name, crs) |\| rs \ patterns_compatibles crs" assumes "\name crs. (name, crs) |\| rs \ crs \ {||}" assumes "\name crs pats rhs. (name, crs) |\| rs \ (pats, rhs) |\| crs \ linears pats" assumes "\name crs pats rhs. (name, crs) |\| rs \ (pats, rhs) |\| crs \ pats \ []" assumes "\name crs pats rhs. (name, crs) |\| rs \ (pats, rhs) |\| crs \ fdisjnt (freess pats) all_consts" assumes "\name crs pats rhs. (name, crs) |\| rs \ (pats, rhs) |\| crs \ \ shadows_consts rhs" assumes "\name crs pats rhs. (name, crs) |\| rs \ (pats, rhs) |\| crs \ frees rhs |\| freess pats" assumes "\name crs pats rhs. (name, crs) |\| rs \ (pats, rhs) |\| crs \ welldefined rhs" assumes "is_fmap rs" "rs \ {||}" shows "crules C_info rs" using assms unfolding crules_axioms_def crules_def by (auto simp: prod_fBallI intro: pre_crules_axioms) lemmas crulesI[intro!] = pre_crules.crulesI[unfolded pre_crules_def] definition "consts_of" :: "nrule fset \ crule_set" where "consts_of = fgroup_by split_rule" lemma consts_of_heads: "fst |`| consts_of rs = heads_of rs" unfolding consts_of_def by (simp add: split_rule_fst comp_def) lemma (in nrules) consts_rules: "crules C_info (consts_of rs)" proof have "is_fmap rs" using fmap by simp thus "is_fmap (consts_of rs)" unfolding consts_of_def by auto show "consts_of rs \ {||}" using nonempty unfolding consts_of_def by (meson fgroup_by_nonempty) show "constants C_info (fst |`| consts_of rs)" proof show "fdisjnt (fst |`| consts_of rs) C" using disjnt by (auto simp: consts_of_heads) next show "distinct all_constructors" by (fact distinct_ctr) qed fix name crs assume crs: "(name, crs) |\| consts_of rs" thus "crs \ {||}" unfolding consts_of_def by (meson femptyE fgroup_by_nonempty_inner) show "arity_compatibles crs" "patterns_compatibles crs" proof safe fix pats\<^sub>1 rhs\<^sub>1 pats\<^sub>2 rhs\<^sub>2 assume "(pats\<^sub>1, rhs\<^sub>1) |\| crs" "(pats\<^sub>2, rhs\<^sub>2) |\| crs" with crs obtain lhs\<^sub>1 lhs\<^sub>2 where rs: "(lhs\<^sub>1, rhs\<^sub>1) |\| rs" "(lhs\<^sub>2, rhs\<^sub>2) |\| rs" and split: "split_rule (lhs\<^sub>1, rhs\<^sub>1) = (name, (pats\<^sub>1, rhs\<^sub>1))" "split_rule (lhs\<^sub>2, rhs\<^sub>2) = (name, (pats\<^sub>2, rhs\<^sub>2))" unfolding consts_of_def by (force simp: split_beta) hence arity: "arity_compatible lhs\<^sub>1 lhs\<^sub>2" using arity by (force dest: fpairwiseD) from rs have const: "is_const (fst (strip_comb lhs\<^sub>1))" "is_const (fst (strip_comb lhs\<^sub>2))" using all_rules by force+ have "name = const_name (fst (strip_comb lhs\<^sub>1))" "name = const_name (fst (strip_comb lhs\<^sub>2))" using split by (auto simp: split_beta) with const have "fst (strip_comb lhs\<^sub>1) = Const name" "fst (strip_comb lhs\<^sub>2) = Const name" apply (fold const_term_def) subgoal by simp subgoal by fastforce done hence fst: "fst (strip_comb lhs\<^sub>1) = fst (strip_comb lhs\<^sub>2)" by simp with arity have "length (snd (strip_comb lhs\<^sub>1)) = length (snd (strip_comb lhs\<^sub>2))" unfolding arity_compatible_def by (simp add: split_beta) with split show "length pats\<^sub>1 = length pats\<^sub>2" by (auto simp: split_beta) have "pattern_compatible lhs\<^sub>1 lhs\<^sub>2" using rs patterns by (auto dest: fpairwiseD) moreover have "lhs\<^sub>1 = name $$ pats\<^sub>1" using split(1) const(1) by (auto simp: split_beta) moreover have "lhs\<^sub>2 = name $$ pats\<^sub>2" using split(2) const(2) by (auto simp: split_beta) ultimately have "pattern_compatible (name $$ pats\<^sub>1) (name $$ pats\<^sub>2)" by simp thus "patterns_compatible pats\<^sub>1 pats\<^sub>2" using \length pats\<^sub>1 = _\ by (auto dest: pattern_compatible_combD) qed show "is_fmap crs" proof fix pats rhs\<^sub>1 rhs\<^sub>2 assume "(pats, rhs\<^sub>1) |\| crs" "(pats, rhs\<^sub>2) |\| crs" with crs obtain lhs\<^sub>1 lhs\<^sub>2 where rs: "(lhs\<^sub>1, rhs\<^sub>1) |\| rs" "(lhs\<^sub>2, rhs\<^sub>2) |\| rs" and split: "split_rule (lhs\<^sub>1, rhs\<^sub>1) = (name, (pats, rhs\<^sub>1))" "split_rule (lhs\<^sub>2, rhs\<^sub>2) = (name, (pats, rhs\<^sub>2))" unfolding consts_of_def by (force simp: split_beta) have "lhs\<^sub>1 = lhs\<^sub>2" proof (rule ccontr) assume "lhs\<^sub>1 \ lhs\<^sub>2" then consider (fst) "fst (strip_comb lhs\<^sub>1) \ fst (strip_comb lhs\<^sub>2)" | (snd) "snd (strip_comb lhs\<^sub>1) \ snd (strip_comb lhs\<^sub>2)" by (metis list_strip_comb) thus False proof cases case fst moreover have "is_const (fst (strip_comb lhs\<^sub>1))" "is_const (fst (strip_comb lhs\<^sub>2))" using rs all_rules by force+ ultimately show ?thesis using split const_name_simps by (fastforce simp: split_beta) next case snd with split show ?thesis by (auto simp: split_beta) qed qed with rs show "rhs\<^sub>1 = rhs\<^sub>2" using \is_fmap rs\ by (auto dest: is_fmapD) qed fix pats rhs assume "(pats, rhs) |\| crs" then obtain lhs where "(lhs, rhs) |\| rs" "pats = snd (strip_comb lhs)" using crs unfolding consts_of_def by (force simp: split_beta) hence "nrule (lhs, rhs)" using all_rules by blast hence "linear lhs" "frees rhs |\| frees lhs" by auto thus "linears pats" unfolding \pats = _\ by (intro linears_strip_comb) have "\ is_const lhs" "is_const (fst (strip_comb lhs))" using \nrule _\ by auto thus "pats \ []" unfolding \pats = _\ using \linear lhs\ apply (cases lhs) apply (fold app_term_def) by (auto split: prod.splits) from \nrule (lhs, rhs)\ have "frees (fst (strip_comb lhs)) = {||}" by (cases "fst (strip_comb lhs)") (auto simp: is_const_def) hence "frees lhs = freess (snd (strip_comb lhs))" by (subst frees_strip_comb) auto thus "frees rhs |\| freess pats" unfolding \pats = _\ using \frees rhs |\| frees lhs\ by simp have "\ shadows_consts rhs" using \(lhs, rhs) |\| rs\ not_shadows by force thus "\ pre_constants.shadows_consts C_info (fst |`| consts_of rs) rhs" by (simp add: consts_of_heads) have "fdisjnt all_consts (frees lhs)" using \(lhs, rhs) |\| rs\ not_shadows by (force simp: shadows_consts_def) moreover have "freess pats |\| frees lhs" unfolding \pats = _\ \frees lhs = _\ by simp ultimately have "fdisjnt (freess pats) all_consts" by (metis fdisjnt_subset_right fdisjnt_swap) thus "fdisjnt (freess pats) (pre_constants.all_consts C_info (fst |`| consts_of rs))" by (simp add: consts_of_heads) show "pre_constants.welldefined C_info (fst |`| consts_of rs) rhs" using welldefined_rs \(lhs, rhs) |\| rs\ by (force simp: consts_of_heads) qed sublocale nrules \ nrules_as_crules?: crules C_info "consts_of rs" by (fact consts_rules) subsection \Computability\ export_code translate_rule consts_of arity nterm_to_term checking Scala end \ No newline at end of file diff --git a/thys/Gabow_SCC/Find_Path_Impl.thy b/thys/Gabow_SCC/Find_Path_Impl.thy --- a/thys/Gabow_SCC/Find_Path_Impl.thy +++ b/thys/Gabow_SCC/Find_Path_Impl.thy @@ -1,414 +1,412 @@ section \Implementation of Safety Property Model Checker \label{sec:find_path_impl}\ theory Find_Path_Impl imports Find_Path CAVA_Automata.Digraph_Impl begin section \Workset Algorithm\ text \A simple implementation is by a workset algorithm.\ definition "ws_update E u p V ws \ RETURN ( V \ E``{u}, ws ++ (\v. if (u,v)\E \ v\V then Some (u#p) else None))" definition "s_init U0 \ RETURN (None,U0,\u. if u\U0 then Some [] else None)" definition "wset_find_path E U0 P \ do { ASSERT (finite U0); s0 \ s_init U0; (res,_,_) \ WHILET (\(res,V,ws). res=None \ ws\Map.empty) (\(res,V,ws). do { ASSERT (ws\Map.empty); (u,p) \ SPEC (\(u,p). ws u = Some p); let ws=ws |` (-{u}); if P u then RETURN (Some (rev p,u),V,ws) else do { ASSERT (finite (E``{u})); ASSERT (dom ws \ V); (V,ws) \ ws_update E u p V ws; RETURN (None,V,ws) } }) s0; RETURN res }" lemma wset_find_path_correct: fixes E :: "('v\'v) set" shows "wset_find_path E U0 P \ find_path E U0 P" proof - define inv where "inv = (\(res,V,ws). case res of None \ dom ws\V \ finite (dom ws) \ \Derived\ \ V\E\<^sup>*``U0 \ E``(V-dom ws) \ V \ (\v\V-dom ws. \ P v) \ U0 \ V \ (\v p. ws v = Some p \ ((\v\set p. \P v) \ (\u0\U0. path E u0 (rev p) v))) | Some (p,v) \ (\u0\U0. path E u0 p v \ P v \ (\v\set p. \P v)))" define var where "var = inv_image (brk_rel (finite_psupset (E\<^sup>*``U0) <*lex*> measure (card o dom))) (\(res::('v list \ 'v) option,V::'v set,ws::'v\'v list). (res\None,V,ws))" (*have [simp, intro!]: "wf var" unfolding var_def by (auto intro: FIN)*) have [simp]: "\u p V. dom (\v. if (u, v) \ E \ v \ V then Some (u # p) else None) = E``{u} - V" by (auto split: if_split_asm) { fix V ws u p assume INV: "inv (None,V,ws)" assume WSU: "ws u = Some p" from INV WSU have [simp]: "V \ E\<^sup>*``U0" and [simp]: "u \ V" and UREACH: "\u0\U0. (u0,u)\E\<^sup>*" and [simp]: "finite (dom ws)" unfolding inv_def apply simp_all apply auto [] apply clarsimp apply blast done have "(V \ E `` {u}, V) \ finite_psupset (E\<^sup>* `` U0) \ V \ E `` {u} = V \ card (E `` {u} - V \ (dom ws - {u})) < card (dom ws)" proof (subst disj_commute, intro disjCI conjI) assume "(V \ E `` {u}, V) \ finite_psupset (E\<^sup>* `` U0)" thus "V \ E `` {u} = V" using UREACH by (auto simp: finite_psupset_def intro: rev_ImageI) hence [simp]: "E``{u} - V = {}" by force show "card (E `` {u} - V \ (dom ws - {u})) < card (dom ws)" using WSU by (auto intro: card_Diff1_less) qed } note wf_aux=this { fix V ws u p assume FIN: "finite (E\<^sup>*``U0)" assume "inv (None,V,ws)" "ws u = Some p" then obtain u0 where "u0\U0" "(u0,u)\E\<^sup>*" unfolding inv_def by clarsimp blast hence "E``{u} \ E\<^sup>*``U0" by (auto intro: rev_ImageI) hence "finite (E``{u})" using FIN(1) by (rule finite_subset) } note succs_finite=this { fix V ws u p assume FIN: "finite (E\<^sup>*``U0)" assume INV: "inv (None,V,ws)" assume WSU: "ws u = Some p" assume NVD: "\ P u" have "inv (None, V \ E `` {u}, ws |` (- {u}) ++ (\v. if (u, v) \ E \ v \ V then Some (u # p) else None))" unfolding inv_def apply (simp, intro conjI) using INV WSU apply (auto simp: inv_def) [] using INV WSU apply (auto simp: inv_def) [] using INV WSU apply (auto simp: succs_finite FIN) [] using INV apply (auto simp: inv_def) [] using INV apply (auto simp: inv_def) [] using INV WSU apply (auto simp: inv_def intro: rtrancl_image_advance ) [] using INV WSU apply (auto simp: inv_def) [] using INV NVD apply (auto simp: inv_def) [] using INV NVD apply (auto simp: inv_def) [] using INV WSU NVD apply (fastforce simp: inv_def restrict_map_def intro!: path_conc path1 split: if_split_asm ) [] done } note ip_aux=this show ?thesis unfolding wset_find_path_def find_path_def ws_update_def s_init_def apply (refine_rcg refine_vcg le_ASSERTI WHILET_rule[where R = var and I = inv] ) using [[goals_limit = 1]] apply (auto simp: var_def) [] apply (auto simp: inv_def dom_def split: if_split_asm) [] apply simp apply (auto simp: inv_def) [] apply (auto simp: var_def brk_rel_def) [] apply (simp add: succs_finite) apply (auto simp: inv_def) [] apply clarsimp apply (simp add: ip_aux) apply clarsimp apply (simp add: var_def brk_rel_def wf_aux) [] apply (fastforce simp: inv_def split: option.splits intro: rev_ImageI dest: Image_closed_trancl) [] done qed text \We refine the algorithm to use a foreach-loop\ definition "ws_update_foreach E u p V ws \ FOREACH (LIST_SET_REV_TAG (E``{u})) (\v (V,ws). if v\V then RETURN (V,ws) else do { ASSERT (v\dom ws); RETURN (insert v V,ws( v \ u#p)) } ) (V,ws)" lemma ws_update_foreach_refine[refine]: assumes FIN: "finite (E``{u})" assumes WSS: "dom ws \ V" assumes ID: "(E',E)\Id" "(u',u)\Id" "(p',p)\Id" "(V',V)\Id" "(ws',ws)\Id" shows "ws_update_foreach E' u' p' V' ws' \ \Id (ws_update E u p V ws)" unfolding ID[simplified] unfolding ws_update_foreach_def ws_update_def LIST_SET_REV_TAG_def apply (refine_rcg refine_vcg FIN FOREACH_rule[where I="\it (V',ws'). V'=V \ (E``{u}-it) \ dom ws' \ V' \ ws' = ws ++ (\v. if (u,v)\E \ v\it \ v\V then Some (u#p) else None)"] ) using WSS apply (auto simp: Map.map_add_def split: option.splits if_split_asm intro!: ext[where 'a='a and 'b="'b list option"]) done definition "s_init_foreach U0 \ do { (U0,ws) \ FOREACH U0 (\x (U0,ws). RETURN (insert x U0,ws(x\[]))) ({},Map.empty); RETURN (None,U0,ws) }" lemma s_init_foreach_refine[refine]: assumes FIN: "finite U0" assumes ID: "(U0',U0)\Id" shows "s_init_foreach U0' \\Id (s_init U0)" unfolding s_init_foreach_def s_init_def ID[simplified] apply (refine_rcg refine_vcg FOREACH_rule[where I = "\it (U,ws). U = U0-it \ ws = (\x. if x\U0-it then Some [] else None)"] ) apply (auto simp: FIN intro!: ext ) done definition "wset_find_path' E U0 P \ do { ASSERT (finite U0); s0\s_init_foreach U0; (res,_,_) \ WHILET (\(res,V,ws). res=None \ ws\Map.empty) (\(res,V,ws). do { ASSERT (ws\Map.empty); ((u,p),ws) \ op_map_pick_remove ws; if P u then RETURN (Some (rev p,u),V,ws) else do { (V,ws) \ ws_update_foreach E u p V ws; RETURN (None,V,ws) } }) s0; RETURN res }" lemma wset_find_path'_refine: "wset_find_path' E U0 P \ \Id (wset_find_path E U0 P)" unfolding wset_find_path'_def wset_find_path_def unfolding op_map_pick_remove_alt apply (refine_rcg IdI) apply assumption apply simp_all done section \Refinement to efficient data structures\ schematic_goal wset_find_path'_refine_aux: fixes U0::"'a set" and P::"'a \ bool" and E::"('a\'a) set" and Pimpl :: "'ai \ bool" and node_rel :: "('ai \ 'a) set" and node_eq_impl :: "'ai \ 'ai \ bool" and node_hash_impl and node_def_hash_size assumes [autoref_rules]: "(succi,E)\\node_rel\slg_rel" "(Pimpl,P)\node_rel \ bool_rel" "(node_eq_impl, (=)) \ node_rel \ node_rel \ bool_rel" "(U0',U0)\\node_rel\list_set_rel" assumes [autoref_ga_rules]: "is_bounded_hashcode node_rel node_eq_impl node_hash_impl" "is_valid_def_hm_size TYPE('ai) node_def_hash_size" notes [autoref_tyrel] = TYRELI[where R="\node_rel,\node_rel\list_rel\list_map_rel"] TYRELI[where R="\node_rel\map2set_rel (ahm_rel node_hash_impl)"] (*notes [autoref_rules] = IdI[of P, unfolded fun_rel_id_simp[symmetric]]*) shows "(?c::?'c,wset_find_path' E U0 P) \ ?R" unfolding wset_find_path'_def ws_update_foreach_def s_init_foreach_def using [[autoref_trace_failed_id]] using [[autoref_trace_intf_unif]] using [[autoref_trace_pat]] apply (autoref (keep_goal)) done - find_theorems list_map_update - concrete_definition wset_find_path_impl for node_eq_impl succi U0' Pimpl uses wset_find_path'_refine_aux section \Autoref Setup\ context begin interpretation autoref_syn . lemma [autoref_itype]: "find_path ::\<^sub>i \I\\<^sub>ii_slg \\<^sub>i \I\\<^sub>ii_set \\<^sub>i (I\\<^sub>ii_bool) \\<^sub>i \\\\I\\<^sub>ii_list, I\\<^sub>ii_prod\\<^sub>ii_option\\<^sub>ii_nres" by simp lemma wset_find_path_autoref[autoref_rules]: fixes node_rel :: "('ai \ 'a) set" assumes eq: "GEN_OP node_eq_impl (=) (node_rel\node_rel\bool_rel)" assumes hash: "SIDE_GEN_ALGO (is_bounded_hashcode node_rel node_eq_impl node_hash_impl)" assumes hash_dsz: "SIDE_GEN_ALGO (is_valid_def_hm_size TYPE('ai) node_def_hash_size)" shows "( wset_find_path_impl node_hash_impl node_def_hash_size node_eq_impl, find_path) \ \node_rel\slg_rel \ \node_rel\list_set_rel \ (node_rel\bool_rel) \ \\\node_rel\list_rel\\<^sub>rnode_rel\option_rel\nres_rel" proof - note EQI = GEN_OP_D[OF eq] note HASHI = SIDE_GEN_ALGO_D[OF hash] note DSZI = SIDE_GEN_ALGO_D[OF hash_dsz] note wset_find_path_impl.refine[THEN nres_relD, OF _ _ EQI _ HASHI DSZI] also note wset_find_path'_refine also note wset_find_path_correct finally show ?thesis by (fastforce intro!: nres_relI) qed end schematic_goal wset_find_path_transfer_aux: "RETURN ?c \ wset_find_path_impl hashi dszi eqi E U0 P" unfolding wset_find_path_impl_def by (refine_transfer (post)) concrete_definition wset_find_path_code for E ?U0.0 P uses wset_find_path_transfer_aux lemmas [refine_transfer] = wset_find_path_code.refine export_code wset_find_path_code checking SML section \Nontrivial paths\ definition "find_path1_gen E u0 P \ do { res \ find_path E (E``{u0}) P; case res of None \ RETURN None | Some (p,v) \ RETURN (Some (u0#p,v)) }" lemma find_path1_gen_correct: "find_path1_gen E u0 P \ find_path1 E u0 P" unfolding find_path1_gen_def find_path_def find_path1_def apply (refine_rcg refine_vcg le_ASSERTI) apply (auto intro: path_prepend dest: tranclD elim: finite_subset[rotated] ) done schematic_goal find_path1_impl_aux: fixes node_rel :: "('ai \ 'a) set" assumes [autoref_rules]: "(node_eq_impl, (=)) \ node_rel \ node_rel \ bool_rel" assumes [autoref_ga_rules]: "is_bounded_hashcode node_rel node_eq_impl node_hash_impl" "is_valid_def_hm_size TYPE('ai) node_def_hash_size" shows "(?c,find_path1_gen::(_\_) set \ _) \ \node_rel\slg_rel \ node_rel \ (node_rel \ bool_rel) \ \\\node_rel\list_rel \\<^sub>r node_rel\option_rel\nres_rel" unfolding find_path1_gen_def[abs_def] apply (autoref (trace,keep_goal)) done lemma [autoref_itype]: "find_path1 ::\<^sub>i \I\\<^sub>ii_slg \\<^sub>i I \\<^sub>i (I\\<^sub>ii_bool) \\<^sub>i \\\\I\\<^sub>ii_list, I\\<^sub>ii_prod\\<^sub>ii_option\\<^sub>ii_nres" by simp concrete_definition find_path1_impl uses find_path1_impl_aux lemma find_path1_autoref[autoref_rules]: fixes node_rel :: "('ai \ 'a) set" assumes eq: "GEN_OP node_eq_impl (=) (node_rel\node_rel\bool_rel)" assumes hash: "SIDE_GEN_ALGO (is_bounded_hashcode node_rel node_eq_impl node_hash_impl)" assumes hash_dsz: "SIDE_GEN_ALGO (is_valid_def_hm_size TYPE('ai) node_def_hash_size)" shows "(find_path1_impl node_eq_impl node_hash_impl node_def_hash_size,find_path1) \ \node_rel\slg_rel \node_rel \ (node_rel \ bool_rel) \ \\\node_rel\list_rel \\<^sub>r node_rel\Relators.option_rel\nres_rel" proof - note EQI = GEN_OP_D[OF eq] note HASHI = SIDE_GEN_ALGO_D[OF hash] note DSZI = SIDE_GEN_ALGO_D[OF hash_dsz] note R = find_path1_impl.refine[param_fo, THEN nres_relD, OF EQI HASHI DSZI] note R also note find_path1_gen_correct finally show ?thesis by (blast intro: nres_relI) qed schematic_goal find_path1_transfer_aux: "RETURN ?c \ find_path1_impl eqi hashi dszi E u P" unfolding find_path1_impl_def by refine_transfer concrete_definition find_path1_code for E u P uses find_path1_transfer_aux lemmas [refine_transfer] = find_path1_code.refine end diff --git a/thys/Gabow_SCC/Gabow_Skeleton_Code.thy b/thys/Gabow_SCC/Gabow_Skeleton_Code.thy --- a/thys/Gabow_SCC/Gabow_Skeleton_Code.thy +++ b/thys/Gabow_SCC/Gabow_Skeleton_Code.thy @@ -1,273 +1,271 @@ section \Code Generation for the Skeleton Algorithm \label{sec:skel_code}\ theory Gabow_Skeleton_Code imports Gabow_Skeleton CAVA_Automata.Digraph_Impl CAVA_Base.CAVA_Code_Target begin section \Statistics\ text \ In this section, we do the ML setup that gathers statistics about the algorithm's execution. \ code_printing code_module Gabow_Skeleton_Statistics \ (SML) \ structure Gabow_Skeleton_Statistics = struct val active = Unsynchronized.ref false val num_vis = Unsynchronized.ref 0 val time = Unsynchronized.ref Time.zeroTime fun is_active () = !active fun newnode () = ( num_vis := !num_vis + 1; if !num_vis mod 10000 = 0 then tracing (IntInf.toString (!num_vis) ^ "\n") else () ) fun start () = (active := true; time := Time.now ()) fun stop () = (time := Time.- (Time.now (), !time)) fun to_string () = let val t = Time.toMilliseconds (!time) val states_per_ms = real (!num_vis) / real t val realStr = Real.fmt (StringCvt.FIX (SOME 2)) in "Required time: " ^ IntInf.toString (t) ^ "ms\n" ^ "States per ms: " ^ realStr states_per_ms ^ "\n" ^ "# states: " ^ IntInf.toString (!num_vis) ^ "\n" end val _ = Statistics.register_stat ("Gabow-Skeleton",is_active,to_string) end \ code_reserved SML Gabow_Skeleton_Statistics code_printing constant stat_newnode \ (SML) "Gabow'_Skeleton'_Statistics.newnode" | constant stat_start \ (SML) "Gabow'_Skeleton'_Statistics.start" | constant stat_stop \ (SML) "Gabow'_Skeleton'_Statistics.stop" section \Automatic Refinement Setup\ consts i_node_state :: interface definition "node_state_rel \ {(-1::int,DONE)} \ {(int k,STACK k) | k. True }" lemma node_state_rel_simps[simp]: "(i,DONE)\node_state_rel \ i=-1" "(i,STACK n)\node_state_rel \ i = int n" unfolding node_state_rel_def by auto lemma node_state_rel_sv[simp,intro!,relator_props]: "single_valued node_state_rel" unfolding node_state_rel_def by (auto intro: single_valuedI) lemmas [autoref_rel_intf] = REL_INTFI[of node_state_rel i_node_state] primrec is_DONE where "is_DONE DONE = True" | "is_DONE (STACK _) = False" lemma node_state_rel_refine[autoref_rules]: "(-1,DONE)\node_state_rel" "(int,STACK)\nat_rel\node_state_rel" "(\i. i<0,is_DONE)\node_state_rel\bool_rel" "((\f g i. if i\0 then f (nat i) else g),case_node_state) \(nat_rel \ R) \ R \ node_state_rel \ R" unfolding node_state_rel_def apply auto [3] apply (fastforce dest: fun_relD) done lemma [autoref_op_pat]: "(x=DONE) \ is_DONE x" "(DONE=x) \ is_DONE x" apply (auto intro!: eq_reflection) apply ((cases x, simp_all) [])+ done (* TODO: Make changing the Autoref-config simpler, by concentrating everything here *) consts i_node :: interface (* TODO: Move generic part of this locale to Digraph_impl *) locale fr_graph_impl_loc = fr_graph G for mrel and node_rel :: "('vi \ 'v) set" and node_eq_impl :: "'vi \ 'vi \ bool" and node_hash_impl :: "nat \ 'vi \ nat" and node_def_hash_size :: nat and G_impl and G :: "('v,'more) graph_rec_scheme" + assumes G_refine: "(G_impl,G)\\mrel,node_rel\g_impl_rel_ext" and node_eq_refine: "(node_eq_impl, (=)) \ node_rel \ node_rel \ bool_rel" and node_hash: "is_bounded_hashcode node_rel node_eq_impl node_hash_impl" and node_hash_def_size: "(is_valid_def_hm_size TYPE('vi) node_def_hash_size)" begin (*abbreviation "node_rel \ Id :: ('v \ _) set"*) lemmas [autoref_rel_intf] = REL_INTFI[of node_rel i_node] lemmas [autoref_rules] = G_refine node_eq_refine lemmas [autoref_ga_rules] = node_hash node_hash_def_size lemma locale_this: "fr_graph_impl_loc mrel node_rel node_eq_impl node_hash_impl node_def_hash_size G_impl G" by unfold_locales abbreviation "oGSi_rel \ \node_rel,node_state_rel\(ahm_rel node_hash_impl)" abbreviation "GSi_rel \ \node_rel\as_rel \\<^sub>r \nat_rel\as_rel \\<^sub>r oGSi_rel \\<^sub>r \nat_rel \\<^sub>r \node_rel\list_set_rel\as_rel" lemmas [autoref_op_pat] = GS.S_def GS.B_def GS.I_def GS.P_def end section \Generating the Code\ thm autoref_ga_rules context fr_graph_impl_loc begin schematic_goal push_code_aux: "(?c,push_impl)\node_rel \ GSi_rel \ GSi_rel" unfolding push_impl_def_opt[abs_def] using [[autoref_trace_failed_id]] apply (autoref (keep_goal)) done concrete_definition (in -) push_code uses fr_graph_impl_loc.push_code_aux lemmas [autoref_rules] = push_code.refine[OF locale_this] schematic_goal pop_code_aux: "(?c,pop_impl)\GSi_rel \ \GSi_rel\nres_rel" unfolding pop_impl_def_opt[abs_def] unfolding GS.mark_as_done_def using [[autoref_trace_failed_id]] apply (autoref (keep_goal)) done concrete_definition (in -) pop_code uses fr_graph_impl_loc.pop_code_aux lemmas [autoref_rules] = pop_code.refine[OF locale_this] schematic_goal S_idx_of_code_aux: notes [autoref_rules] = IdI[of "undefined::nat"] (* TODO: hack!*) shows "(?c,GS.S_idx_of)\GSi_rel \ node_rel \ nat_rel" unfolding GS.S_idx_of_def[abs_def] using [[autoref_trace_failed_id]] apply (autoref (keep_goal)) done concrete_definition (in -) S_idx_of_code uses fr_graph_impl_loc.S_idx_of_code_aux lemmas [autoref_rules] = S_idx_of_code.refine[OF locale_this] schematic_goal idx_of_code_aux: notes [autoref_rules] = IdI[of "undefined::nat"] (* TODO: hack!*) shows "(?c,GS.idx_of_impl)\ GSi_rel \ node_rel \ \nat_rel\nres_rel" unfolding GS.idx_of_impl_def[abs_def, unfolded GS.find_seg_impl_def GS.S_idx_of_def, THEN opt_GSdef, unfolded GS_sel_simps, abs_def] using [[autoref_trace_failed_id]] apply (autoref (keep_goal)) done concrete_definition (in -) idx_of_code uses fr_graph_impl_loc.idx_of_code_aux lemmas [autoref_rules] = idx_of_code.refine[OF locale_this] schematic_goal collapse_code_aux: "(?c,collapse_impl)\node_rel \ GSi_rel \ \GSi_rel\nres_rel" unfolding collapse_impl_def_opt[abs_def] using [[autoref_trace_failed_id]] apply (autoref (keep_goal)) done concrete_definition (in -) collapse_code uses fr_graph_impl_loc.collapse_code_aux lemmas [autoref_rules] = collapse_code.refine[OF locale_this] term select_edge_impl schematic_goal select_edge_code_aux: "(?c,select_edge_impl) \ GSi_rel \ \\node_rel\option_rel \\<^sub>r GSi_rel\nres_rel" unfolding select_edge_impl_def_opt[abs_def] using [[autoref_trace_failed_id]] using [[goals_limit=1]] apply (autoref (keep_goal,trace)) done concrete_definition (in -) select_edge_code uses fr_graph_impl_loc.select_edge_code_aux lemmas [autoref_rules] = select_edge_code.refine[OF locale_this] context begin interpretation autoref_syn . term fr_graph.pop_impl lemma [autoref_op_pat]: "push_impl \ OP push_impl" "collapse_impl \ OP collapse_impl" "select_edge_impl \ OP select_edge_impl" "pop_impl \ OP pop_impl" by simp_all end - find_theorems is_valid_def_hm_size - schematic_goal skeleton_code_aux: "(?c,skeleton_impl) \ \oGSi_rel\nres_rel" unfolding skeleton_impl_def[abs_def] initial_impl_def GS_initial_impl_def unfolding path_is_empty_impl_def is_on_stack_impl_def is_done_impl_def is_done_oimpl_def unfolding GS.is_on_stack_impl_def GS.is_done_impl_def using [[autoref_trace_failed_id]] apply (autoref (keep_goal,trace)) done concrete_definition (in -) skeleton_code for node_eq_impl G_impl uses fr_graph_impl_loc.skeleton_code_aux thm skeleton_code.refine lemmas [autoref_rules] = skeleton_code.refine[OF locale_this] schematic_goal pop_tr_aux: "RETURN ?c \ pop_code node_eq_impl node_hash_impl s" unfolding pop_code_def by refine_transfer concrete_definition (in -) pop_tr uses fr_graph_impl_loc.pop_tr_aux lemmas [refine_transfer] = pop_tr.refine[OF locale_this] schematic_goal select_edge_tr_aux: "RETURN ?c \ select_edge_code node_eq_impl s" unfolding select_edge_code_def by refine_transfer concrete_definition (in -) select_edge_tr uses fr_graph_impl_loc.select_edge_tr_aux lemmas [refine_transfer] = select_edge_tr.refine[OF locale_this] schematic_goal idx_of_tr_aux: "RETURN ?c \ idx_of_code node_eq_impl node_hash_impl v s" unfolding idx_of_code_def by refine_transfer concrete_definition (in -) idx_of_tr uses fr_graph_impl_loc.idx_of_tr_aux lemmas [refine_transfer] = idx_of_tr.refine[OF locale_this] schematic_goal collapse_tr_aux: "RETURN ?c \ collapse_code node_eq_impl node_hash_impl v s" unfolding collapse_code_def by refine_transfer concrete_definition (in -) collapse_tr uses fr_graph_impl_loc.collapse_tr_aux lemmas [refine_transfer] = collapse_tr.refine[OF locale_this] schematic_goal skeleton_tr_aux: "RETURN ?c \ skeleton_code node_hash_impl node_def_hash_size node_eq_impl g" unfolding skeleton_code_def by refine_transfer concrete_definition (in -) skeleton_tr uses fr_graph_impl_loc.skeleton_tr_aux lemmas [refine_transfer] = skeleton_tr.refine[OF locale_this] end term skeleton_tr export_code skeleton_tr checking SML end