diff --git a/thys/Incompleteness/Coding.thy b/thys/Incompleteness/Coding.thy --- a/thys/Incompleteness/Coding.thy +++ b/thys/Incompleteness/Coding.thy @@ -1,860 +1,858 @@ chapter\De Bruijn Syntax, Quotations, Codes, V-Codes\ theory Coding imports SyntaxN begin declare fresh_Nil [iff] section \de Bruijn Indices (locally-nameless version)\ nominal_datatype dbtm = DBZero | DBVar name | DBInd nat | DBEats dbtm dbtm nominal_datatype dbfm = DBMem dbtm dbtm | DBEq dbtm dbtm | DBDisj dbfm dbfm | DBNeg dbfm | DBEx dbfm declare dbtm.supp [simp] declare dbfm.supp [simp] fun lookup :: "name list \ nat \ name \ dbtm" where "lookup [] n x = DBVar x" | "lookup (y # ys) n x = (if x = y then DBInd n else (lookup ys (Suc n) x))" lemma fresh_imp_notin_env: "atom name \ e \ name \ set e" by (metis List.finite_set fresh_finite_set_at_base fresh_set) lemma lookup_notin: "x \ set e \ lookup e n x = DBVar x" by (induct e arbitrary: n) auto lemma lookup_in: "x \ set e \ \k. lookup e n x = DBInd k \ n \ k \ k < n + length e" by (induction e arbitrary: n) force+ lemma lookup_fresh: "x \ lookup e n y \ y \ set e \ x \ atom y" by (induct arbitrary: n rule: lookup.induct) (auto simp: pure_fresh fresh_at_base) lemma lookup_eqvt[eqvt]: "(p \ lookup xs n x) = lookup (p \ xs) (p \ n) (p \ x)" by (induct xs arbitrary: n) (simp_all add: permute_pure) lemma lookup_inject [iff]: "(lookup e n x = lookup e n y) \ x = y" proof (induction e n x arbitrary: y rule: lookup.induct) case (2 y ys n x z) then show ?case by (metis dbtm.distinct(7) dbtm.eq_iff(3) lookup.simps(2) lookup_in lookup_notin not_less_eq_eq) qed auto nominal_function trans_tm :: "name list \ tm \ dbtm" where "trans_tm e Zero = DBZero" | "trans_tm e (Var k) = lookup e 0 k" | "trans_tm e (Eats t u) = DBEats (trans_tm e t) (trans_tm e u)" by (auto simp: eqvt_def trans_tm_graph_aux_def) (metis tm.strong_exhaust) nominal_termination (eqvt) by lexicographic_order lemma fresh_trans_tm_iff [simp]: "i \ trans_tm e t \ i \ t \ i \ atom ` set e" by (induct t rule: tm.induct, auto simp: lookup_fresh fresh_at_base) lemma trans_tm_forget: "atom i \ t \ trans_tm [i] t = trans_tm [] t" by (induct t rule: tm.induct, auto simp: fresh_Pair) nominal_function (invariant "\(xs, _) y. atom ` set xs \* y") trans_fm :: "name list \ fm \ dbfm" where "trans_fm e (Mem t u) = DBMem (trans_tm e t) (trans_tm e u)" | "trans_fm e (Eq t u) = DBEq (trans_tm e t) (trans_tm e u)" | "trans_fm e (Disj A B) = DBDisj (trans_fm e A) (trans_fm e B)" | "trans_fm e (Neg A) = DBNeg (trans_fm e A)" | "atom k \ e \ trans_fm e (Ex k A) = DBEx (trans_fm (k#e) A)" supply [[simproc del: defined_all]] apply(simp add: eqvt_def trans_fm_graph_aux_def) apply(erule trans_fm_graph.induct) using [[simproc del: alpha_lst]] apply(auto simp: fresh_star_def) apply (metis fm.strong_exhaust fresh_star_insert) apply(erule Abs_lst1_fcb2') apply (simp_all add: eqvt_at_def) apply (simp_all add: fresh_star_Pair perm_supp_eq) apply (simp add: fresh_star_def) done nominal_termination (eqvt) by lexicographic_order lemma fresh_trans_fm [simp]: "i \ trans_fm e A \ i \ A \ i \ atom ` set e" by (nominal_induct A avoiding: e rule: fm.strong_induct, auto simp: fresh_at_base) abbreviation DBConj :: "dbfm \ dbfm \ dbfm" where "DBConj t u \ DBNeg (DBDisj (DBNeg t) (DBNeg u))" lemma trans_fm_Conj [simp]: "trans_fm e (Conj A B) = DBConj (trans_fm e A) (trans_fm e B)" by (simp add: Conj_def) lemma trans_tm_inject [iff]: "(trans_tm e t = trans_tm e u) \ t = u" proof (induct t arbitrary: u rule: tm.induct) case Zero show ?case apply (cases u rule: tm.exhaust, auto) apply (metis dbtm.distinct(1) dbtm.distinct(3) lookup_in lookup_notin) done next case (Var i) show ?case apply (cases u rule: tm.exhaust, auto) apply (metis dbtm.distinct(1) dbtm.distinct(3) lookup_in lookup_notin) apply (metis dbtm.distinct(10) dbtm.distinct(11) lookup_in lookup_notin) done next case (Eats tm1 tm2) thus ?case apply (cases u rule: tm.exhaust, auto) apply (metis dbtm.distinct(12) dbtm.distinct(9) lookup_in lookup_notin) done qed lemma trans_fm_inject [iff]: "(trans_fm e A = trans_fm e B) \ A = B" proof (nominal_induct A avoiding: e B rule: fm.strong_induct) case (Mem tm1 tm2) thus ?case by (rule fm.strong_exhaust [where y=B and c=e]) (auto simp: fresh_star_def) next case (Eq tm1 tm2) thus ?case by (rule fm.strong_exhaust [where y=B and c=e]) (auto simp: fresh_star_def) next case (Disj fm1 fm2) show ?case by (rule fm.strong_exhaust [where y=B and c=e]) (auto simp: Disj fresh_star_def) next case (Neg fm) show ?case by (rule fm.strong_exhaust [where y=B and c=e]) (auto simp: Neg fresh_star_def) next case (Ex name fm) thus ?case using [[simproc del: alpha_lst]] proof (cases rule: fm.strong_exhaust [where y=B and c="(e, name)"], simp_all add: fresh_star_def) fix name'::name and fm'::fm assume name': "atom name' \ (e, name)" assume "atom name \ fm' \ name = name'" thus "(trans_fm (name # e) fm = trans_fm (name' # e) fm') = ([[atom name]]lst. fm = [[atom name']]lst. fm')" (is "?lhs = ?rhs") proof (rule disjE) assume "name = name'" thus "?lhs = ?rhs" by (metis fresh_Pair fresh_at_base(2) name') next assume name: "atom name \ fm'" have eq1: "(name \ name') \ trans_fm (name' # e) fm' = trans_fm (name' # e) fm'" by (simp add: flip_fresh_fresh name) have eq2: "(name \ name') \ ([[atom name']]lst. fm') = [[atom name']]lst. fm'" by (rule flip_fresh_fresh) (auto simp: Abs_fresh_iff name) show "?lhs = ?rhs" using name' eq1 eq2 Ex(1) Ex(3) [of "name#e" "(name \ name') \ fm'"] by (simp add: flip_fresh_fresh) (metis Abs1_eq(3)) qed qed qed lemma trans_fm_perm: assumes c: "atom c \ (i,j,A,B)" and t: "trans_fm [i] A = trans_fm [j] B" shows "(i \ c) \ A = (j \ c) \ B" proof - have c_fresh1: "atom c \ trans_fm [i] A" using c by (auto simp: supp_Pair) moreover have i_fresh: "atom i \ trans_fm [i] A" by auto moreover have c_fresh2: "atom c \ trans_fm [j] B" using c by (auto simp: supp_Pair) moreover have j_fresh: "atom j \ trans_fm [j] B" by auto ultimately have "((i \ c) \ (trans_fm [i] A)) = ((j \ c) \ trans_fm [j] B)" by (simp only: flip_fresh_fresh t) then have "trans_fm [c] ((i \ c) \ A) = trans_fm [c] ((j \ c) \ B)" by simp then show "(i \ c) \ A = (j \ c) \ B" by simp qed section\Abstraction and Substitution on de Bruijn Formulas\ nominal_function abst_dbtm :: "name \ nat \ dbtm \ dbtm" where "abst_dbtm name i DBZero = DBZero" | "abst_dbtm name i (DBVar name') = (if name = name' then DBInd i else DBVar name')" | "abst_dbtm name i (DBInd j) = DBInd j" | "abst_dbtm name i (DBEats t1 t2) = DBEats (abst_dbtm name i t1) (abst_dbtm name i t2)" apply (simp add: eqvt_def abst_dbtm_graph_aux_def, auto) apply (metis dbtm.exhaust) done nominal_termination (eqvt) by lexicographic_order nominal_function subst_dbtm :: "dbtm \ name \ dbtm \ dbtm" where "subst_dbtm u x DBZero = DBZero" | "subst_dbtm u x (DBVar name) = (if x = name then u else DBVar name)" | "subst_dbtm u x (DBInd j) = DBInd j" | "subst_dbtm u x (DBEats t1 t2) = DBEats (subst_dbtm u x t1) (subst_dbtm u x t2)" by (auto simp: eqvt_def subst_dbtm_graph_aux_def) (metis dbtm.exhaust) nominal_termination (eqvt) by lexicographic_order lemma fresh_iff_non_subst_dbtm: "subst_dbtm DBZero i t = t \ atom i \ t" by (induct t rule: dbtm.induct) (auto simp: pure_fresh fresh_at_base(2)) lemma lookup_append: "lookup (e @ [i]) n j = abst_dbtm i (length e + n) (lookup e n j)" by (induct e arbitrary: n) (auto simp: fresh_Cons) lemma trans_tm_abs: "trans_tm (e@[name]) t = abst_dbtm name (length e) (trans_tm e t)" by (induct t rule: tm.induct) (auto simp: lookup_notin lookup_append) subsection\Well-Formed Formulas\ nominal_function abst_dbfm :: "name \ nat \ dbfm \ dbfm" where "abst_dbfm name i (DBMem t1 t2) = DBMem (abst_dbtm name i t1) (abst_dbtm name i t2)" | "abst_dbfm name i (DBEq t1 t2) = DBEq (abst_dbtm name i t1) (abst_dbtm name i t2)" | "abst_dbfm name i (DBDisj A1 A2) = DBDisj (abst_dbfm name i A1) (abst_dbfm name i A2)" | "abst_dbfm name i (DBNeg A) = DBNeg (abst_dbfm name i A)" | "abst_dbfm name i (DBEx A) = DBEx (abst_dbfm name (i+1) A)" apply (simp add: eqvt_def abst_dbfm_graph_aux_def, auto) apply (metis dbfm.exhaust) done nominal_termination (eqvt) by lexicographic_order nominal_function subst_dbfm :: "dbtm \ name \ dbfm \ dbfm" where "subst_dbfm u x (DBMem t1 t2) = DBMem (subst_dbtm u x t1) (subst_dbtm u x t2)" | "subst_dbfm u x (DBEq t1 t2) = DBEq (subst_dbtm u x t1) (subst_dbtm u x t2)" | "subst_dbfm u x (DBDisj A1 A2) = DBDisj (subst_dbfm u x A1) (subst_dbfm u x A2)" | "subst_dbfm u x (DBNeg A) = DBNeg (subst_dbfm u x A)" | "subst_dbfm u x (DBEx A) = DBEx (subst_dbfm u x A)" by (auto simp: eqvt_def subst_dbfm_graph_aux_def) (metis dbfm.exhaust) nominal_termination (eqvt) by lexicographic_order lemma fresh_iff_non_subst_dbfm: "subst_dbfm DBZero i t = t \ atom i \ t" by (induct t rule: dbfm.induct) (auto simp: fresh_iff_non_subst_dbtm) section\Well formed terms and formulas (de Bruijn representation)\ subsection\Well-Formed Terms\ inductive wf_dbtm :: "dbtm \ bool" where Zero: "wf_dbtm DBZero" | Var: "wf_dbtm (DBVar name)" | Eats: "wf_dbtm t1 \ wf_dbtm t2 \ wf_dbtm (DBEats t1 t2)" equivariance wf_dbtm inductive_cases Zero_wf_dbtm [elim!]: "wf_dbtm DBZero" inductive_cases Var_wf_dbtm [elim!]: "wf_dbtm (DBVar name)" inductive_cases Ind_wf_dbtm [elim!]: "wf_dbtm (DBInd i)" inductive_cases Eats_wf_dbtm [elim!]: "wf_dbtm (DBEats t1 t2)" declare wf_dbtm.intros [intro] lemma wf_dbtm_imp_is_tm: assumes "wf_dbtm x" shows "\t::tm. x = trans_tm [] t" using assms proof (induct rule: wf_dbtm.induct) case Zero thus ?case by (metis trans_tm.simps(1)) next case (Var i) thus ?case by (metis lookup.simps(1) trans_tm.simps(2)) next case (Eats dt1 dt2) thus ?case by (metis trans_tm.simps(3)) qed lemma wf_dbtm_trans_tm: "wf_dbtm (trans_tm [] t)" by (induct t rule: tm.induct) auto theorem wf_dbtm_iff_is_tm: "wf_dbtm x \ (\t::tm. x = trans_tm [] t)" by (metis wf_dbtm_imp_is_tm wf_dbtm_trans_tm) subsection\Well-Formed Formulas\ inductive wf_dbfm :: "dbfm \ bool" where Mem: "wf_dbtm t1 \ wf_dbtm t2 \ wf_dbfm (DBMem t1 t2)" | Eq: "wf_dbtm t1 \ wf_dbtm t2 \ wf_dbfm (DBEq t1 t2)" | Disj: "wf_dbfm A1 \ wf_dbfm A2 \ wf_dbfm (DBDisj A1 A2)" | Neg: "wf_dbfm A \ wf_dbfm (DBNeg A)" | Ex: "wf_dbfm A \ wf_dbfm (DBEx (abst_dbfm name 0 A))" equivariance wf_dbfm lemma atom_fresh_abst_dbtm [simp]: "atom i \ abst_dbtm i n t" by (induct t rule: dbtm.induct) (auto simp: pure_fresh) lemma atom_fresh_abst_dbfm [simp]: "atom i \ abst_dbfm i n A" by (nominal_induct A arbitrary: n rule: dbfm.strong_induct) auto text\Setting up strong induction: "avoiding" for name. Necessary to allow some proofs to go through\ nominal_inductive wf_dbfm avoids Ex: name by (auto simp: fresh_star_def) inductive_cases Mem_wf_dbfm [elim!]: "wf_dbfm (DBMem t1 t2)" inductive_cases Eq_wf_dbfm [elim!]: "wf_dbfm (DBEq t1 t2)" inductive_cases Disj_wf_dbfm [elim!]: "wf_dbfm (DBDisj A1 A2)" inductive_cases Neg_wf_dbfm [elim!]: "wf_dbfm (DBNeg A)" inductive_cases Ex_wf_dbfm [elim!]: "wf_dbfm (DBEx z)" declare wf_dbfm.intros [intro] lemma trans_fm_abs: "trans_fm (e@[name]) A = abst_dbfm name (length e) (trans_fm e A)" apply (nominal_induct A avoiding: name e rule: fm.strong_induct) apply (auto simp: trans_tm_abs fresh_Cons fresh_append) by (metis append_Cons length_Cons) lemma abst_trans_fm: "abst_dbfm name 0 (trans_fm [] A) = trans_fm [name] A" by (metis append_Nil list.size(3) trans_fm_abs) lemma abst_trans_fm2: "i \ j \ abst_dbfm i (Suc 0) (trans_fm [j] A) = trans_fm [j,i] A" using trans_fm_abs [where e="[j]" and name=i] by auto lemma wf_dbfm_imp_is_fm: assumes "wf_dbfm x" shows "\A::fm. x = trans_fm [] A" using assms proof (induct rule: wf_dbfm.induct) case (Mem t1 t2) thus ?case by (metis trans_fm.simps(1) wf_dbtm_imp_is_tm) next case (Eq t1 t2) thus ?case by (metis trans_fm.simps(2) wf_dbtm_imp_is_tm) next case (Disj fm1 fm2) thus ?case by (metis trans_fm.simps(3)) next case (Neg fm) thus ?case by (metis trans_fm.simps(4)) next case (Ex fm name) thus ?case apply auto apply (rule_tac x="Ex name A" in exI) apply (auto simp: abst_trans_fm) done qed lemma wf_dbfm_trans_fm: "wf_dbfm (trans_fm [] A)" apply (nominal_induct A rule: fm.strong_induct) apply (auto simp: wf_dbtm_trans_tm abst_trans_fm) apply (metis abst_trans_fm wf_dbfm.Ex) done lemma wf_dbfm_iff_is_fm: "wf_dbfm x \ (\A::fm. x = trans_fm [] A)" by (metis wf_dbfm_imp_is_fm wf_dbfm_trans_fm) lemma dbtm_abst_ignore [simp]: "abst_dbtm name i (abst_dbtm name j t) = abst_dbtm name j t" by (induct t rule: dbtm.induct) auto lemma abst_dbtm_fresh_ignore [simp]: "atom name \ u \ abst_dbtm name j u = u" by (induct u rule: dbtm.induct) auto lemma dbtm_subst_ignore [simp]: "subst_dbtm u name (abst_dbtm name j t) = abst_dbtm name j t" by (induct t rule: dbtm.induct) auto lemma dbtm_abst_swap_subst: "name \ name' \ atom name' \ u \ subst_dbtm u name (abst_dbtm name' j t) = abst_dbtm name' j (subst_dbtm u name t)" by (induct t rule: dbtm.induct) auto lemma dbfm_abst_swap_subst: "name \ name' \ atom name' \ u \ subst_dbfm u name (abst_dbfm name' j A) = abst_dbfm name' j (subst_dbfm u name A)" by (induct A arbitrary: j rule: dbfm.induct) (auto simp: dbtm_abst_swap_subst) lemma subst_trans_commute [simp]: "atom i \ e \ subst_dbtm (trans_tm e u) i (trans_tm e t) = trans_tm e (subst i u t)" apply (induct t rule: tm.induct) - apply (auto simp: lookup_notin fresh_imp_notin_env) - apply (metis abst_dbtm_fresh_ignore dbtm_subst_ignore lookup_fresh lookup_notin subst_dbtm.simps(2)) - done + apply (auto simp: lookup_notin fresh_imp_notin_env) + by (metis abst_dbtm_fresh_ignore atom_eq_iff dbtm_subst_ignore lookup_fresh) lemma subst_fm_trans_commute [simp]: "subst_dbfm (trans_tm [] u) name (trans_fm [] A) = trans_fm [] (A (name::= u))" apply (nominal_induct A avoiding: name u rule: fm.strong_induct) - apply (auto simp: lookup_notin abst_trans_fm [symmetric]) - apply (metis dbfm_abst_swap_subst fresh_at_base(2) fresh_trans_tm_iff) + apply (auto simp: lookup_notin dbfm_abst_swap_subst simp flip: abst_trans_fm) done lemma subst_fm_trans_commute_eq: "du = trans_tm [] u \ subst_dbfm du i (trans_fm [] A) = trans_fm [] (A(i::=u))" by (metis subst_fm_trans_commute) section\Quotations\ fun htuple :: "nat \ hf" where "htuple 0 = \0,0\" | "htuple (Suc k) = \0, htuple k\" fun HTuple :: "nat \ tm" where "HTuple 0 = HPair Zero Zero" | "HTuple (Suc k) = HPair Zero (HTuple k)" lemma eval_tm_HTuple [simp]: "\HTuple n\e = htuple n" by (induct n) auto lemma fresh_HTuple [simp]: "x \ HTuple n" by (induct n) auto lemma HTuple_eqvt[eqvt]: "(p \ HTuple n) = HTuple (p \ n)" by (induct n, auto simp: HPair_eqvt permute_pure) lemma htuple_nonzero [simp]: "htuple k \ 0" by (induct k) auto lemma htuple_inject [iff]: "htuple i = htuple j \ i=j" proof (induct i arbitrary: j) case 0 show ?case by (cases j) auto next case (Suc i) show ?case by (cases j) (auto simp: Suc) qed subsection \Quotations of de Bruijn terms\ definition nat_of_name :: "name \ nat" where "nat_of_name x = nat_of (atom x)" lemma nat_of_name_inject [simp]: "nat_of_name n1 = nat_of_name n2 \ n1 = n2" by (metis nat_of_name_def atom_components_eq_iff atom_eq_iff sort_of_atom_eq) definition name_of_nat :: "nat \ name" where "name_of_nat n \ Abs_name (Atom (Sort ''SyntaxN.name'' []) n)" lemma nat_of_name_Abs_eq [simp]: "nat_of_name (Abs_name (Atom (Sort ''SyntaxN.name'' []) n)) = n" by (auto simp: nat_of_name_def atom_name_def Abs_name_inverse) lemma nat_of_name_name_eq [simp]: "nat_of_name (name_of_nat n) = n" by (simp add: name_of_nat_def) lemma name_of_nat_nat_of_name [simp]: "name_of_nat (nat_of_name i) = i" by (metis nat_of_name_inject nat_of_name_name_eq) lemma HPair_neq_ORD_OF [simp]: "HPair x y \ ORD_OF i" by (metis Not_Ord_hpair Ord_ord_of eval_tm_HPair eval_tm_ORD_OF) text\Infinite support, so we cannot use nominal primrec.\ function quot_dbtm :: "dbtm \ tm" where "quot_dbtm DBZero = Zero" | "quot_dbtm (DBVar name) = ORD_OF (Suc (nat_of_name name))" | "quot_dbtm (DBInd k) = HPair (HTuple 6) (ORD_OF k)" | "quot_dbtm (DBEats t u) = HPair (HTuple 1) (HPair (quot_dbtm t) (quot_dbtm u))" by (rule dbtm.exhaust) auto termination by lexicographic_order lemma quot_dbtm_inject_lemma [simp]: "\quot_dbtm t\e = \quot_dbtm u\e \ t=u" proof (induct t arbitrary: u rule: dbtm.induct) case DBZero show ?case by (induct u rule: dbtm.induct) auto next case (DBVar name) show ?case by (induct u rule: dbtm.induct) (auto simp: hpair_neq_Ord') next case (DBInd k) show ?case by (induct u rule: dbtm.induct) (auto simp: hpair_neq_Ord hpair_neq_Ord') next case (DBEats t1 t2) thus ?case by (induct u rule: dbtm.induct) (simp_all add: hpair_neq_Ord) qed lemma quot_dbtm_inject [iff]: "quot_dbtm t = quot_dbtm u \ t=u" by (metis quot_dbtm_inject_lemma) subsection \Quotations of de Bruijn formulas\ text\Infinite support, so we cannot use nominal primrec.\ function quot_dbfm :: "dbfm \ tm" where "quot_dbfm (DBMem t u) = HPair (HTuple 0) (HPair (quot_dbtm t) (quot_dbtm u))" | "quot_dbfm (DBEq t u) = HPair (HTuple 2) (HPair (quot_dbtm t) (quot_dbtm u))" | "quot_dbfm (DBDisj A B) = HPair (HTuple 3) (HPair (quot_dbfm A) (quot_dbfm B))" | "quot_dbfm (DBNeg A) = HPair (HTuple 4) (quot_dbfm A)" | "quot_dbfm (DBEx A) = HPair (HTuple 5) (quot_dbfm A)" by (rule_tac y=x in dbfm.exhaust, auto) termination by lexicographic_order lemma htuple_minus_1: "n > 0 \ htuple n = \0, htuple (n - 1)\" by (metis Suc_diff_1 htuple.simps(2)) lemma HTuple_minus_1: "n > 0 \ HTuple n = HPair Zero (HTuple (n - 1))" by (metis Suc_diff_1 HTuple.simps(2)) lemmas HTS = HTuple_minus_1 HTuple.simps \ \for freeness reasoning on codes\ lemma quot_dbfm_inject_lemma [simp]: "\quot_dbfm A\e = \quot_dbfm B\e \ A=B" proof (induct A arbitrary: B rule: dbfm.induct) case (DBMem t u) show ?case by (induct B rule: dbfm.induct) (simp_all add: htuple_minus_1) next case (DBEq t u) show ?case by (induct B rule: dbfm.induct) (auto simp: htuple_minus_1) next case (DBDisj A B') thus ?case by (induct B rule: dbfm.induct) (simp_all add: htuple_minus_1) next case (DBNeg A) thus ?case by (induct B rule: dbfm.induct) (simp_all add: htuple_minus_1) next case (DBEx A) thus ?case by (induct B rule: dbfm.induct) (simp_all add: htuple_minus_1) qed class quot = fixes quot :: "'a \ tm" ("\_\") instantiation tm :: quot begin definition quot_tm :: "tm \ tm" where "quot_tm t = quot_dbtm (trans_tm [] t)" instance .. end lemma quot_dbtm_fresh [simp]: "s \ (quot_dbtm t)" by (induct t rule: dbtm.induct) auto lemma quot_tm_fresh [simp]: fixes t::tm shows "s \ \t\" by (simp add: quot_tm_def) lemma quot_Zero [simp]: "\Zero\ = Zero" by (simp add: quot_tm_def) lemma quot_Var: "\Var x\ = SUCC (ORD_OF (nat_of_name x))" by (simp add: quot_tm_def) lemma quot_Eats: "\Eats x y\ = HPair (HTuple 1) (HPair \x\ \y\)" by (simp add: quot_tm_def) text\irrelevance of the environment for quotations, because they are ground terms\ lemma eval_quot_dbtm_ignore: "\quot_dbtm t\e = \quot_dbtm t\e'" by (induct t rule: dbtm.induct) auto lemma eval_quot_dbfm_ignore: "\quot_dbfm A\e = \quot_dbfm A\e'" by (induct A rule: dbfm.induct) (auto intro: eval_quot_dbtm_ignore) instantiation fm :: quot begin definition quot_fm :: "fm \ tm" where "quot_fm A = quot_dbfm (trans_fm [] A)" instance .. end lemma quot_dbfm_fresh [simp]: "s \ (quot_dbfm A)" by (induct A rule: dbfm.induct) auto lemma quot_fm_fresh [simp]: fixes A::fm shows "s \ \A\" by (simp add: quot_fm_def) lemma quot_fm_permute [simp]: fixes A:: fm shows "p \ \A\ = \A\" by (metis fresh_star_def perm_supp_eq quot_fm_fresh) lemma quot_Mem: "\x IN y\ = HPair (HTuple 0) (HPair (\x\) (\y\))" by (simp add: quot_fm_def quot_tm_def) lemma quot_Eq: "\x EQ y\ = HPair (HTuple 2) (HPair (\x\) (\y\))" by (simp add: quot_fm_def quot_tm_def) lemma quot_Disj: "\A OR B\ = HPair (HTuple 3) (HPair (\A\) (\B\))" by (simp add: quot_fm_def) lemma quot_Neg: "\Neg A\ = HPair (HTuple 4) (\A\)" by (simp add: quot_fm_def) lemma quot_Ex: "\Ex i A\ = HPair (HTuple 5) (quot_dbfm (trans_fm [i] A))" by (simp add: quot_fm_def) lemma eval_quot_fm_ignore: fixes A:: fm shows "\\A\\e = \\A\\e'" by (metis eval_quot_dbfm_ignore quot_fm_def) lemmas quot_simps = quot_Var quot_Eats quot_Eq quot_Mem quot_Disj quot_Neg quot_Ex section\Definitions Involving Coding\ definition q_Var :: "name \ hf" where "q_Var i \ succ (ord_of (nat_of_name i))" definition q_Ind :: "hf \ hf" where "q_Ind k \ \htuple 6, k\" abbreviation Q_Eats :: "tm \ tm \ tm" where "Q_Eats t u \ HPair (HTuple (Suc 0)) (HPair t u)" definition q_Eats :: "hf \ hf \ hf" where "q_Eats x y \ \htuple 1, x, y\" abbreviation Q_Succ :: "tm \ tm" where "Q_Succ t \ Q_Eats t t" definition q_Succ :: "hf \ hf" where "q_Succ x \ q_Eats x x" lemma quot_Succ: "\SUCC x\ = Q_Succ \x\" by (auto simp: SUCC_def quot_Eats) abbreviation Q_HPair :: "tm \ tm \ tm" where "Q_HPair t u \ Q_Eats (Q_Eats Zero (Q_Eats (Q_Eats Zero u) t)) (Q_Eats (Q_Eats Zero t) t)" definition q_HPair :: "hf \ hf \ hf" where "q_HPair x y \ q_Eats (q_Eats 0 (q_Eats (q_Eats 0 y) x)) (q_Eats (q_Eats 0 x) x)" abbreviation Q_Mem :: "tm \ tm \ tm" where "Q_Mem t u \ HPair (HTuple 0) (HPair t u)" definition q_Mem :: "hf \ hf \ hf" where "q_Mem x y \ \htuple 0, x, y\" abbreviation Q_Eq :: "tm \ tm \ tm" where "Q_Eq t u \ HPair (HTuple 2) (HPair t u)" definition q_Eq :: "hf \ hf \ hf" where "q_Eq x y \ \htuple 2, x, y\" abbreviation Q_Disj :: "tm \ tm \ tm" where "Q_Disj t u \ HPair (HTuple 3) (HPair t u)" definition q_Disj :: "hf \ hf \ hf" where "q_Disj x y \ \htuple 3, x, y\" abbreviation Q_Neg :: "tm \ tm" where "Q_Neg t \ HPair (HTuple 4) t" definition q_Neg :: "hf \ hf" where "q_Neg x \ \htuple 4, x\" abbreviation Q_Conj :: "tm \ tm \ tm" where "Q_Conj t u \ Q_Neg (Q_Disj (Q_Neg t) (Q_Neg u))" definition q_Conj :: "hf \ hf \ hf" where "q_Conj t u \ q_Neg (q_Disj (q_Neg t) (q_Neg u))" abbreviation Q_Imp :: "tm \ tm \ tm" where "Q_Imp t u \ Q_Disj (Q_Neg t) u" definition q_Imp :: "hf \ hf \ hf" where "q_Imp t u \ q_Disj (q_Neg t) u" abbreviation Q_Ex :: "tm \ tm" where "Q_Ex t \ HPair (HTuple 5) t" definition q_Ex :: "hf \ hf" where "q_Ex x \ \htuple 5, x\" abbreviation Q_All :: "tm \ tm" where "Q_All t \ Q_Neg (Q_Ex (Q_Neg t))" definition q_All :: "hf \ hf" where "q_All x \ q_Neg (q_Ex (q_Neg x))" lemmas q_defs = q_Var_def q_Ind_def q_Eats_def q_HPair_def q_Eq_def q_Mem_def q_Disj_def q_Neg_def q_Conj_def q_Imp_def q_Ex_def q_All_def lemma q_Eats_iff [iff]: "q_Eats x y = q_Eats x' y' \ x=x' \ y=y'" by (metis hpair_iff q_Eats_def) lemma quot_subst_eq: "\A(i::=t)\ = quot_dbfm (subst_dbfm (trans_tm [] t) i (trans_fm [] A))" by (metis quot_fm_def subst_fm_trans_commute) lemma Q_Succ_cong: "H \ x EQ x' \ H \ Q_Succ x EQ Q_Succ x'" by (metis HPair_cong Refl) section\Quotations are Injective\ subsection\Terms\ lemma eval_tm_inject [simp]: fixes t::tm shows "\\t\\ e = \\u\\ e \ t=u" proof (induct t arbitrary: u rule: tm.induct) case Zero thus ?case by (cases u rule: tm.exhaust) (auto simp: quot_Var quot_Eats) next case (Var i) thus ?case apply (cases u rule: tm.exhaust, auto) apply (auto simp: quot_Var quot_Eats) done next case (Eats t1 t2) thus ?case apply (cases u rule: tm.exhaust, auto) apply (auto simp: quot_Eats quot_Var) done qed subsection\Formulas\ lemma eval_fm_inject [simp]: fixes A::fm shows "\\A\\ e = \\B\\ e \ A=B" proof (nominal_induct B arbitrary: A rule: fm.strong_induct) case (Mem tm1 tm2) thus ?case by (cases A rule: fm.exhaust, auto simp: quot_simps htuple_minus_1) next case (Eq tm1 tm2) thus ?case by (cases A rule: fm.exhaust, auto simp: quot_simps htuple_minus_1) next case (Neg \) thus ?case by (cases A rule: fm.exhaust, auto simp: quot_simps htuple_minus_1) next case (Disj fm1 fm2) thus ?case by (cases A rule: fm.exhaust, auto simp: quot_simps htuple_minus_1) next case (Ex i \) thus ?case apply (induct A arbitrary: i rule: fm.induct) apply (auto simp: trans_fm_perm quot_simps htuple_minus_1 Abs1_eq_iff_all) by (metis (no_types) Abs1_eq_iff_all(3) dbfm.eq_iff(5) fm.eq_iff(5) fresh_Nil trans_fm.simps(5)) qed subsection\The set \\\ of Definition 1.1, constant terms used for coding\ inductive coding_tm :: "tm \ bool" where Ord: "\i. x = ORD_OF i \ coding_tm x" | HPair: "coding_tm x \ coding_tm y \ coding_tm (HPair x y)" declare coding_tm.intros [intro] lemma coding_tm_Zero [intro]: "coding_tm Zero" by (metis ORD_OF.simps(1) Ord) lemma coding_tm_HTuple [intro]: "coding_tm (HTuple k)" by (induct k, auto) inductive_simps coding_tm_HPair [simp]: "coding_tm (HPair x y)" lemma quot_dbtm_coding [simp]: "coding_tm (quot_dbtm t)" apply (induct t rule: dbtm.induct, auto) apply (metis ORD_OF.simps(2) Ord) done lemma quot_dbfm_coding [simp]: "coding_tm (quot_dbfm fm)" by (induct fm rule: dbfm.induct, auto) lemma quot_fm_coding: fixes A::fm shows "coding_tm \A\" by (metis quot_dbfm_coding quot_fm_def) inductive coding_hf :: "hf \ bool" where Ord: "\i. x = ord_of i \ coding_hf x" | HPair: "coding_hf x \ coding_hf y \ coding_hf (\x,y\)" declare coding_hf.intros [intro] lemma coding_hf_0 [intro]: "coding_hf 0" by (metis coding_hf.Ord ord_of.simps(1)) inductive_simps coding_hf_hpair [simp]: "coding_hf (\x,y\)" lemma coding_tm_hf [simp]: "coding_tm t \ coding_hf \t\e" by (induct t rule: coding_tm.induct) auto section \V-Coding for terms and formulas, for the Second Theorem\ text\Infinite support, so we cannot use nominal primrec.\ function vquot_dbtm :: "name set \ dbtm \ tm" where "vquot_dbtm V DBZero = Zero" | "vquot_dbtm V (DBVar name) = (if name \ V then Var name else ORD_OF (Suc (nat_of_name name)))" | "vquot_dbtm V (DBInd k) = HPair (HTuple 6) (ORD_OF k)" | "vquot_dbtm V (DBEats t u) = HPair (HTuple 1) (HPair (vquot_dbtm V t) (vquot_dbtm V u))" by (auto, rule_tac y=b in dbtm.exhaust, auto) termination by lexicographic_order lemma fresh_vquot_dbtm [simp]: "i \ vquot_dbtm V tm \ i \ tm \ i \ atom ` V" by (induct tm rule: dbtm.induct) (auto simp: fresh_at_base pure_fresh) text\Infinite support, so we cannot use nominal primrec.\ function vquot_dbfm :: "name set \ dbfm \ tm" where "vquot_dbfm V (DBMem t u) = HPair (HTuple 0) (HPair (vquot_dbtm V t) (vquot_dbtm V u))" | "vquot_dbfm V (DBEq t u) = HPair (HTuple 2) (HPair (vquot_dbtm V t) (vquot_dbtm V u))" | "vquot_dbfm V (DBDisj A B) = HPair (HTuple 3) (HPair (vquot_dbfm V A) (vquot_dbfm V B))" | "vquot_dbfm V (DBNeg A) = HPair (HTuple 4) (vquot_dbfm V A)" | "vquot_dbfm V (DBEx A) = HPair (HTuple 5) (vquot_dbfm V A)" by (auto, rule_tac y=b in dbfm.exhaust, auto) termination by lexicographic_order lemma fresh_vquot_dbfm [simp]: "i \ vquot_dbfm V fm \ i \ fm \ i \ atom ` V" by (induct fm rule: dbfm.induct) (auto simp: HPair_def HTuple_minus_1) class vquot = fixes vquot :: "'a \ name set \ tm" ("\_\_" [0,1000]1000) instantiation tm :: vquot begin definition vquot_tm :: "tm \ name set \ tm" where "vquot_tm t V = vquot_dbtm V (trans_tm [] t)" instance .. end lemma vquot_dbtm_empty [simp]: "vquot_dbtm {} t = quot_dbtm t" by (induct t rule: dbtm.induct) auto lemma vquot_tm_empty [simp]: fixes t::tm shows "\t\{} = \t\" by (simp add: vquot_tm_def quot_tm_def) lemma vquot_dbtm_eq: "atom ` V \ supp t = atom ` W \ supp t \ vquot_dbtm V t = vquot_dbtm W t" by (induct t rule: dbtm.induct) (auto simp: image_iff, blast+) instantiation fm :: vquot begin definition vquot_fm :: "fm \ name set \ tm" where "vquot_fm A V = vquot_dbfm V (trans_fm [] A)" instance .. end lemma vquot_fm_fresh [simp]: fixes A::fm shows "i \ \A\V \ i \ A \ i \ atom ` V" by (simp add: vquot_fm_def) lemma vquot_dbfm_empty [simp]: "vquot_dbfm {} A = quot_dbfm A" by (induct A rule: dbfm.induct) auto lemma vquot_fm_empty [simp]: fixes A::fm shows "\A\{} = \A\" by (simp add: vquot_fm_def quot_fm_def) lemma vquot_dbfm_eq: "atom ` V \ supp A = atom ` W \ supp A \ vquot_dbfm V A = vquot_dbfm W A" by (induct A rule: dbfm.induct) (auto simp: intro!: vquot_dbtm_eq, blast+) lemma vquot_fm_insert: fixes A::fm shows "atom i \ supp A \ \A\(insert i V) = \A\V" by (auto simp: vquot_fm_def supp_conv_fresh intro: vquot_dbfm_eq) declare HTuple.simps [simp del] end diff --git a/thys/Sophomores_Dream/Sophomores_Dream.thy b/thys/Sophomores_Dream/Sophomores_Dream.thy --- a/thys/Sophomores_Dream/Sophomores_Dream.thy +++ b/thys/Sophomores_Dream/Sophomores_Dream.thy @@ -1,522 +1,442 @@ (* File: Sophomores_Dream.thy Author: Manuel Eberl, University of Innsbruck *) section \The Sophomore's Dream\ theory Sophomores_Dream imports "HOL-Analysis.Analysis" "HOL-Real_Asymp.Real_Asymp" begin text \ This formalisation mostly follows the very clear proof sketch from Wikipedia~\cite{wikipedia}. That article also provides an interesting historical perspective. A more detailed exploration of Bernoulli's historical proof can be found in the book by Dunham~\cite{dunham}. The name `Sophomore's Dream' apparently comes from a book by Borwein et al., in analogy to the `Freshman's Dream' equation $(x+y)^n = x^n + y^n$ (which is generally \<^emph>\not\ true except in rings of characteristic $n$). \ -subsection \Auxiliary material\ - -(* TODO: Move to library! *) -lemma integrable_cong: - assumes "\x. x \ A \ f x = g x" - shows "f integrable_on A \ g integrable_on A" - using has_integral_cong [OF assms] by fast - -lemma has_integral_cmul_iff': - assumes "c \ 0" - shows "((\x. c *\<^sub>R f x) has_integral I) A \ (f has_integral I /\<^sub>R c) A" - using assms by (metis divideR_right has_integral_cmul_iff) - -lemma has_integral_Icc_iff_Ioo: - fixes f :: "real \ 'a :: banach" - shows "(f has_integral I) {a..b} \ (f has_integral I) {a<.. {a..b} - {a<.. 0}" - by (rule negligible_subset [of "{a,b}"]) auto - show "negligible {x \ {a<.. 0}" - by (rule negligible_subset [of "{}"]) auto -qed - -lemma integrable_on_Icc_iff_Ioo: - fixes f :: "real \ 'a :: banach" - shows "f integrable_on {a..b} \ f integrable_on {a<.. 'a :: banach" - assumes "summable (\n. norm (f n))" and "f sums S" - shows "has_sum f (UNIV :: nat set) S" - unfolding has_sum_def tendsto_iff eventually_finite_subsets_at_top -proof (safe, goal_cases) - case (1 \) - from assms(1) obtain S' where S': "(\n. norm (f n)) sums S'" - by (auto simp: summable_def) - with 1 obtain N where N: "\n. n \ N \ \S' - (\i < \" - by (auto simp: tendsto_iff eventually_at_top_linorder sums_def dist_norm abs_minus_commute) - - show ?case - proof (rule exI[of _ "{..n. if n \ Y then 0 else f n) sums (S - sum f Y)" - by (intro sums_If_finite_set'[OF \f sums S\]) (auto simp: sum_negf) - hence "S - sum f Y = (\n. if n \ Y then 0 else f n)" - by (simp add: sums_iff) - also have "norm \ \ (\n. norm (if n \ Y then 0 else f n))" - by (rule summable_norm[OF summable_comparison_test'[OF assms(1)]]) auto - also have "\ \ (\n. if n < N then 0 else norm (f n))" - using 2 by (intro suminf_le summable_comparison_test'[OF assms(1)]) auto - also have "(\n. if n \ {..in. if n < N then 0 else norm (f n)) = S' - (\ii \S' - (\i" by simp - also have "\ < \" by (rule N) auto - finally show ?case by (simp add: dist_norm norm_minus_commute) - qed auto -qed - -lemma norm_summable_imp_summable_on: - fixes f :: "nat \ 'a :: banach" - assumes "summable (\n. norm (f n))" - shows "f summable_on UNIV" - using norm_summable_imp_has_sum[OF assms, of "suminf f"] assms - by (auto simp: sums_iff summable_on_def dest: summable_norm_cancel) - -lemma summable_comparison_test_bigo: - fixes f :: "nat \ real" - assumes "summable (\n. norm (g n))" "f \ O(g)" - shows "summable f" -proof - - from \f \ O(g)\ obtain C where C: "eventually (\x. norm (f x) \ C * norm (g x)) at_top" - by (auto elim: landau_o.bigE) - thus ?thesis - by (rule summable_comparison_test_ev) (insert assms, auto intro: summable_mult) -qed - - subsection \Continuity and bounds for $x \log x$\ lemma x_log_x_continuous: "continuous_on {0..1} (\x::real. x * ln x)" proof - have "continuous (at x within {0..1}) (\x::real. x * ln x)" if "x \ {0..1}" for x proof (cases "x = 0") case True have "((\x::real. x * ln x) \ 0) (at_right 0)" by real_asymp thus ?thesis using True by (simp add: continuous_def Lim_ident_at at_within_Icc_at_right) qed (auto intro!: continuous_intros) thus ?thesis using continuous_on_eq_continuous_within by blast qed lemma x_log_x_within_01_le: assumes "x \ {0..(1::real)}" shows "x * ln x \ {-exp (-1)..0}" proof - have "x * ln x \ 0" using assms by (cases "x = 0") (auto simp: mult_nonneg_nonpos) let ?f = "\x::real. x * ln x" have diff: "(?f has_field_derivative (ln x + 1)) (at x)" if "x > 0" for x using that by (auto intro!: derivative_eq_intros) have diff': "?f differentiable at x" if "x > 0" for x using diff[OF that] real_differentiable_def by blast consider "x = 0" | "x = 1" | "x = exp (-1)" | "0 < x" "x < exp (-1)" | "exp (-1) < x" "x < 1" using assms unfolding atLeastAtMost_iff by linarith hence "x * ln x \ -exp (-1)" proof cases assume x: "0 < x" "x < exp (-1)" have "\l z. x < z \ z < exp (-1) \ (?f has_real_derivative l) (at z) \ ?f (exp (-1)) - ?f x = (exp (-1) - x) * l" using x by (intro MVT continuous_on_subset [OF x_log_x_continuous] diff') auto then obtain l z where lz: "x < z" "z < exp (-1)" "(?f has_real_derivative l) (at z)" "?f x = -exp (-1) - (exp (-1) - x) * l" by (auto simp: algebra_simps) have [simp]: "l = ln z + 1" using DERIV_unique[OF diff[of z] lz(3)] lz(1) x by auto have "ln z \ ln (exp (-1))" using lz x by (subst ln_le_cancel_iff) auto hence "(exp (- 1) - x) * l \ 0" using x lz by (intro mult_nonneg_nonpos) auto with lz show ?thesis by linarith next assume x: "exp (-1) < x" "x < 1" have "\l z. exp (-1) < z \ z < x \ (?f has_real_derivative l) (at z) \ ?f x - ?f (exp (-1)) = (x - exp (-1)) * l" proof (intro MVT continuous_on_subset [OF x_log_x_continuous] diff') fix t :: real assume t: "exp (-1) < t" show "t > 0" by (rule less_trans [OF _ t]) auto qed (use x in auto) then obtain l z where lz: "exp (-1) < z" "z < x" "(?f has_real_derivative l) (at z)" "?f x = -exp (-1) - (exp (-1) - x) * l" by (auto simp: algebra_simps) have "z > 0" by (rule less_trans [OF _ lz(1)]) auto have [simp]: "l = ln z + 1" using DERIV_unique[OF diff[of z] lz(3)] \z > 0\ by auto have "ln z \ ln (exp (-1))" using lz \z > 0\ by (subst ln_le_cancel_iff) auto hence "(exp (- 1) - x) * l \ 0" using x lz by (intro mult_nonpos_nonneg) auto with lz show ?thesis by linarith qed auto with \x * ln x \ 0\ show ?thesis by auto qed subsection \Convergence, Summability, Integrability\ text \ As a first result we can show that the two sums that occur in the two different versions of the Sophomore's Dream are absolutely summable. This is achieved by a simple comparison test with the series $\sum_{k=1}^\infty k^{-2}$, as $k^{-k} \in O(k^{-2})$. \ theorem abs_summable_sophomores_dream: "summable (\k. 1 / real (k ^ k))" proof (rule summable_comparison_test_bigo) show "(\k. 1 / real (k ^ k)) \ O(\k. 1 / real k ^ 2)" by real_asymp show "summable (\n. norm (1 / real n ^ 2))" using inverse_power_summable[of 2, where ?'a = real] by (simp add: field_simps) qed text \ The existence of the integral is also fairly easy to show since the integrand is continuous and the integration domain is compact. There is, however, one hiccup: The integrand is not actually continuous. We have $\lim_{x\to 0} x^x = 1$, but in Isabelle $0^0$ is defined as \0\ (for real numbers). Thus, there is a discontinuity at \x = 0\ However, this is a removable discontinuity since for any $x>0$ we have $x^x = e^{x\log x}$, and as we have just shown, $e^{x \log x}$ \<^emph>\is\ continuous on $[0, 1]$. Since the two integrands differ only for \x = 0\ (which is negligible), the integral still exists. \ theorem integrable_sophomores_dream: "(\x::real. x powr x) integrable_on {0..1}" proof - have "(\x::real. exp (x * ln x)) integrable_on {0..1}" by (intro integrable_continuous_real continuous_on_exp x_log_x_continuous) also have "?this \ (\x::real. exp (x * ln x)) integrable_on {0<..<1}" by (simp add: integrable_on_Icc_iff_Ioo) also have "\ \ (\x::real. x powr x) integrable_on {0<..<1}" by (intro integrable_cong) (auto simp: powr_def) also have "\ \ ?thesis" by (simp add: integrable_on_Icc_iff_Ioo) finally show ?thesis . qed text \ Next, we have to show the absolute convergence of the two auxiliary sums that will occur in our proofs so that we can exchange the order of integration and summation. This is done with a straightforward application of the Weierstra\ss\ \M\ test. \ lemma uniform_limit_sophomores_dream1: "uniform_limit {0..(1::real)} (\n x. \kx. \k. (x * ln x) ^ k / fact k) sequentially" proof (rule Weierstrass_m_test) show "summable (\k. exp (-1) ^ k / fact k :: real)" using summable_exp[of "exp (-1)"] by (simp add: field_simps) next fix k :: nat and x :: real assume x: "x \ {0..1}" have "norm ((x * ln x) ^ k / fact k) = norm (x * ln x) ^ k / fact k" by (simp add: power_abs) also have "\ \ exp (-1) ^ k / fact k" by (intro divide_right_mono power_mono) (use x_log_x_within_01_le [of x] x in auto) finally show "norm ((x * ln x) ^ k / fact k) \ exp (- 1) ^ k / fact k" . qed lemma uniform_limit_sophomores_dream2: "uniform_limit {0..(1::real)} (\n x. \kx. \k. (-(x * ln x)) ^ k / fact k) sequentially" proof (rule Weierstrass_m_test) show "summable (\k. exp (-1) ^ k / fact k :: real)" using summable_exp[of "exp (-1)"] by (simp add: field_simps) next fix k :: nat and x :: real assume x: "x \ {0..1}" have "norm ((-x * ln x) ^ k / fact k) = norm (x * ln x) ^ k / fact k" by (simp add: power_abs) also have "\ \ exp (-1) ^ k / fact k" by (intro divide_right_mono power_mono) (use x_log_x_within_01_le [of x] x in auto) finally show "norm ((-(x * ln x)) ^ k / fact k) \ exp (- 1) ^ k / fact k" by simp qed subsection \An auxiliary integral\ text \ Next we compute the integral \[\int_0^1 (x\log x)^n\,\text{d}x = \frac{(-1)^n\, n!}{(n+1)^{n+1}}\ ,\] which is a key ingredient in our proof. \ lemma sophomores_dream_aux_integral: "((\x. (x * ln x) ^ n) has_integral (- 1) ^ n * fact n / real ((n + 1) ^ (n + 1))) {0<..<1}" proof - have "((\t. t powr real n / exp t) has_integral fact n) {0..}" using Gamma_integral_real[of "n + 1"] by (auto simp: Gamma_fact powr_realpow) also have "?this \ ((\t. t powr real n / exp t) has_integral fact n) {0<..}" proof (rule has_integral_spike_set_eq) have eq: "{x \ {0<..} - {0..}. x powr real n / exp x \ 0} = {}" by auto thus "negligible {x \ {0<..} - {0..}. x powr real n / exp x \ 0}" by (subst eq) auto have "{x \ {0..} - {0<..}. x powr real n / exp x \ 0} \ {0}" by auto moreover have "negligible {0::real}" by simp ultimately show "negligible {x \ {0..} - {0<..}. x powr real n / exp x \ 0}" by (meson negligible_subset) qed also have "\ \ ((\t::real. t ^ n / exp t) has_integral fact n) {0<..}" by (intro has_integral_spike_eq) (auto simp: powr_realpow) finally have 1: "((\t::real. t ^ n / exp t) has_integral fact n) {0<..}" . have "(\x::real. \x\ ^ n / exp x) integrable_on {0<..} \ (\x::real. x ^ n / exp x) integrable_on {0<..}" by (intro integrable_cong) auto hence 2: "(\t::real. t ^ n / exp t) absolutely_integrable_on {0<..}" using 1 by (simp add: absolutely_integrable_on_def power_abs has_integral_iff) define g :: "real \ real" where "g = (\x. -ln x * (n + 1))" define g' :: "real \ real" where "g' = (\x. -(n + 1) / x)" define h :: "real \ real" where "h = (\u. exp (-u / (n + 1)))" have bij: "bij_betw g {0<..<1} {0<..}" by (rule bij_betwI[of _ _ _ h]) (auto simp: g_def h_def mult_neg_pos) have deriv: "(g has_real_derivative g' x) (at x within {0<..<1})" if "x \ {0<..<1}" for x unfolding g_def g'_def using that by (auto intro!: derivative_eq_intros simp: field_simps) have "(\t::real. t ^ n / exp t) absolutely_integrable_on g ` {0<..<1} \ integral (g ` {0<..<1}) (\t::real. t ^ n / exp t) = fact n" using 1 2 bij by (simp add: bij_betw_def has_integral_iff) also have "?this \ ((\x. \g' x\ *\<^sub>R (g x ^ n / exp (g x))) absolutely_integrable_on {0<..<1} \ integral {0<..<1} (\x. \g' x\ *\<^sub>R (g x ^ n / exp (g x))) = fact n)" by (intro has_absolute_integral_change_of_variables_1' [symmetric] deriv) (auto simp: inj_on_def g_def) finally have "((\x. \g' x\ *\<^sub>R (g x ^ n / exp (g x))) has_integral fact n) {0<..<1}" using eq_integralD set_lebesgue_integral_eq_integral(1) by blast also have "?this \ ((\x::real. ((-1)^n*(n+1)^(n+1)) *\<^sub>R (ln x ^ n * x ^ n)) has_integral fact n) {0<..<1}" proof (rule has_integral_cong) fix x :: real assume x: "x \ {0<..<1}" have "\g' x\ *\<^sub>R (g x ^ n / exp (g x)) = (-1) ^ n * (real n + 1) ^ (n + 1) * ln x ^ n * (exp (ln x * (n + 1)) / x)" using x by (simp add: g_def g'_def exp_minus power_minus' divide_simps add_ac) also have "exp (ln x * (n + 1)) = x powr real (n + 1)" using x by (simp add: powr_def) also have "\ / x = x ^ n" using x by (subst powr_realpow) auto finally show "\g' x\ *\<^sub>R (g x ^ n / exp (g x)) = ((-1)^n*(n+1)^(n+1)) *\<^sub>R (ln x ^ n * x ^ n)" by (simp add: algebra_simps) qed also have "\ \ ((\x::real. ln x ^ n * x ^ n) has_integral fact n /\<^sub>R real_of_int ((- 1) ^ n * int ((n + 1) ^ (n + 1)))) {0<..<1}" by (intro has_integral_cmul_iff') (auto simp del: power_Suc) also have "fact n /\<^sub>R real_of_int ((- 1) ^ n * int ((n + 1) ^ (n + 1))) = (-1) ^ n * fact n / (n+1) ^ (n+1)" by (auto simp: divide_simps) finally show ?thesis by (simp add: power_mult_distrib mult_ac) qed subsection \Main proofs\ text \ We can now show the first formula: $\int_0^1 x^{-x}\,\text{d}x = \sum_{n=1}^\infty n^{-n}$ \ lemma sophomores_dream_aux1: "summable (\k. 1 / real ((k+1)^(k+1)))" "integral {0..1} (\x. x powr (-x)) = (\n. 1 / (n+1)^(n+1))" proof - define S where "S = (\x::real. \k. (-(x * ln x)) ^ k / fact k)" have S_eq: "S x = x powr (-x)" if "x > 0" for x proof - have "S x = exp (-x * ln x)" by (simp add: S_def exp_def field_simps) also have "\ = x powr (-x)" using \x > 0\ by (simp add: powr_def) finally show ?thesis . qed have cont: "continuous_on {0..1} (\x::real. \kn. ((\x. \k J" using uniform_limit_integral [OF uniform_limit_sophomores_dream2 cont] by (auto simp: S_def) note \(S has_integral J) {0..1}\ also have "(S has_integral J) {0..1} \ (S has_integral J) {0<..<1}" by (simp add: has_integral_Icc_iff_Ioo) also have "\ \ ((\x. x powr (-x)) has_integral J) {0<..<1}" by (intro has_integral_cong) (use S_eq in auto) also have "\ \ ((\x. x powr (-x)) has_integral J) {0..1}" by (simp add: has_integral_Icc_iff_Ioo) finally have integral: "((\x. x powr (-x)) has_integral J) {0..1}" . have I_eq: "I = (\n. \kx::real. \kkx::real. \kx::real. \kkkkk. 1 / real ((k + 1) ^ (k + 1))) sums J" using IJ(3) I_eq by (simp add: sums_def) from sums show "summable (\k. 1 / real ((k+1)^(k+1)))" by (simp add: sums_iff) from integral sums show "integral {0..1} (\x. x powr (-x)) = (\n. 1 / (n+1)^(n+1))" by (simp add: sums_iff has_integral_iff) qed theorem sophomores_dream1: "(\k::nat. norm (k powi (-k))) summable_on {1..}" "integral {0..1} (\x. x powr (-x)) = (\\<^sub>\ k\{(1::nat)..}. k powi (-k))" proof - let ?I = "integral {0..1} (\x. x powr (-x))" have "(\k::nat. norm (k powi (-k))) summable_on UNIV" using abs_summable_sophomores_dream by (intro norm_summable_imp_summable_on) (auto simp: power_int_minus field_simps) thus "(\k::nat. norm (k powi (-k))) summable_on {1..}" by (rule summable_on_subset_banach) auto have "(\n. 1 / (n+1)^(n+1)) sums ?I" using sophomores_dream_aux1 by (simp add: sums_iff) moreover have "summable (\n. norm (1 / real (Suc n ^ Suc n)))" by (subst summable_Suc_iff) (use abs_summable_sophomores_dream in \auto simp: field_simps\) ultimately have "has_sum (\n::nat. 1 / (n+1)^(n+1)) UNIV ?I" by (intro norm_summable_imp_has_sum) auto also have "?this \ has_sum ((\n::nat. 1 / n^n) \ Suc) UNIV ?I" by (simp add: o_def field_simps) also have "\ \ has_sum (\n::nat. 1 / n ^ n) (Suc ` UNIV) ?I" by (intro has_sum_reindex [symmetric]) auto also have "Suc ` UNIV = {1..}" using greaterThan_0 by auto also have "has_sum (\n::nat. (1 / real (n ^ n))) {1..} ?I \ has_sum (\n::nat. n powi (-n)) {1..} ?I" by (intro has_sum_cong) (auto simp: power_int_minus field_simps power_minus') finally show "integral {0..1} (\x. x powr (-x)) = (\\<^sub>\k\{(1::nat)..}. k powi (-k))" by (auto dest!: infsumI simp: algebra_simps) qed text \ Next, we show the second formula: $\int_0^1 x^x\,\text{d}x = -\sum_{n=1}^\infty (-n)^{-n}$ \ lemma sophomores_dream_aux2: "summable (\k. (-1) ^ k / real ((k+1)^(k+1)))" "integral {0..1} (\x. x powr x) = (\n. (-1)^n / (n+1)^(n+1))" proof - define S where "S = (\x::real. \k. (x * ln x) ^ k / fact k)" have S_eq: "S x = x powr x" if "x > 0" for x proof - have "S x = exp (x * ln x)" by (simp add: S_def exp_def field_simps) also have "\ = x powr x" using \x > 0\ by (simp add: powr_def) finally show ?thesis . qed have cont: "continuous_on {0..1} (\x::real. \kn. ((\x. \k J" using uniform_limit_integral [OF uniform_limit_sophomores_dream1 cont] by (auto simp: S_def) note \(S has_integral J) {0..1}\ also have "(S has_integral J) {0..1} \ (S has_integral J) {0<..<1}" by (simp add: has_integral_Icc_iff_Ioo) also have "\ \ ((\x. x powr x) has_integral J) {0<..<1}" by (intro has_integral_cong) (use S_eq in auto) also have "\ \ ((\x. x powr x) has_integral J) {0..1}" by (simp add: has_integral_Icc_iff_Ioo) finally have integral: "((\x. x powr x) has_integral J) {0..1}" . have I_eq: "I = (\n. \kx::real. \kkkkkk. (-1) ^ k / real ((k + 1) ^ (k + 1))) sums J" using IJ(3) I_eq by (simp add: sums_def) from sums show "summable (\k. (-1) ^ k / real ((k+1)^(k+1)))" by (simp add: sums_iff) from integral sums show "integral {0..1} (\x. x powr x) = (\n. (-1)^n / (n+1)^(n+1))" by (simp add: sums_iff has_integral_iff) qed theorem sophomores_dream2: "(\k::nat. norm ((-k) powi (-k))) summable_on {1..}" "integral {0..1} (\x. x powr x) = -(\\<^sub>\ k\{(1::nat)..}. (-k) powi (-k))" proof - let ?I = "integral {0..1} (\x. x powr x)" have "(\k::nat. norm ((-k) powi (-k))) summable_on UNIV" using abs_summable_sophomores_dream by (intro norm_summable_imp_summable_on) (auto simp: power_int_minus field_simps) thus "(\k::nat. norm ((-k) powi (-k))) summable_on {1..}" by (rule summable_on_subset_banach) auto have "(\n. (-1)^n / (n+1)^(n+1)) sums ?I" using sophomores_dream_aux2 by (simp add: sums_iff) moreover have "summable (\n. 1 / real (Suc n ^ Suc n))" by (subst summable_Suc_iff) (use abs_summable_sophomores_dream in \auto simp: field_simps\) hence "summable (\n. norm ((- 1) ^ n / real (Suc n ^ Suc n)))" by simp ultimately have "has_sum (\n::nat. (-1)^n / (n+1)^(n+1)) UNIV ?I" by (intro norm_summable_imp_has_sum) auto also have "?this \ has_sum ((\n::nat. -((-1)^n / n^n)) \ Suc) UNIV ?I" by (simp add: o_def field_simps) also have "\ \ has_sum (\n::nat. -((-1)^n / n ^ n)) (Suc ` UNIV) ?I" by (intro has_sum_reindex [symmetric]) auto also have "Suc ` UNIV = {1..}" using greaterThan_0 by auto also have "has_sum (\n::nat. -((- 1) ^ n / real (n ^ n))) {1..} ?I \ has_sum (\n::nat. -((-n) powi (-n))) {1..} ?I" by (intro has_sum_cong) (auto simp: power_int_minus field_simps power_minus') also have "\ \ has_sum (\n::nat. (-n) powi (-n)) {1..} (-?I)" by (simp add: has_sum_uminus) finally show "integral {0..1} (\x. x powr x) = -(\\<^sub>\k\{(1::nat)..}. (-k) powi (-k))" by (auto dest!: infsumI simp: algebra_simps) qed end \ No newline at end of file