theory CoWBasic imports Main begin chapter "Combinatorics on Words - Basic" section "Preliminaries" text\We use lists as a basic datatype. We first give a few abbreviations and definitions concerning lists, followed by some lemmas.\ subsection "Definitions and notations" abbreviation concat_list :: "'a list \ 'a list \ 'a list" (infixl "\" 70) where "concat_list xs ys \ xs @ ys" abbreviation empty_list :: "'a list" ("\") where "empty_list \ []" abbreviation nonempty_element (infixl "\n" 50) where "u \n S \ (u \ S \ u \ \)" abbreviation drop_emp :: "'a list set \ 'a list set" ( "_\<^sub>+" [1000] ) where "drop_emp S \ S - {\}" lemma nemp_elem_setI[intro]: "u \ S \ u \ \ \ u \ S\<^sub>+" by simp lemma nel_drop_emp: "u \n S \ u \ S\<^sub>+" by simp lemma nel_drop_emp': "u \ S\<^sub>+ \ u \n S" by simp definition prefix (infixl "\p" 50) where prefix_def[simp]: "u \p v \ \ z. v = u \ z" lemma prefI[simp, intro]: " v = u \ z \ u \p v" by simp lemma prefE[simp, elim]: "u \p v \ \ z. v = u \ z" by simp abbreviation prefix_comparable :: "'a list \ 'a list \ bool" (infixl "\" 50) where "(prefix_comparable u v) \ u \p v \ v \p u" definition nonempty_prefix (infixl "\np" 50) where nonempty_prefix_def[simp]: "u \np v \ u \ \ \ u \p v" lemma nemp_prefI_pref[intro]: "u \ \ \ u \p v \ u \np v" by simp lemma nemp_prefI[intro]: "u \ \ \ (\ z. v = u \ z) \ u \np v" by simp definition suffix (infixl "\s" 60) where suffix_def[simp]: "u \s v \ \ z. v = z\u" abbreviation suffix_comparable :: "'a list \ 'a list \ bool" (infixl "\\<^sub>s" 50) where "(suffix_comparable u v) \ u \s v \ v \s u" lemma sufI[simp, intro]: " v = z \ u \ u \s v" by simp lemma sufE[simp, elim]: "u \s v \ \ z. v = z \ u" by simp definition nonempty_suffix (infixl "\ns" 60) where nonempty_suffix_def[simp]: "u \ns v \ u \ \ \ u \s v" definition factor (infixl "\f" 60) where factor_def[simp]: "u \f v \ \ p s. v = p\u\s" definition nonempty_factor (infixl "\nf" 60) where nonempty_factor_def[simp]: "u \nf v \ u \ \ \ (\ p s. v = p\u\s)" notation length ("\<^bold>|_\<^bold>|") \ \note that it's bold |\ text\A useful function of left quotient. Note that the function is sometimes undefined.\ fun left_quotient:: "'a list \ 'a list \ 'a list" ("(_\\<^sup>>)(_)" [51,51] 69) where left_quotient_def: "left_quotient u v = (THE z. u \ z = v)" text\Analogously, we define the right quotient.\ definition right_quotient :: "'a list \ 'a list \ 'a list" ("(_) (\<^sup><\_) " [51,1000] 69) where right_quotient_def[simp]: "right_quotient u v = rev (rev v\\<^sup>> rev u)" subsection \Power\ primrec list_power :: "'a list \ nat \ 'a list" (infixr "\<^sup>@" 80) where power_zero: "u\<^sup>@0 = \" | power_Suc_list: "u\<^sup>@(Suc n) = u \ u\<^sup>@n" lemma power_add_list: "u\<^sup>@a \ u\<^sup>@b = u\<^sup>@(a+b)" by (induct a) auto lemma power_Suc2_list: "u\<^sup>@(Suc n) = u\<^sup>@n \ u" by (induct n) auto lemma power_eq_if_list: "p\<^sup>@m = (if m = 0 then \ else p \ p\<^sup>@(m-1))" unfolding One_nat_def by (cases m) simp_all lemma power_mult_list: "(u\<^sup>@m)\<^sup>@n = u\<^sup>@(m*n)" by (induct n) (simp_all add: power_add_list) lemma emp_power: "\\<^sup>@n = \" by (induct n) auto lemma power_one_id: "u\<^sup>@1 = u" by auto lemma power2_list: "u\<^sup>@2 = u \ u" by (metis Suc_1 power_Suc_list power_one_id) subsection "Length and its properties" lemma eqd_pref: "(x \ y = u \ v) \ \<^bold>|x\<^bold>| \ \<^bold>|u\<^bold>| \ x \ (x\\<^sup>> u) = u \ (x\\<^sup>> u) \ v = y" by (simp add: append_eq_conv_conj) lemma eqd_equal: "\\<^bold>|x\<^bold>| = \<^bold>|u\<^bold>|; x \ y = u \ v\ \ x = u \ y = v" by simp lemma len_after_drop: "p + q \ \<^bold>|w\<^bold>| \ q \ \<^bold>|drop p w\<^bold>|" by simp lemma hd_prod: "u \ \ \ (u \ v)!0 = u!0" by (metis Nil_is_append_conv hd_append2 hd_conv_nth) lemma sing_word: "\<^bold>|b\<^bold>| = 1 \ b = [hd b]" by (metis diff_self_eq_0 length_0_conv length_tl list.expand list.sel(1) list.sel(3) not_Cons_self2 zero_neq_one) lemma nonsing_concat_len: "\<^bold>|us\<^bold>| \ 1 \ concat us \ \ \ 1 < \<^bold>|us\<^bold>|" using nat_neq_iff by fastforce lemma sing_len: "\<^bold>|[a]\<^bold>| = 1" by simp lemma pref_len: "w \p z \ \<^bold>|w\<^bold>| \ \<^bold>|z\<^bold>|" by force lemma drop_len: "\<^bold>|u \ w\<^bold>| \ \<^bold>|u \ v \ w\<^bold>|" by simp lemma take_len: "p \ \<^bold>|w\<^bold>| \ \<^bold>|take p w\<^bold>| = p" by simp subsection "Left Quotient" lemma lqI: "v = u \ z \ u\\<^sup>> v = z" by simp lemma lq_id: "u\\<^sup>> u = \" by auto lemma lq_emp: "\\\<^sup>> u = u" by auto lemma lq_pref: "u \p v \ u \ (u\\<^sup>> v) = v" by auto lemma lq_reassoc: "u \p v \ (u\\<^sup>> v)\w = u\\<^sup>> v\w" by auto lemma lq_prod: "u \p v\u \ u \p w\u \ u\\<^sup>> v\w\u = (u\\<^sup>> v\u)\(u\\<^sup>> w\u)" by (metis append.assoc lq_pref lq_reassoc) lemma lq_ne: "p \p u\p \ u \ \ \ p\\<^sup>>u\p \ \" by auto lemma rev_lq: "r \p s \ rev (r\\<^sup>>s) \p rev s" by auto lemma rev_lq': "r \p s \ rev (r\\<^sup>>s) = (rev s)\<^sup><\(rev r)" by auto lemma lq_len: "r \p s \ \<^bold>|s\<^bold>| = \<^bold>|r\<^bold>| + \<^bold>|r\\<^sup>>s\<^bold>|" by auto subsection "Right quotient" lemma rqI: "v = u \ z \ v \<^sup><\z = u" by simp lemma rq_id: "u \<^sup><\u = \" by simp lemma rq_emp: "u \<^sup><\\ = u" by simp lemma rq_suf: "v \s u \ (u \<^sup><\v ) \ v = u" by auto lemma lq_rev_rq: "u \p v \ (rev v) \<^sup><\(rev u) = rev (u\\<^sup>> v)" by simp lemma rq_rev_lq: "v \s u \ (rev v)\\<^sup>> rev u = rev (u \<^sup><\v )" by auto lemma rq_the: "v \s u \ u \<^sup><\v = (THE z. u = z \ v)" unfolding rq_suf by auto subsection "Prefix and its properties" text\Empty and nonempty prefixes.\ lemma triv_pref: "r \p r \ s" by simp lemma self_pref: "r \p r" by simp lemma pref_antisym: "r \p s \ s \p r \ r = s" by auto lemma pref_take_len: "p \p w \ p = take \<^bold>|p\<^bold>| w" by auto lemma pref_same_len: "u \p v \ \<^bold>|u\<^bold>| = \<^bold>|v\<^bold>| \ u = v" by auto lemma add_nth: "n < \<^bold>|w\<^bold>| \ (take n w) \ [w!n] \p w" using id_take_nth_drop by fastforce lemma add_nth_pref: "u \p w \ u \ w \ u \ [w!\<^bold>|u\<^bold>|] \p w" by (metis add_nth le_eq_less_or_eq pref_len pref_same_len pref_take_len) lemma nth_pref_ex: assumes "k < Suc \<^bold>|w\<^bold>|" shows "\u. (u \p w \ \<^bold>|u\<^bold>| = k)" proof- have "\<^bold>|take k w\<^bold>| = k" using assms by auto moreover have "take k w \p w" using prefI[OF sym[OF append_take_drop_id[of k w]]]. ultimately show ?thesis by blast qed lemma pref_shorter: "u \p v \ u \ v \ \<^bold>|u\<^bold>| < \<^bold>|v\<^bold>|" by auto lemma pref_trans[trans]: "u \p v \ v \p w \ u \p w" by auto lemma pref_prod_shorter: assumes "u \p z \ w" "v \p w" "\<^bold>|u\<^bold>| \ \<^bold>|z \ v\<^bold>|" shows "u \p z \ v" proof- have "u \p z \ v \ (v\\<^sup>> w)" using \u \p z \ w\ \v \p w\ by (metis append_assoc lq_pref) thus "u \p z \ v" using \\<^bold>|u\<^bold>| \ \<^bold>|z \ v\<^bold>|\ by (metis eqd_pref lq_pref prefI) qed lemma pref_index: "u \p w \ i < \<^bold>|u\<^bold>| \ u!i = w!i" by (metis nth_append prefE) lemma index_pref: assumes "\<^bold>|u\<^bold>| \ \<^bold>|w\<^bold>|" "\i < \<^bold>|u\<^bold>|. u!i = w!i" shows "u \p w" using append_eq_conv_conj[of u \ u] append_Nil2[of u] nth_take_lemma[of "\<^bold>|u\<^bold>|" u w, OF order_refl[of "\<^bold>|u\<^bold>|"] \\<^bold>|u\<^bold>| \ \<^bold>|w\<^bold>|\] \\i < \<^bold>|u\<^bold>|. u!i = w!i\ prefI[of w "take \<^bold>|u\<^bold>| w" "drop \<^bold>|u\<^bold>| w", OF sym[OF append_take_drop_id[of "\<^bold>|u\<^bold>|" w]]] by simp lemma pref_cancel: "u\v \p u\w \ v \p w" by simp lemma pref_drop: assumes "p \ \<^bold>|w\<^bold>|" "w \p w'" shows "drop p w \p drop p w'" proof- have "take p w = take p w'" using assms by auto show ?thesis using pref_cancel[of "take p w" "drop p w" "drop p w'"] unfolding append_take_drop_id[of p w] unfolding \take p w = take p w'\ append_take_drop_id[of p w'] using \w \p w'\ by blast qed lemma pref_ext: "u \p v \ z \ u \p z \ v" by simp lemma pref_prod_shorter1: assumes "u \p z\u\w" shows "u \p z\u" proof- have "u \p z \ (u \ w)" using \u \p z\u\w\ unfolding append_assoc[of z u w] . have "\<^bold>|u\<^bold>| \ \<^bold>|z \ u\<^bold>|" using length_append by simp show "u \p z\u" using pref_prod_shorter[OF \u \p z \ (u \ w)\ triv_pref \\<^bold>|u\<^bold>| \ \<^bold>|z \ u\<^bold>|\]. qed lemma pref_prod_shorter2: "u \p z \ s \ u \p s \ u \p z \ u" using pref_prod_shorter1[of u z "u\\<^sup>>s"] lq_pref[of u s] append_assoc[of z u "u\\<^sup>>s"] by presburger lemma pref_prolong: "w \p z \ r \ r \p s \ w \p z \ s" using pref_ext pref_trans by blast lemma pref_prolong': "u \p w \ z \ v \ u \p z \ u \p w \ v \ u" by (metis append_assoc lq_pref pref_prod_shorter1) lemma pref_prolong_comp: "u \p w \ z \ v \ u \ z \ u \p w \ v \ u" by (metis append_assoc pref_prolong pref_prolong') lemma pref_comm_product: "u\v \p v\u\w \ u\v = v\u" by (metis Groups.add_ac(2) eqd_equal length_append lq_pref) lemma comme_ruler: "r \ s \p w1 \ s \ r \p w2 \ w1 \ w2 \ r \ s = s \ r" by (metis lq_pref pref_comm_product pref_trans) lemma pref_share_take: "u \p v \ q \ \<^bold>|u\<^bold>| \ take q u = take q v" by auto lemma ruler_le: "\u \p x; v \p x; \<^bold>|u\<^bold>| \ \<^bold>|v\<^bold>| \ \ (u \p v)" by (metis eqd_pref prefix_def) lemma pref_pref_short_pref: "v \p u \ z \ \<^bold>|u\<^bold>| \ \<^bold>|v\<^bold>| \ u \p v" using ruler_le[of u "u \ z" v, OF triv_pref]. lemma ruler: "\ u \p x; v\p x \ \ (u \p v) \ (v \p u) " by (meson le_cases ruler_le) lemma pref_prod_longer: "u \p z \ w \ v \p w \ \<^bold>|z \ v\<^bold>| \ \<^bold>|u\<^bold>| \ z \ v \p u" using ruler_le[of "z \ v" "z \ w" u] pref_ext[of v w z] by blast lemma ruler_comp: "w \p v\z \ w \ v" using ruler by blast lemma pref_power: "u \p t\<^sup>@k \ (\ m. t\<^sup>@m \p u \ u \p t\<^sup>@m \ t)" proof (induct k) case 0 then show ?case by (metis append_self_conv2 power_zero prefI pref_antisym) next case (Suc k) then show ?case using power_Suc2_list by (metis ruler_comp) qed lemma pref_power_eq: "x \p r\<^sup>@l \ \ k z. x = r\<^sup>@k\z \ z \p r" using pref_power by (metis lq_pref pref_cancel) lemma pref_rq: "w \p (w \<^sup><\z ) \ z \s w \ z = \" unfolding right_quotient_def by auto lemma distinct_first: "w \ \ \ z \ \ \ w!0 \ z!0 \ w \ w' \ z \ z'" by (metis hd_prod) lemma last_no_split: "q \p w \ [a] \ \ q \p w \ q = w \ [a]" by (metis butlast_append butlast_snoc prefix_def) subsubsection "Prefix comparability" lemma pref_comp_len: "w \ v \ \<^bold>|v\<^bold>| \ \<^bold>|w\<^bold>| \ v \p w" by auto lemma pref_comp_len_trans: "u \ v \ \<^bold>|w\<^bold>| \ \<^bold>|u\<^bold>| \ w \p v \ w \p u" using pref_trans ruler_le by blast lemma comp_ext: "z \ w1 \ z \ w2 \ w1 \ w2" using pref_cancel pref_ext by blast lemma incomp_ext: "\ w1 \ w2 \ \ w1 \ z \ w2 \ z'" by (meson prefI pref_trans ruler) lemma mismatch_incopm: "\<^bold>|u\<^bold>| = \<^bold>|v\<^bold>| \ x \ y \ \ u \ [x] \ v \ [y]" by simp lemma rotate_comp_eq:"w \ rotate n w \ w = rotate n w" by (metis length_rotate pref_same_len) subsection "Suffix and suffix properties" lemma pref_rev_suf: "u \p v \ rev u \s rev v" by (metis lq_pref rev_append sufI) lemma pref_rev_suf': "rev u \p rev v \ u \s v" using pref_rev_suf[of "rev u" "rev v"] unfolding rev_rev_ident. lemma suf_rev_pref: "u \s v \ rev u \p rev v" by (metis lqI prefI rev_lq rq_suf) lemma suf_rev_pref': "rev u \s rev v \ u \p v" using suf_rev_pref[of "rev u" "rev v"] unfolding rev_rev_ident. lemma ruler_le_suf: assumes "u \s x" and "v \s x" and "\<^bold>|u\<^bold>| \ \<^bold>|v\<^bold>|" shows "u \s v" using ruler_le[OF suf_rev_pref[OF \u \s x\] suf_rev_pref[OF \v \s x\]] unfolding length_rev using \\<^bold>|u\<^bold>| \ \<^bold>|v\<^bold>|\ pref_rev_suf[of "rev u" "rev v"] unfolding rev_rev_ident by blast lemma suf_prod_shorter1: "u \s z \ u \ w \ u \s u \ w" by (metis pref_prod_shorter2 pref_rev_suf' rev_append sufI suf_rev_pref) lemma suf_prod_shorter2: "z \s s \ w \ z \s s \ z \s z \ w" using sufE suf_prod_shorter1 by blast lemma suf_prolong: "w \s r \ v \ r \s s \ w \s s \ v" using pref_prolong[of "rev w" "rev v" "rev r" "rev s"] by (metis pref_rev_suf' rev_append rev_rev_ident suf_rev_pref') lemma suf_prolong': assumes "u \s z \ w" and "u \ v \s z" shows "u \s u \ v \ w" proof- have "u \ v \ w \s z \ w" using \u \ v \s z\ by auto thus "u \s u \ v \ w" using ruler_le_suf[OF \u \s z \ w\ \u \ v \ w \s z \ w\] append_assoc prefI pref_len by blast qed lemma suf_prolong_comp: "u \s z \ w \ u \ v \\<^sub>s z \ u \s u \ v \ w" using suf_prolong suf_prolong' by blast lemma suf_prod_shorter3: "z \s s \ w \ u \s s \ \<^bold>|z\<^bold>| \ \<^bold>|u \ w\<^bold>| \ z \s u \ w" by (metis append.assoc rq_suf ruler_le_suf sufI) lemma suf_prod_shorter4: "w \s r \ s \ \<^bold>|w\<^bold>| \ \<^bold>|s\<^bold>| \ w \s s" using ruler_le_suf by blast lemma suf_comp: "z \s u\w \ \ z \s w \ w \s z" by (metis pref_rev_suf' rev_append ruler_comp suf_rev_pref) lemma suf_ext_left: "u \s v \ u \s w\v" by auto lemma long_pref_short_suf: "x \p w \ \<^bold>|w\<^bold>| < \<^bold>|x\<^bold>|+\<^bold>|x\<^bold>| \ w = x\s \ \<^bold>|s\<^bold>| < \<^bold>|x\<^bold>|" by simp lemma suf_trans: "u \s v \ v \s w \ u \s w" using sufE suf_ext_left by blast lemma suf_trans_eq: "u \s v \ v \s w \ u = w \ u = v" by auto subsubsection "Suffix comparability" lemma pref_suf_rev_comp: "w \ v \ (rev w) \\<^sub>s (rev v)" using pref_rev_suf by blast lemma pref_suf_rev_comp1: "(rev w) \\<^sub>s (rev v) \ w \ v" using suf_rev_pref' by blast lemma pref_suf_rev_comp2: "(rev w) \ (rev v) \ w \\<^sub>s v" using pref_rev_suf' by blast lemma pref_suf_rev_comp3: "w \\<^sub>s v \ (rev w) \ (rev v)" using suf_rev_pref by blast subsection \Longest common prefix\ fun get_longest_common_prefix :: "'a list \ 'a list \ 'a list" ("_ \\<^sub>p _" [61,62] 66) where "\ \\<^sub>p v = \" | "v \\<^sub>p \ = \" | "(a#u) \\<^sub>p (b#v) = (if a\b then \ else (a # (u \\<^sub>p v)))" lemmas lcp_simps = get_longest_common_prefix.simps lemma lcp_sym: "u \\<^sub>p v = v \\<^sub>p u" by (induct u v rule: list_induct2') auto lemma lcp_pref: "u \\<^sub>p v \p v" by (induct u v rule: list_induct2') auto lemma lcp_pref': "u \\<^sub>p v \p u" by (metis lcp_pref lcp_sym) lemma pref_lcp_pref: "w \p u \\<^sub>p v \ w \p u" using lcp_pref' pref_trans by blast lemma pref_lcp_pref': "w \p u \\<^sub>p v \ w \p v" using pref_lcp_pref lcp_sym by metis lemma lcp_self: "w \\<^sub>p w = w" by (induct w) auto lemma lcp_len: "\<^bold>|u \\<^sub>p v\<^bold>| \ \<^bold>|u\<^bold>|" by (induct u v rule: list_induct2') auto lemma lcp_eq: "\<^bold>|u \\<^sub>p v\<^bold>| = \<^bold>|u\<^bold>| \ u \p v" by (metis lcp_pref lcp_sym nth_equalityI pref_index) lemma lcp_len': "\ u \p v \ \<^bold>|u \\<^sub>p v\<^bold>| < \<^bold>|u\<^bold>|" using lcp_eq lcp_len antisym_conv2 by blast lemma lcp_ext_right: "r \p r' \ r' \p r \ (r \ u) \\<^sub>p (r' \ v) = r \\<^sub>p r'" by (induct r r' rule: list_induct2') auto lemma lcp_same_len: "\<^bold>|u\<^bold>| = \<^bold>|v\<^bold>| \ u \ v \ u \\<^sub>p v = u \ w \\<^sub>p v \ w'" using lcp_ext_right[of u v w w'] pref_same_len[of u v] pref_same_len[of v u] by presburger lemma lcp_mismatch: "\<^bold>|u \\<^sub>p v\<^bold>| < \<^bold>|u\<^bold>| \ \<^bold>|u \\<^sub>p v\<^bold>| < \<^bold>|v\<^bold>| \ u! \<^bold>|u \\<^sub>p v\<^bold>| \ v! \<^bold>|u \\<^sub>p v\<^bold>|" by (induct u v rule: list_induct2') auto lemma lcp_mismatch': "\ u \p v \ \ v \p u \ u! \<^bold>|u \\<^sub>p v\<^bold>| \ v! \<^bold>|u \\<^sub>p v\<^bold>|" by (metis lcp_len' lcp_mismatch lcp_sym) lemma lcp_ext_left: "(z \ u) \\<^sub>p (z \ v) = z \ (u \\<^sub>p v)" by (induct z) auto lemma lcp_first_letters: "u!0 \ v!0 \ u \\<^sub>p v = \" by (induct u v rule: list_induct2') auto lemma lcp_first_mismatch: "a \ b \ w \ [a] \ u \\<^sub>p w \ [b] \ v = w" by (simp add: lcp_ext_left) lemma lcp_first_mismatch': "a \ b \ u \ [a] \\<^sub>p u \ [b] = u" using lcp_first_mismatch[of a b u \ \] by simp lemma lcp_mismatch_shorter: assumes "\<^bold>|u\<^bold>| = \<^bold>|v\<^bold>|" "x \ y" shows "u \ [x] \\<^sub>p v \ [y] = u \\<^sub>p v" by (cases "u = v") (simp add: lcp_self[of v] lcp_first_mismatch'[OF \x \ y\, of v], use lcp_same_len[OF \\<^bold>|u\<^bold>| = \<^bold>|v\<^bold>|\, of "[x]" "[y]"] in auto) lemma lcp_rulers: "r \p s \ r' \p s' \ (r \p r' \ r' \p r \ r \\<^sub>p r' = s \\<^sub>p s')" by (metis lcp_ext_right prefE) lemma pref_pref_lcp: "w \p r \ w \p s \ w \p (r \\<^sub>p s)" using lcp_ext_left by auto lemma pref_pref_lcp': "w \p r \ w' \p s \ w \\<^sub>p w' \p (r \\<^sub>p s)" using pref_pref_lcp lcp_pref lcp_sym pref_trans by metis lemma lcp_distinct_hd: "hd u \ hd v \ u \\<^sub>p v = \" proof- assume "hd u \ hd v" hence "(u \ \ \ v \ \) \ hd u \ hd v \ u \\<^sub>p v = \" by (simp add: lcp_first_letters hd_conv_nth) moreover have "u = \ \ v = \ \ u \\<^sub>p v = \" using lcp_pref by auto ultimately show ?thesis using \hd u \ hd v\ by blast qed subsubsection "Relation with prefix comparability" lemma lcp_ruler: "r \ w1 \ r \ w2 \ \ w1 \ w2 \ r \p w1 \\<^sub>p w2" by (meson pref_pref_lcp pref_trans ruler) lemma comp_monotone: "w \ r \ u \p w \ u \ r" using pref_trans[of u w r] ruler[of u w r] by blast lemma comp_monotone': "w \ r \ w \\<^sub>p w' \ r" using lcp_pref' comp_monotone by blast lemma double_ruler: assumes "w \ r" and "w' \ r'" and "\ r \ r'" shows "w \\<^sub>p w' \p r \\<^sub>p r'" using comp_monotone'[OF \w' \ r'\, of w] unfolding lcp_sym[of w' w] using lcp_ruler[OF comp_monotone'[OF \w \ r\, of w'] _ \\ r \ r'\] by blast lemma pref_comp_ruler: assumes "w \ u \ [x]" and "w \ v \ [y]" and "x \ y" and "\<^bold>|u\<^bold>| = \<^bold>|v\<^bold>|" shows "w \p u \ w \p v" using double_ruler[OF \w \ u \ [x]\ \w \ v \ [y]\ mismatch_incopm[OF \\<^bold>|u\<^bold>| = \<^bold>|v\<^bold>|\ \x \ y\]] unfolding lcp_self[of w] lcp_mismatch_shorter[OF \\<^bold>|u\<^bold>| = \<^bold>|v\<^bold>|\ \x \ y\] using pref_lcp_pref pref_lcp_pref' by blast lemma rev_sing: "rev [x] = [x]" by simp lemma suf_comp_ruler: assumes "w \\<^sub>s [x] \ u" and "w \\<^sub>s [y] \ v" and "x \ y" and "\<^bold>|u\<^bold>| = \<^bold>|v\<^bold>|" shows "w \s u \ w \s v" proof- have f1: "rev w \ rev u \ [x]" using pref_suf_rev_comp3[OF \w \\<^sub>s [x] \ u\] unfolding rev_append[of "[x]" u] rev_sing[of x]. have f2: "rev w \ rev v \ [y]" using pref_suf_rev_comp3[OF \w \\<^sub>s [y] \ v\] unfolding rev_append[of "[y]" v] rev_sing[of y]. have f3: "\<^bold>|rev u\<^bold>| = \<^bold>|rev v\<^bold>|" using \\<^bold>|u\<^bold>| = \<^bold>|v\<^bold>|\ length_rev by simp show ?thesis using pref_comp_ruler[OF f1 f2 \x \ y\ f3] pref_rev_suf' by blast qed subsection "Factor and factor properties" lemma fac_pref: "u \f v \ \ p. p\u \p v" by simp lemma fac_suf: "u \f v \ \ s. u \ s \s v" by auto lemma fac_suf': "u \ s \s v \ u \f v" by auto lemma fac_pref_suf: "u \f v \ \ p. p \p v \ u \s p" by (meson fac_pref sufI) lemma fac_pref_suf': "r \p v \ u \s r \ u \f v" using fac_pref sufE by blast subsection "Various lemmas on lists" lemma cancel: "u\v = u\w \ v = w" by simp lemma cancel_right: "v\u = w\u \ v = w" by simp lemma bij_lists: "bij_betw f X Y \ bij_betw (map f) (lists X) (lists Y)" proof- assume "bij_betw f X Y" hence "inj_on f X" by (simp add: bij_betw_def) have "\ x y. x \ lists X \ y \ lists X \ (set x \ set y) \ X" by blast hence "\ x y. x \ lists X \ y \ lists X \ inj_on f (set x \ set y)" by (meson \inj_on f X\ subset_inj_on) hence "\ x y. x \ lists X \ y \ lists X \ map f x = map f y \ x = y" by (simp add: inj_on_map_eq_map) hence "inj_on (map f) (lists X)" by (simp add: inj_on_def) thus ?thesis using \bij_betw f X Y\ bij_betw_def lists_image by metis qed lemma emp_concat_emp: "us \ lists S\<^sub>+ \ concat us = \ \ us = \" using DiffD2 by auto lemma concat_sing: "s = [hd s] \ concat s = hd s" using append.right_neutral concat.simps(1) concat.simps(2)[of "hd s" \] by auto lemma concat_sing_pow: "concat ([a]\<^sup>@k) = a\<^sup>@k" by (induct k, simp, simp) lemma concat_len_one: assumes "\<^bold>|us\<^bold>| = 1" shows "concat us = hd us" using concat_sing[OF sing_word[OF \\<^bold>|us\<^bold>| = 1\]]. lemma overlap: "p\x = x\s \ \<^bold>|p\<^bold>| \ \<^bold>|x\<^bold>| \ (p\\<^sup>> x) \p x \ (p\\<^sup>> x) \s x" using eqd_pref[of p x x s] prefI[of x "(p\\<^sup>> x)" s] sufI[of x p "(p\\<^sup>> x)" ] by auto lemma hd_word: "a#ws = [a] \ ws" by simp lemma hd_word': "w \ \ \ w = [hd w] \ tl w" by simp lemma hd_pref: "w \ \ \ [hd w] \p w" using hd_word' by blast lemma hd_pref': "w \ \ \ [w!0] \p w" using add_nth by fastforce lemma unique_letter_word: "(\ c. c \ set w \ c = a) \ \ k. w = [a]\<^sup>@k" proof (induct w) case Nil then show ?case by (metis power_zero) next case (Cons b w) then show ?case proof- obtain k where "w = [a]\<^sup>@k" using Cons.hyps Cons.prems by auto hence "b#w = [a]\<^sup>@Suc k" by (simp add: \w = (a # \)\<^sup>@k\ Cons.prems) thus ?thesis by blast qed qed lemma sub_lists_mono: "A \ B \ x \ lists A \ x \ lists B" by auto lemma lists_hd: "us \n lists Q \ hd us \ Q" by fastforce lemma replicate_in_lists: "replicate k z \ lists {z}" by (induction k) auto lemma tl_lists: "us \ lists A \ tl us \ lists A" using list.sel(2) list.sel(3) lists.cases[of us A "tl us \ lists A"] by auto subsubsection "Lemmas on empty lists/words in lists" lemma del_empty_concat: "concat us = concat (filter (\x. x \ \) us)" by (induct us) simp+ lemmas concat_morph = concat_append lemma lists_drop_emp: "us \ lists C\<^sub>+ \ us \ lists C" by blast lemma lists_drop_emp': "us \ lists C \ (filter (\x. x \ \) us) \ lists C\<^sub>+" by (simp add: in_lists_conv_set) subsection "Powers and their properties" lemma power_is_concat_replicate: "u\<^sup>@n = concat (replicate n u) " by (induct n) auto text \More lemmas on powers\ lemma power_slide: "u \ (v \ u)\<^sup>@n \ v = (u \ v)\<^sup>@(Suc n)" by (induct n) simp+ lemma pop_power_one: "m \ 0 \ r\<^sup>@m = r \ r\<^sup>@(m-1)" by (simp add: power_eq_if_list) lemma pop_power: "m \ k \ u\<^sup>@k = u\<^sup>@m \ u\<^sup>@(k-m)" using le_add_diff_inverse power_add_list by metis lemma pop_power_cancel: "u\<^sup>@k \ v = u\<^sup>@m \ w \ m \ k \ u\<^sup>@(k-m) \ v = w" using pop_power cancel[of "u\<^sup>@m" "u\<^sup>@(k-m) \ v" w] by (metis append_assoc) lemma powers_comm: "t\<^sup>@k \ t\<^sup>@m = t\<^sup>@m \ t\<^sup>@k" by (metis add.commute power_add_list) lemma comm_add_exp: "r \ u = u \ r \ r\<^sup>@m \ u = u \ r\<^sup>@m" by (induct m) auto lemma comm_add_exps: "r \ u = u \ r \ r\<^sup>@m \ u\<^sup>@k = u\<^sup>@k \ r\<^sup>@m" by (metis comm_add_exp) lemma powers_pref: "\ t \ \; m \ 0; m \ k \ \ t\<^sup>@m \np t\<^sup>@k" using power_add_list[of t m "k-m"] by (metis append_is_Nil_conv nemp_prefI pop_power power_eq_if_list) lemma rev_power: "rev (x\<^sup>@m) = (rev x)\<^sup>@m" proof (induct m, simp) case (Suc m) then show ?case by (simp add: comm_add_exp) qed lemmas add_one_exp = power_Suc2_list lemma power_len: "\<^bold>|u\<^sup>@k\<^bold>| = k * \<^bold>|u\<^bold>|" by (induct k) simp+ lemma eq_powers: "u\<^sup>@k = u\<^sup>@m \ u \ \ \ k = m" using power_len by (metis length_0_conv mult_cancel2) lemma sing_power_empty: "[a]\<^sup>@n = \ \ n = 0" by (simp add: eq_powers) lemma long_power: "r \ \ \ \<^bold>|x\<^bold>|\\<^bold>|r\<^sup>@\<^bold>|x\<^bold>|\<^bold>|" using power_len by (metis eq_iff le_square length_0_conv linear mult_cancel2 mult_le_mono2 nat_mult_1 nat_mult_1_right) lemma long_power_ex: "r \ \ \ \ n. m \ \<^bold>|r\<^sup>@n\<^bold>|" by (metis Ex_list_of_length long_power) lemma longer_power: "r \ \ \ \<^bold>|x\<^bold>| \ m \ \<^bold>|x\<^bold>|\\<^bold>|r\<^sup>@m\<^bold>|" by (metis Ex_list_of_length long_power order.trans) lemma pref_power_ext: "x \p r\<^sup>@k \ x \p r\<^sup>@Suc k" using add_one_exp pref_trans prefix_def by blast lemma pref_power_root_ext: "x \p r\<^sup>@k \ r \ x \p r\<^sup>@Suc k" by simp lemma pref_power_exps_less: "x \p r\<^sup>@k \ \ x \p r\<^sup>@l \ l < k" by (metis leI pop_power pref_trans prefix_def) lemma pref_exps_power: "k \ l \ r\<^sup>@k \p r\<^sup>@l" by (meson leD pref_power_exps_less self_pref) lemma pref_sing_exp: "[a]\<^sup>@m \p [a]\<^sup>@n \ m \ n" by (metis eq_powers le_cases not_Cons_self2 pref_antisym pref_exps_power) lemma comm_common_power: assumes "r \ u = u \ r" shows "r\<^sup>@\<^bold>|u\<^bold>| = u\<^sup>@\<^bold>|r\<^bold>|" using mult.commute[of "\<^bold>|u\<^bold>|" "\<^bold>|r\<^bold>|"] power_len[of r "\<^bold>|u\<^bold>|"] power_len[of u "\<^bold>|r\<^bold>|"] eqd_equal[OF _ comm_add_exps[OF assms]] by auto lemma one_generated_list_power: "u \ lists {x} \ \k. concat u = x\<^sup>@k" proof(induction u) case Nil then show ?case by (metis concat.simps(1) power_zero) next case (Cons a u) then show ?case by (metis Cons_in_lists_iff concat.simps(2) singletonD power_Suc_list) qed lemma power_lists: "0 < k \ u\<^sup>@k \ lists B\<^sub>+ \ u \ lists B\<^sub>+" by (simp add: power_eq_if_list) lemma concat_morph_power: "xs \ lists B \ xs = ts\<^sup>@k \ concat ts\<^sup>@k = concat xs" by (induct k arbitrary: xs ts) simp+ lemma pref_not_idem: "z \ \ \ z \ x \ z \ x\<^sup>@k \ x" by (metis append_self_conv2 power_eq_if_list prefI pref_antisym pref_prod_shorter1 self_append_conv self_pref) lemma per_exp_pref: "u \p r \ u \ u \p r\<^sup>@k \ u" proof(induct k) case (Suc k) then show ?case by (metis add_one_exp pref_prolong_comp) qed simp lemma per_exp_suf: "z \s z \ r \ z \s z \ r\<^sup>@j" by (metis per_exp_pref pref_rev_suf' rev_append rev_power suf_rev_pref) lemma hd_sing_power: "k \ 0 \ hd ([a]\<^sup>@k) = a" by (induction k) simp+ lemma root_pref_cancel: assumes "t\<^sup>@m \ y = t\<^sup>@k" shows "y = t\<^sup>@(k - m)" using lqI[of "t\<^sup>@k" "t\<^sup>@m" "t\<^sup>@(k-m)"] unfolding lqI[OF sym[OF \t\<^sup>@m \ y = t\<^sup>@k\]] using nat_le_linear[of m k] pop_power[of m k t] diff_is_0_eq[of k m] append.right_neutral[of "t\<^sup>@k"] power_zero[of t] pref_antisym[of "t\<^sup>@m" "t\<^sup>@k", OF prefI[OF sym[OF \t\<^sup>@m \ y = t\<^sup>@k\]] pref_exps_power[of k m t]] by presburger subsection "Total morphisms" locale morphism = fixes f assumes morph: "f (u \ v) = f u \ f v" begin lemma empty_to_empty: "f \ = \" by (metis morph self_append_conv2) lemma power_morph: "f (x\<^sup>@k) = (f x)\<^sup>@k" by (induction k) (simp add: morph empty_to_empty)+ lemma pop_head: "f (a#u) = f [a] \ f u" by (metis hd_word morph) lemma pref_mono: "u \p v \ f u \p f v" using morph by auto lemma morph_concat_map: "f x = concat (map (\ x. f [x]) x)" proof (induction x, simp add: empty_to_empty) case (Cons a x) then show ?case unfolding pop_head[of a x] by auto qed end lemma morph_compose: "morphism f \ morphism g \ morphism (f \ g)" by (simp add: morphism_def) subsection "Arithmetical hints" lemma zero_diff_eq: "i \ j \(0::nat) = j - i \ j = i" by simp lemma nat_prod_le: "n \ (0 :: nat) \ m \ 0 \ m*n \ k \ n \ k" using le_trans[of n "m*n" k] by simp subsection "Conjugation" lemma conjug_power: "x \ z = z \ y \ x\<^sup>@k \ z = z \ y\<^sup>@k" by (induct k) fastforce+ lemma conjug_rq: "x \ z = z \ y \ x = z \ y \<^sup><\z" using rqI by metis lemma conjug_lq: "x \ z = z \ y \ y = z\\<^sup>> x \ z" by simp lemma lq_conjug: "z \p x \ z \ y = z\\<^sup>> x \ z \ x \ z = z \ y" by auto lemma rq_conjug: "z \s z \ y \ x = z \ y \<^sup><\z \ x \ z = z \ y" using rq_suf by blast lemma lq_conjug_power: "p \p x \ p \ p\\<^sup>> x\<^sup>@k \ p = (p\\<^sup>> x \ p)\<^sup>@k" using conjug_power[of x p "p\\<^sup>> x \ p"] lqI lq_conjug by metis lemma rq_conjug_power: "p \s p \ x \ p \ x\<^sup>@k \<^sup><\p = (p \ x \<^sup><\p)\<^sup>@k" using conjug_power[of "p \ x \<^sup><\p" p x] by (metis rqI rq_suf) lemma conjug_empty_pref: "p \s p \ u \ p \ u \<^sup><\p = \ \ u = \" by (metis append_self_conv append_self_conv2 rq_suf) lemma conjug_empty_suf: "p \p u \ p \ p\\<^sup>> u \ p = \ \ u = \" using lq_ne by blast lemma lq_rq_conj: "p \p r\p \ r = (p\(p\\<^sup>> r \ p))\<^sup><\p" by (metis lq_pref rqI) lemma rq_lq_conjugate: "p \s p\r \ r = p\\<^sup>>(((p \ r) \<^sup><\p )\p)" by (metis lqI rq_suf) section \Root\ definition root :: "'a list \ 'a list \ bool" ("_ \ _*" [51,51] 60 ) where "x \ r* = (\ k. x = r\<^sup>@k)" text\Root can be empty, and the empty word has all roots.\ lemma empty_all_roots: "\ \ r*" by (metis root_def power_zero) lemma take_root: "k \ 0 \ r = take (length r) (r\<^sup>@k)" by (simp add: power_eq_if_list) lemma root_nemp: "u \ \ \ u \ r* \ r \ \" unfolding root_def using emp_power by auto lemma root_shorter: "u \ \ \ u \ r* \ u \ r \ \<^bold>|r\<^bold>| < \<^bold>|u\<^bold>|" by (metis root_def leI take_all take_root power_zero) lemma root_trans[trans]: "\v \ u*; u \ t*\ \ v \ t*" by (metis root_def power_mult_list) lemma root_len: "u \ q* \ \k. \<^bold>|u\<^bold>| = k*\<^bold>|q\<^bold>|" unfolding root_def using power_len by auto lemma root_len_dvd: "u \ t* \ \<^bold>|t\<^bold>| dvd \<^bold>|u\<^bold>|" using root_len root_def by fastforce lemma common_root_len_gcd: "u \ t* \ v \ t* \ \<^bold>|t\<^bold>| dvd ( gcd \<^bold>|u\<^bold>| \<^bold>|v\<^bold>| )" by (simp add: root_len_dvd) lemma add_root: "w \ z* \ z \ w \ z*" using root_def by (metis power_Suc_list ) lemma add_roots: "w \ z* \ w' \ z* \ w \ w' \ z*" using root_def by (metis power_add_list) lemma concat_sing_list: "ws \ lists {z} \ concat ws \ z*" proof (induct ws) case Nil then show ?case using empty_all_roots by auto next case (Cons a ws) then show ?case using add_root by auto qed lemma root_pref_cancel': "\ x\y \ t* ; x \ t* \ \ y \ t*" unfolding root_def using root_pref_cancel by fastforce section Commutation text\The solution of the easiest nontrivial word equation, @{term "x \ y = y \ x"}, is in fact already contained in List.thy as the fact @{thm comm_append_are_replicate}.\ theorem comm: "x \ y = y \ x \ \ t m k. x = t\<^sup>@k \ y = t\<^sup>@m" using comm_append_are_replicate[of x y] power_is_concat_replicate power_zero power_one_id by metis theorem comm_root0: "x \ y = y \ x \ \ t. x \ t* \ y \ t*" unfolding root_def using comm by auto theorem comm_root1: "(\ t. (x \ t*) \ (y \ t*)) \ x \ y = y \ x" unfolding root_def using powers_comm by auto corollary comm_root: "x \ y = y \ x \ (\ t. x \ t* \ y \ t*)" using comm_root0 comm_root1 by blast section \Periods\ subsection "Period root" definition period_root :: "'a list \ 'a list \ bool" ("_ \p _\<^sup>\" [51,51] 60 ) where period_root_def[simp]: "period_root x r = (x \p r \ x \ r \ \)" lemma per_rootI[simp,intro]: "x \p r \ x \ r \ \ \ x \p r\<^sup>\" by simp text \Empty word has no period, and is not a periodic root.\ lemma emp_any_per: "r \ \ \ (\ \p r\<^sup>\ )" by simp lemma emp_not_per: "\ (x \p \\<^sup>\)" by simp text \Any nonempty word is its own periodic root.\ lemma root_self: "w \ \ \ w \p (take (length w) w)\<^sup>\" by simp text\"Short roots are prefixes"\ lemma root_is_take: "length r \ length w \ w \p r\<^sup>\ \ r = take (length r) w" by (simp add: append_eq_conv_conj) text\An important equivalent characterization of a periodic root, which motivates the notation.\ lemma per_exp: "u \p r\<^sup>\ \ u \p r\<^sup>@k \ u" proof(induct k) case (Suc k) then show ?case by (meson per_exp_pref period_root_def) qed simp lemma per_add_exp: "\ u \p r\<^sup>\; m \ 0 \ \ u \p (r\<^sup>@m)\<^sup>\" by (metis eq_powers per_exp_pref period_root_def power_zero) lemma per_pref_ex: "x \p r\<^sup>\ \ \ n. x \p r\<^sup>@Suc n" using long_power_ex[of r "\<^bold>|x\<^bold>|"] per_exp by (metis emp_not_per prefI pref_comp_len pref_power_ext ruler) theorem per_pref: "x \p r\<^sup>\ \ (r \ \ \ (\ k. x \p r\<^sup>@k))" by (metis per_pref_ex period_root_def power_Suc_list pref_power_ext pref_prod_shorter2) lemma per_eq: "x \p r\<^sup>\ \ (r \ \ \ (\ k z. x = r\<^sup>@k\z \ z \p r ))" proof show "x \p r\<^sup>\ \r \ \ \ (\ k z. x = r\<^sup>@k\z \ z \p r )" using pref_power_eq by (metis period_root_def per_pref) show "r \ \ \ (\k z. x = r\<^sup>@k \ z \ z \p r) \ x \p r\<^sup>\" by (metis add_one_exp append_assoc per_pref prefix_def) qed text\The previous theorem allows to prove some basic relations between powers, periods and commutation\ lemma per_drop_exp: "u \p (r\<^sup>@m)\<^sup>\ \ u \p r\<^sup>\" using per_pref power_mult_list by (metis length_0_conv mult_0_right power_len) lemma per_drop_exp': "i \ 0 \ p \p e\<^sup>@i \ p \ p \p e \ p" by (metis period_root_def eq_powers per_drop_exp power_zero) lemma per_drop_exp_rev: "i \ 0 \ p \s p \ e\<^sup>@i \ p \s p \ e" using per_drop_exp' [of i "rev p" "rev e"] rev_power by (metis pref_rev_suf' rev_append suf_rev_pref) corollary comm_drop_exp: "\ m \ 0; r\<^sup>@m \ u = u \ r\<^sup>@m \ \ r \ u = u \ r" proof- assume "m \ 0" "r\<^sup>@m \ u = u \ r\<^sup>@m" { assume "r \ \" "u \ \" hence "u\r \p u\r\<^sup>@m" using pop_power_one \m \ 0\ by auto hence "u\r \p r\<^sup>@m\(u\r)" using \r\<^sup>@m \ u = u \ r\<^sup>@m\ by (metis append_assoc prefix_def) hence "u\r \p r\(u\r)" using per_drop_exp[of "u\r" r m] using \r \ \\ \u \ r \p u \ r\<^sup>@m\ by auto hence "r \ u = u \ r" using pref_comm_product by fastforce } thus "r \ u = u \ r" by fastforce qed corollary powers_comm_comm: "\x\<^sup>@j = y\<^sup>@k; j \ 0\ \ x\y = y\x" by (metis append_Nil append_Nil2 comm_drop_exp power_zero) corollary comm_powers_roots: "\ m \ 0; k \ 0 \ \ u \ v = v \ u \ u\<^sup>@m \ v\<^sup>@k = v\<^sup>@k \ u\<^sup>@m" using comm_drop_exp comm_add_exp by metis theorem per_all_exps: "\ m \ 0; k \ 0 \ \ (u \p (r\<^sup>@m)\<^sup>\) \ (u \p (r\<^sup>@k)\<^sup>\)" using per_add_exp per_drop_exp by blast text\Another equivalent characterization of "short" periods.\ theorem per_shift: "\ n < length w; n \ 0 \ \ w \p (take n w)\<^sup>\ \ drop n w \p w" proof show "\ n < length w; n \ 0 \ \ w \p (take n w)\<^sup>\ \ drop n w \p w" using pref_drop[of n w "take n w \ w"] period_root_def[of w "take n w"] by (metis append_take_drop_id pref_cancel) have aux:"n < length w \ n \ 0 \ take n w \ \" by auto have "n < length w \ n \ 0 \ drop n w \p w \ w \p take n w \ w" by (metis append_take_drop_id pref_ext) thus "n < length w \ n \ 0 \ drop n w \p w \ w \p (take n w)\<^sup>\" using period_root_def[of w "take n w"] aux by blast qed text\Some auxiliary lemmas\ lemma take_per: "\ length r < length w; w \p r\<^sup>\\ \ r = take (length r) w" by (simp add: append_eq_conv_conj) lemma drop_per: assumes "p < \<^bold>|w\<^bold>|" "w \p (take p w)\<^sup>\" shows "(drop p w) \p (take p w)\<^sup>\" by (metis period_root_def append_take_drop_id \w \p (take p w)\<^sup>\\ pref_cancel) lemma drop_per_pref: "w \p u\<^sup>\ \ drop \<^bold>|u\<^bold>| w \p w" by (metis period_root_def append_eq_conv_conj drop_append prefix_def) lemma drop_per': assumes as: "length r < length w" "w \p r\<^sup>\" shows "(drop (length r) w) \p r\<^sup>\" using drop_per take_per as by metis lemma per_root_trans: "w \p u\<^sup>\ \ u \ t* \ w \p t\<^sup>\" by (metis root_def per_drop_exp) text\Note that @{term "w \p u\<^sup>\ \ u \p t\<^sup>\ \ w \p t\<^sup>\"} does not hold. \ lemma per_root_same_prefix:"w \p r\<^sup>\ \ w' \p r\<^sup>\ \ w \p w' \ w' \p w" by (meson per_exp per_pref pref_trans prefix_def ruler) lemma take_after_drop: "\<^bold>|u\<^bold>| + q \ \<^bold>|w\<^bold>| \ w \p u\<^sup>\ \ take q (drop \<^bold>|u\<^bold>| w) = take q w" using pref_share_take[OF drop_per_pref[of w u] len_after_drop[of "\<^bold>|u\<^bold>|" q w]]. lemma two_pers: assumes "w \p u\<^sup>\" "w \p v\<^sup>\" "\<^bold>|u\<^bold>|+\<^bold>|v\<^bold>| \ \<^bold>|w\<^bold>|" shows "u\v = v\u" proof- have t1: "take \<^bold>|u\<^bold>| w = u" using root_is_take \w \p u\<^sup>\\ \\<^bold>|u\<^bold>|+\<^bold>|v\<^bold>| \ \<^bold>|w\<^bold>|\ by (metis add_leD1) have t2: "take \<^bold>|v\<^bold>| w = v" using root_is_take \w \p v\<^sup>\\ \\<^bold>|u\<^bold>|+\<^bold>|v\<^bold>| \ \<^bold>|w\<^bold>|\ by (metis add_leD1 add.commute) have t3: "take \<^bold>|v\<^bold>| (drop \<^bold>|u\<^bold>| w) = v" using take_after_drop[OF \\<^bold>|u\<^bold>|+\<^bold>|v\<^bold>| \ \<^bold>|w\<^bold>|\ \w \p u\<^sup>\\] unfolding t2. have t4: "take \<^bold>|u\<^bold>| (drop \<^bold>|v\<^bold>| w) = u" using take_after_drop[OF _ \w \p v\<^sup>\\, of "\<^bold>|u\<^bold>|"] \\<^bold>|u\<^bold>|+\<^bold>|v\<^bold>| \ \<^bold>|w\<^bold>|\ unfolding t1 by simp show ?thesis using take_add[of "\<^bold>|u\<^bold>|" "\<^bold>|v\<^bold>|" w] take_add[of "\<^bold>|v\<^bold>|" "\<^bold>|u\<^bold>|" w] unfolding t1 t2 t3 t4 add.commute[of "\<^bold>|v\<^bold>|" "\<^bold>|u\<^bold>|"] by auto qed lemma "x \ \ \ x\z = z\y \ z \p x\<^sup>\" by blast lemma "z \p x\<^sup>\ \ \y. x\z = z\y" by simp subsection "Period - numeric" text\Numeric definition of a period\ definition periodN :: "'a list \ nat \ bool" where periodN_def[simp]: "periodN w n = w \p (take n w)\<^sup>\" text\The numeric definition respects the following convention about empty words and empty periods.\ lemma emp_no_periodN: "\ periodN \ n" by simp lemma zero_not_per: "\ periodN w 0" by simp text\A nonempty word has all "long" periods\ lemma all_long_pers: "\ w \ \; length w \ n \ \ periodN w n" by simp lemma per_nemp: "periodN w n \ w \ \" using emp_no_periodN by blast lemma per_positive: "periodN w n \ n \ 0" by (meson zero_not_per) text\The numeric definition is equivalent to the definition by a root for all "short" roots.\ lemma periodN_is_root: " w \ \ \ periodN w n \ (w \p (take n w)\<^sup>\)" using root_self by force theorem periodN_pref: assumes "w \ \" shows "periodN w n \ (\k r. w \np r\<^sup>@k \ \<^bold>|r\<^bold>| = n)" proof assume "periodN w n" consider (short) "\<^bold>|w\<^bold>| \ n" | (long) "n < \<^bold>|w\<^bold>|" by linarith then show "(\k r. w \np r\<^sup>@k \ \<^bold>|r\<^bold>| = n)" proof(cases) case short then show ?thesis proof- obtain z where "\<^bold>|w \ z\<^bold>| = n" using Ex_list_of_length[of "n - \<^bold>|w\<^bold>|"] length_append by (metis add_diff_inverse_nat not_le short) thus ?thesis using assms power_one_id by blast qed next case long then show ?thesis using \periodN w n\ per_pref[of w "take n w"] by (meson assms leD nat_le_linear nemp_prefI_pref periodN_def take_len) qed next show "\k r. w \np r\<^sup>@k \ \<^bold>|r\<^bold>| = n \ periodN w n" using \w \ \\ periodN_def per_pref by (metis emp_power nonempty_prefix_def power_Suc_list pref_len pref_power_ext pref_take_len root_self ruler_comp self_pref take_all) qed lemma take_several_pers: assumes "periodN w n" and "m*n \ \<^bold>|w\<^bold>|" shows "(take n w)\<^sup>@m = take (m*n) w" proof- {assume "m \ 0" have "n \ 0" using \periodN w n\ by auto hence "\<^bold>|(take n w)\<^sup>@m\<^bold>| = m*n" using power_len[of "take n w" m] take_len[OF nat_prod_le[OF \n \ 0\ \m \ 0\ \m*n \ \<^bold>|w\<^bold>|\]] by metis have "(take n w)\<^sup>@m \p w" using \periodN w n\ unfolding periodN_def using per_exp[of w "take n w" m] \\<^bold>|take n w\<^sup>@m\<^bold>| = m * n\ \m * n \ \<^bold>|w\<^bold>|\ ruler_le[of "take n w\<^sup>@m" "take n w\<^sup>@m \ w" w, OF triv_pref] by linarith have ?thesis using \\<^bold>|take n w\<^sup>@m\<^bold>| = m * n\ pref_take_len[OF \take n w\<^sup>@m \p w\] by metis } note nemp = this {assume "m = 0" hence "take (n*m) w = \" and "(take n w)\<^sup>@m = \" by simp+ } thus ?thesis using nemp by fastforce qed lemma per_mult: "\ periodN w n ; m \ 0 \ \ periodN w (m*n)" using take_several_pers by (metis all_long_pers emp_no_periodN nat_le_linear periodN_def per_add_exp) lemma periodN_root: "w \ \ \ w \p r\<^sup>\ \ periodN w \<^bold>|r\<^bold>|" by (metis all_long_pers not_less periodN_def take_per) theorem two_periodsN: assumes "periodN w p" "periodN w q" "p + q \ \<^bold>|w\<^bold>|" shows "periodN w (gcd p q)" proof- obtain t where "t \ \" "take p w \ t*" "take q w \ t*" using two_pers[of w "take p w" "take q w"] periodN_def comm_root[of "take p w" "take q w"] \periodN w p\ \periodN w q\ \p + q \ \<^bold>|w\<^bold>|\ take_len by (metis add_leD1 add_leD2 period_root_def root_nemp) hence "w \p t\<^sup>\" using \periodN w p\ periodN_def per_root_trans by blast have "periodN w \<^bold>|t\<^bold>|" using \w \p t\<^sup>\\ periodN_root \periodN w p\ per_nemp by blast have "\<^bold>|t\<^bold>| dvd (gcd p q)" using \take p w \ t*\ \take q w \ t*\ root_len_dvd by (metis add_leD1 add_leD2 \p + q \ \<^bold>|w\<^bold>|\ take_len gcd_nat.boundedI) thus ?thesis using \periodN w \<^bold>|t\<^bold>|\ per_mult by (metis \periodN w p\ dvdE gcd_eq_0_iff mult.commute mult_not_zero) qed lemma index_power_mod: "w = r\<^sup>@k \ \ i < \<^bold>|w\<^bold>|. w!i = r!(i mod \<^bold>|r\<^bold>| )" proof(induction k arbitrary:w) case 0 then show ?case by auto next case (Suc k) have "w = r\r\<^sup>@k" by (simp add: Suc.prems power_commutes) hence "\<^bold>|r\<^sup>@k\<^bold>|+\<^bold>|r\<^bold>| = \<^bold>|w\<^bold>|" by simp { fix i assume "\<^bold>|r\<^bold>| \ i" "i < \<^bold>|w\<^bold>|" hence q: "w!i = (r\<^sup>@k)!(i - \<^bold>|r\<^bold>| )" by (simp add: \w = r \ r\<^sup>@k\ nth_append) have "(r\<^sup>@k)!(i - \<^bold>|r\<^bold>| ) = r!(i mod \<^bold>|r\<^bold>| )" by (simp add: Suc.IH \i < \<^bold>|w\<^bold>|\ \\<^bold>|r\<^sup>@k\<^bold>| + \<^bold>|r\<^bold>| = \<^bold>|w\<^bold>|\ \\<^bold>|r\<^bold>| \ i\ le_mod_geq less_diff_conv2) hence "(w)!i = r!(i mod \<^bold>|r\<^bold>| )" using q by metis } then show ?case by (simp add: Suc.prems nth_append) qed lemma index_mod_per_root: assumes "r \ \" and i: "\ i < \<^bold>|w\<^bold>|. w!i = r!(i mod \<^bold>|r\<^bold>|)" shows "w \p r\<^sup>\" proof- have "\<^bold>|w\<^bold>| \ \<^bold>|r \ w\<^bold>|" by auto {fix i assume "i < \<^bold>|w\<^bold>|" { assume "\<^bold>|w\<^bold>| \ \<^bold>|r\<^bold>|" hence "w!i = (r \ w) ! i" by (metis \i < \<^bold>|w\<^bold>|\ dual_order.strict_trans1 i mod_less nth_append) } { assume "\<^bold>|r\<^bold>| \ \<^bold>|w\<^bold>|" hence "w!i = (r \ w) ! i" by (simp add: \i < \<^bold>|w\<^bold>|\ i less_imp_diff_less mod_if nth_append) } hence "w!i = (r \ w) ! i" using \\<^bold>|w\<^bold>| \ \<^bold>|r\<^bold>| \ w ! i = (r \ w) ! i\ by linarith} thus "w \p r\<^sup>\" using index_pref[OF \\<^bold>|w\<^bold>| \ \<^bold>|r \ w\<^bold>|\] period_root_def \r \ \\ by blast qed lemma index_pref_power_mod: "w \p r\<^sup>@k \ \ i < \<^bold>|w\<^bold>|. w!i = r!(i mod \<^bold>|r\<^bold>| )" by (metis (no_types, hide_lams) add.commute index_power_mod leI length_append less_le_trans not_add_less2 pref_index prefix_def) lemma index_per_root_mod: "w \p r\<^sup>\ \ \ i < \<^bold>|w\<^bold>|. w!i = r!(i mod \<^bold>|r\<^bold>|)" using index_pref_power_mod per_pref by metis lemma per_factor: "y \ \ \ v \ \ \ u\v\w = y\<^sup>@k \ periodN v \<^bold>|y\<^bold>|" proof- assume "y\\" " u\v\w=y\<^sup>@k" "v\\" have "u \p y\<^sup>@k" using \u\v\w=y\<^sup>@k\ unfolding append_assoc[of u v w] using prefI[of "y\<^sup>@k" u "v\w"] by auto hence "v\w = u\\<^sup>>(y\<^sup>@k)" using \u \ v \ w = y\<^sup>@k\ by auto have "u \p y\<^sup>\" using \u \p y\<^sup>@k\ \y \ \\ per_pref by blast hence "u\\<^sup>>y\<^sup>@k\u=(u\\<^sup>>(y\u))\<^sup>@k" using lq_conjug_power by auto hence "v \p (u\\<^sup>>(y\u))\<^sup>@k" by (metis \u \ v \ w = y\<^sup>@k\ append.assoc lqI triv_pref) have "\<^bold>|u\\<^sup>>(y\u)\<^bold>| = \<^bold>|y\<^bold>|" using period_root_def[of u y] \u \p y\<^sup>\\ lq_pref[of u "y \ u"] length_append[of y u] length_append[of u "u\\<^sup>> y \ u"] by presburger thus ?thesis using \v \p (u\\<^sup>>(y\u))\<^sup>@k\ using \v \ \\ periodN_pref by blast qed lemma root_divisor: "periodN w k \ k dvd \<^bold>|w\<^bold>| \ w \ (take k w)*" proof- assume "periodN w k" "k dvd \<^bold>|w\<^bold>|" hence "w = (take k w)\<^sup>@(\<^bold>|w\<^bold>| div k)" by (simp add: take_several_pers) then show ?thesis using root_def by blast qed lemma per_pref': "u \ \ \ periodN v k \ u \p v \ periodN u k" proof- assume "u \ \" "periodN v k" " u\p v" { assume "k \ \<^bold>|u\<^bold>|" have "take k v = take k u" using pref_share_take[OF \u \p v\ \k \ \<^bold>|u\<^bold>|\] by auto hence "take k v \ \" using \periodN v k\ by auto hence "take k u \ \" by (simp add: \take k v = take k u\) have "u \p take k u \ v" using \periodN v k\ unfolding periodN_def period_root_def \take k v = take k u\ using pref_trans[OF \u \p v\, of "take k u \ v"] by blast hence "u \p take k u \ u" using \u \p v\ pref_prod_shorter2 by blast hence ?thesis using \take k u \ \\ periodN_def by blast } thus ?thesis using \u \ \\ all_long_pers nat_le_linear by blast qed subsection "Period: overview" notepad begin fix w r::"'a list" fix n::nat assume "w \ \" "r \ \" "n > 0" have "\ w \p \\<^sup>\" by simp have "\ \ \p \\<^sup>\" by simp have "\ \p r\<^sup>\" by (simp add: \r \ \\) have "\ periodN w 0" by simp have "\ periodN \ 0" by simp have "\ periodN \ n" by simp end subsection \Singleton\ lemma pref_sing_power: "w \p [a]\<^sup>@m \ w \ [a]*" proof(induct w arbitrary: m) case Nil then show ?case using empty_all_roots by auto next case (Cons x w) then show ?case proof- have "m \ 0" using power_zero[of "[a]"] \(x # w) \p [a]\<^sup>@m\ prefix_def by fastforce hence "x = a" using \(x # w) \p [a]\<^sup>@m\ hd_word[of x w] hd_sing_power[OF \m\0\, of a] by (metis hd_append2 list.discI list.sel(1) prefix_def) hence "w \p [a]\<^sup>@m" using \(x # w) \p [a]\<^sup>@m\ by (metis hd_word pref_cancel pref_power_ext power_Suc_list ) thus ?thesis using Cons.hyps \x = a\ add_root by fastforce qed qed lemma suf_sing_power: "w \s [a]\<^sup>@m \ w \ [a]*" using pref_sing_power[of "rev w" a m] suf_rev_pref'[of "rev w" "rev [a]\<^sup>@m"] by (metis root_def rev_power rev_rev_ident rev_singleton_conv) lemma sing_factor_power: "w \ [a]* \ v \f w \ v \ [a]*" by (metis root_def fac_suf prefI pref_sing_power suf_sing_power) lemma sing_power_factor': "a \ b \ w \ [a]* \ \ ([b] \f w)" by (metis (mono_tags, lifting) less_irrefl list.distinct(1) list.inject list.size(4) root_shorter sing_factor_power) lemma distinct_letter_in: "\ w \ [a]* \ \ m b. [a]\<^sup>@m \ [b] \p w \ b \ a" proof (induct w) case Nil then show ?case using empty_all_roots by auto next case (Cons x w) then show ?case proof- {assume "x \ a" hence ?thesis by (metis append_Nil hd_word power_zero prefI) } note neq = this {assume "x = a" hence "\ w \ [a]*" using Cons.prems add_root by force then obtain m b where "[a]\<^sup>@m \ [b] \p w" and "b \ a" using Cons.hyps by blast hence "[a]\<^sup>@Suc m \ [b] \p x#w \ b \ a" using \x = a\ by auto hence ?thesis by blast } note eq = this show ?thesis using eq neq by blast qed qed lemma distinct_letter_in': "\ w \ [hd w]* \ \ m b. [hd w]\<^sup>@m \ [b] \p w \ b \ hd w \ m \ 0" using distinct_letter_in[of w "hd w"] Cons_eq_append_conv by fastforce lemma distinct_letter_in_suf: assumes "\ w \ [a]*" shows "\ m b. [b] \ [a]\<^sup>@m \s w \ b \ a" proof- have "\ rev w \ [a]*" using rev_power[of "[a]"] unfolding rev_sing using assms root_def rev_rev_ident[of w] by metis obtain m b where "[a]\<^sup>@m \ [b] \p rev w" and "b \ a" using distinct_letter_in[OF \\ rev w \ [a]*\] by blast have "rev ( [b] \ [a]\<^sup>@m) = [a]\<^sup>@m \ [b]" by (simp add: rev_power) have "[b] \ [a]\<^sup>@m \s w" using pref_rev_suf'[of "[b] \ [a]\<^sup>@m" w] \[a]\<^sup>@m \ [b] \p rev w\ unfolding \rev ( [b] \ [a]\<^sup>@m) = [a]\<^sup>@m \ [b]\ by blast thus ?thesis using \b \ a\ by blast qed lemma sing_power:"i < m \ ([a]\<^sup>@m) ! i = a" by (induct i m rule: diff_induct) auto lemma sing_power':"w \ [a]* \ i < \<^bold>|w\<^bold>| \ w ! i = a" by (metis add_nth factor_def prefix_def sing_power_factor') lemma rev_sing_power: "x \ [a]* \ rev x = x" unfolding root_def using rev_power rev_singleton_conv by metis lemma lcp_letter_power: assumes "w \ \" and "w \ [a]*" and "[a]\<^sup>@m \ [b] \p z" and "a \ b" shows "w \ z \\<^sub>p z \ w = [a]\<^sup>@m" proof- obtain k z' where "w = [a]\<^sup>@k" "z = [a]\<^sup>@m \ [b] \ z'" "k \ 0" using \w \ [a]*\ \[a]\<^sup>@m \ [b] \p z\ \w \ \\ unfolding root_def by fastforce hence eq1: "w \ z = [a]\<^sup>@m \ ([a]\<^sup>@k \ [b] \ z')" and eq2: "z \ w = [a]\<^sup>@m \ ([b] \ z'\ [a]\<^sup>@k)" by (simp add: \w = [a]\<^sup>@k\ \z = [a]\<^sup>@m \ [b] \ z'\ powers_comm)+ have "hd ([a]\<^sup>@k \ [b] \ z') = a" using hd_sing_power \k \ 0\ by (metis \w = (a # \)\<^sup>@k\ append.assoc assms(1) hd_append2) moreover have "hd([b] \ z'\ [a]\<^sup>@k) = b" by simp ultimately have "[a]\<^sup>@k \ [b] \ z' \\<^sub>p [b] \ z'\ [a]\<^sup>@k = \" by (simp add: \a \ b\ lcp_distinct_hd) thus ?thesis using eq1 eq2 lcp_ext_left[of "[a]\<^sup>@m" "[a]\<^sup>@k \ [b] \ z'" "[b] \ z'\ [a]\<^sup>@k"] by simp qed lemma per_one: "w \p [a]\<^sup>\ \ w \ [a]*" proof(induct w) case Nil then show ?case using empty_all_roots by auto next case (Cons a w) then show ?case by (metis period_root_def add_root append_Cons hd_word list.sel(1) pref_cancel prefix_def) qed lemma per_one': "w \ [a]* \ w \p [a]\<^sup>\" by (metis append_Nil2 not_Cons_self2 per_pref prefI root_def) lemma per_sing_one: assumes "w \ \" "w \p [a]\<^sup>\" shows "periodN w 1" using periodN_root[OF \w \ \\ \w \p [a]\<^sup>\\] unfolding sing_len[of a]. section \Conjugation lemma\ lemma conjugation: assumes "x\z = z\y" and "x \ \" shows "\ u v k. x = u \ v \ y = v \ u \ z = (u \ v)\<^sup>@k \ u" proof- obtain k where "x\<^sup>@k \p z" and "z \p x\<^sup>@k \ x" using triv_pref[of z y] unfolding sym[OF \x\z = z\y\] using per_rootI[of z x, OF _ \x \ \\] per_pref[of z x] pref_power[of z x] by blast then obtain u v where "z = x\<^sup>@k \ u" and "x = u \ v" by auto hence "z = (u \ v)\<^sup>@k \ u" by simp have e: "u \ v \ ((u \ v) \<^sup>@ k \ u) = (u \ v) \<^sup>@ k \ u \ (v \ u)" by (simp add: comm_add_exp) hence "y = v \ u" using \x\z = z\y\ unfolding \x = u \ v\ \z = (u \ v)\<^sup>@k \ u\ e by simp thus ?thesis using \x = u \ v\ \z = x \<^sup>@ k \ u\ by blast qed section \Primitive words\ definition primitive :: "'a list \ bool" where "primitive x = (x \ \ \ (\ r. x \ r* \ x = r))" lemma power_non_prim: "1 < k \ \ primitive (w\<^sup>@k)" proof (cases "w = \") assume "w = \" thus "\ primitive (w\<^sup>@k)" unfolding primitive_def using emp_power by auto next assume "w \ \" and "1 < k" hence "w\<^sup>@k \ w" by (metis eq_powers nat_neq_iff power_one_id) have "w\<^sup>@k \ w*" unfolding root_def by auto thus "\ primitive (w\<^sup>@k)" unfolding primitive_def using \w\<^sup>@k \ w\ by blast qed lemma comm_non_prim: "u \ \ \ v \ \ \ u\v = v\u \ \ primitive (u\v)" proof- assume "u \ \" "v \ \" "u\v = v\u" then obtain t k m where "u = t\<^sup>@k" "k > 0" "v = t\<^sup>@m" "m > 0" "t \ \" by (metis comm emp_power neq0_conv power_zero) thus ?thesis using power_non_prim[of "k+m" "t"] by (simp add: power_add_list) qed lemma non_prim: "\ primitive w \ w \ \ \ (\ r k. r \ \ \ 1 < k \ w = r\<^sup>@k)" unfolding primitive_def by (metis emp_power less_one nat_neq_iff power_one_id power_zero root_def) section \Primitive root\ definition primitive_root :: "'a list \ 'a list \ bool" ("_ \\<^sub>p _ *" [51,51] 60) where "primitive_root x r = (x \ \ \ x \ r* \ primitive r)" fun get_primitive_root :: "'a list \ 'a list" ("\") where "get_primitive_root x = (THE r. x \\<^sub>p r*)" lemma primroot_of_root: "\ x \ \; x \ u*; u \\<^sub>p r*\ \ x \\<^sub>p r*" unfolding primitive_root_def using root_trans by blast lemma prim_self_root: "primitive x \ x \\<^sub>p x*" by (metis comm_root primitive_def primitive_root_def) lemma comm_prim: "\ primitive r; primitive s; r\s = s\r \ \ r = s" by (metis primitive_def comm_root) lemma primroot_ex: "x \ \ \ (\ r k. x \\<^sub>p r* \ k \ 0 \ x = r\<^sup>@k)" proof(induction "\<^bold>|x\<^bold>|" arbitrary: x rule: less_induct) case less then show ?case proof- {assume "\ primitive x" then obtain r where "x \ r*" "x \ r" "r \ \" unfolding primitive_def using less.prems root_nemp empty_all_roots by blast have "x \ \ \ (\ r k. x \\<^sub>p r* \ k \ 0 \ x = r\<^sup>@k)" using less.hyps[OF root_shorter[OF _ \x \ r*\ \x \ r\]] root_trans by (metis \r \ \\ \x \ r*\ power_zero primitive_root_def root_def)} thus "x \ \ \ (\ r k. x \\<^sub>p r* \ k \ 0 \ x = r\<^sup>@k)" using prim_self_root by (metis power_zero primitive_root_def root_def) qed qed text\Uniqueness of the primitive root follows from the following lemma\ lemma primroot_unique: "\ u \\<^sub>p r*; u \\<^sub>p s* \ \ r = s" proof- assume "u \\<^sub>p r*" then obtain kr where "u = r\<^sup>@kr" and "kr \ 0" by (metis power_zero primitive_root_def root_def) assume "u \\<^sub>p s*" then obtain ks where "u = s\<^sup>@ks" and "ks \ 0" by (metis power_zero primitive_root_def root_def) obtain t where "s \ t*" and "r \ t*" using powers_comm_comm[of r kr s ks, OF _ \kr \ 0\] \u = r\<^sup>@kr\ \u = s\<^sup>@ks\ comm_root0[of r s] by auto have "primitive r" and "primitive s" using \u \\<^sub>p r *\ \u \\<^sub>p s *\ primitive_root_def by auto thus ?thesis unfolding primitive_def using \s \ t*\ \r \ t*\ by auto qed text\Existence and uniqueness of the primitive root justifies the function @{term "\"}: it indeed yields the primitive root of a nonempty word.\ lemma primroot_is_primroot: assumes "x \ \" shows "x \\<^sub>p (\ x)*" by (metis assms get_primitive_root.simps primroot_ex primroot_unique theI_unique) lemma primroot_root:"u \ \ \ u \ q* \ \ q = \ u" by (metis root_nemp primroot_is_primroot primroot_of_root primroot_unique) lemma primroot_len_mult:"u \ \ \ u \ q* \ \k . \<^bold>|q\<^bold>| = k*\<^bold>|\ u\<^bold>|" by (metis primitive_root_def length_0_conv mult_0 primroot_is_primroot primroot_root root_len) lemma primroot_shorter_root:"u \ \ \ u \ q* \ \<^bold>|\ u\<^bold>| \ \<^bold>|q\<^bold>|" by (metis primitive_root_def eq_refl root_nemp order.strict_implies_order primroot_is_primroot primroot_root root_shorter) lemma primroot_shortest_root: assumes "u \ \" shows "\<^bold>|\ u\<^bold>| = (LEAST d. (\ r. (u \ r*) \ \<^bold>|r\<^bold>| = d))" using Least_equality[of "\ k. (\ r. (u \ r*) \ \<^bold>|r\<^bold>| = k)" "\<^bold>|\ u\<^bold>|"] proof show "\r. u \ r* \ \<^bold>|r\<^bold>| = \<^bold>|\ u\<^bold>|" using assms primitive_root_def primroot_is_primroot by blast show "\y. \r. u \ r* \ \<^bold>|r\<^bold>| = y \ \<^bold>|\ u\<^bold>| \ y" using assms primroot_shorter_root by fastforce qed lemma primroot_take: "u \ \ \ \ u = (take ( \<^bold>|\ u\<^bold>| ) u)" proof- assume "u \ \" then obtain k where "u = (\ u)\<^sup>@k" and "k \ 0" by (metis power_zero primitive_root_def primroot_is_primroot root_def) thus "\ u = (take ( \<^bold>|\ u\<^bold>| ) u)" by (metis take_root) qed lemma primroot_take_shortest: "u \ \ \ \ u = (take (LEAST d. (\ r. (u \ r*) \ \<^bold>|r\<^bold>| = d)) u)" using primroot_shortest_root primroot_take by fastforce text\We also have the standard characterization of commutation for nonempty words.\ theorem comm_primroots: "\ u \ \; v \ \ \ \ u \ v = v \ u \ \ u = \ v" using primitive_root_def comm_root[of u v] primroot_is_primroot primroot_root[of u] primroot_root[of v] by metis end