# HG changeset patch # User Lars Hupel # Date 1467705020 -7200 # Node ID 0d6adf2d5035be8c2cc5d8ce624769cc32d0fa73 # Parent 370cce7ad9b9aa21d85e1d89be4d0225dfe833a2# Parent bf894d31ed0f8256955256d88829c01117c1e8e3 merged diff -r 370cce7ad9b9 -r 0d6adf2d5035 NEWS --- a/NEWS Mon Jul 04 18:20:51 2016 +0200 +++ b/NEWS Tue Jul 05 09:50:20 2016 +0200 @@ -49,6 +49,9 @@ context. Unlike "context includes ... begin", the effect of 'unbundle' on the target context persists, until different declarations are given. +* Proof method "blast" is more robust wrt. corner cases of Pure +statements without object-logic judgment. + *** Prover IDE -- Isabelle/Scala/jEdit *** @@ -84,6 +87,13 @@ *** Isar *** +* The defining position of a literal fact \prop\ is maintained more +carefully, and made accessible as hyperlink in the Prover IDE. + +* Commands 'finally' and 'ultimately' used to expose the result as +literal fact: this accidental behaviour has been discontinued. Rare +INCOMPATIBILITY, use more explicit means to refer to facts in Isar. + * Command 'axiomatization' has become more restrictive to correspond better to internal axioms as singleton facts with mandatory name. Minor INCOMPATIBILITY. @@ -136,6 +146,15 @@ *** HOL *** +* Theory Library/Combinator_PER.thy: combinator to build partial +equivalence relations from a predicate and an equivalence relation. + +* Theory Library/Perm.thy: basic facts about almost everywhere fix +bijections. + +* Locale bijection establishes convenient default simp rules +like "inv f (f a) = a" for total bijections. + * Former locale lifting_syntax is now a bundle, which is easier to include in a local context or theorem statement, e.g. "context includes lifting_syntax begin ... end". Minor INCOMPATIBILITY. diff -r 370cce7ad9b9 -r 0d6adf2d5035 src/HOL/Binomial.thy --- a/src/HOL/Binomial.thy Mon Jul 04 18:20:51 2016 +0200 +++ b/src/HOL/Binomial.thy Tue Jul 05 09:50:20 2016 +0200 @@ -6,7 +6,7 @@ Additional binomial identities by Chaitanya Mangla and Manuel Eberl *) -section\Factorial Function, Binomial Coefficients and Binomial Theorem\ +section \Combinatorial Functions: Factorial Function, Rising Factorials, Binomial Coefficients and Binomial Theorem\ theory Binomial imports Main @@ -170,7 +170,8 @@ text \This development is based on the work of Andy Gordon and Florian Kammueller.\ -subsection \Basic definitions and lemmas\ + +subsection \Binomial coefficients\ text \Combinatorial definition\ @@ -394,6 +395,12 @@ ultimately show ?ths by blast qed +lemma binomial_fact': + assumes "k \ n" + shows "n choose k = fact n div (fact k * fact (n - k))" + using binomial_fact_lemma [OF assms] + by (metis fact_nonzero mult_eq_0_iff nonzero_mult_divide_cancel_left) + lemma binomial_fact: assumes kn: "k \ n" shows "(of_nat (n choose k) :: 'a::field_char_0) = @@ -465,7 +472,8 @@ finally show ?thesis . qed -subsection\Pochhammer's symbol : generalized rising factorial\ + +subsection \Pochhammer's symbol : generalized rising factorial\ text \See @{url "http://en.wikipedia.org/wiki/Pochhammer_symbol"}\ @@ -675,20 +683,24 @@ qed -subsection\Generalized binomial coefficients\ +subsection \Generalized binomial coefficients\ -definition (in field_char_0) gbinomial :: "'a \ nat \ 'a" (infixl "gchoose" 65) +definition gbinomial :: "'a :: {semidom_divide, semiring_char_0} \ nat \ 'a" (infixl "gchoose" 65) where - "a gchoose n = setprod (\i. a - of_nat i) {..i. a - of_nat i) {..i. a - of_nat i) {..k} / fact (Suc k)" by (simp add: gbinomial_def lessThan_Suc_atMost) -lemma gbinomial_0 [simp]: "a gchoose 0 = 1" "0 gchoose (Suc n) = 0" +lemma gbinomial_0 [simp]: + fixes a :: "'a::field_char_0" + shows "a gchoose 0 = 1" "(0::'a) gchoose (Suc n) = 0" by (simp_all add: gbinomial_def) -lemma gbinomial_pochhammer: "a gchoose n = (- 1) ^ n * pochhammer (- a) n / (fact n)" +lemma gbinomial_pochhammer: + fixes a :: "'a::field_char_0" + shows "a gchoose n = (- 1) ^ n * pochhammer (- a) n / (fact n)" proof (cases "n = 0") case True then show ?thesis by simp @@ -710,6 +722,32 @@ finally show ?thesis by simp qed +lemma gbinomial_binomial: + "n gchoose k = n choose k" +proof (cases "k \ n") + case False + then have "n < k" by (simp add: not_le) + then have "0 \ (op - n) ` {..n < k\ show ?thesis + by (simp add: binomial_eq_0 gbinomial_def setprod_zero) +next + case True + then have "inj_on (op - n) {..(op - n ` {..q. n - q) {..{Suc (n - k)..n}" .. + from True have "(n choose k) = fact n div (fact k * fact (n - k))" + by (rule binomial_fact') + with * show ?thesis + by (simp add: gbinomial_def mult.commute [of "fact k"] div_mult2_eq fact_div_fact) +qed + lemma binomial_gbinomial: "of_nat (n choose k) = (of_nat n gchoose k :: 'a::field_char_0)" proof - @@ -752,6 +790,8 @@ ultimately show ?thesis by blast qed +setup \Sign.add_const_constraint (@{const_name gbinomial}, SOME @{typ "'a::field_char_0 \ nat \ 'a"})\ + lemma gbinomial_1[simp]: "a gchoose 1 = a" by (simp add: gbinomial_def lessThan_Suc) @@ -1098,7 +1138,7 @@ thus ?case using gbinomial_Suc_Suc[of "(r + of_nat m + 1)" m] by (simp add: add_ac) qed auto -subsection \Summation on the upper index\ +subsubsection \Summation on the upper index\ text \ Another summation formula is equation 5.10 of the reference material \cite[p.~160]{GKP}, aptly named \emph{summation on the upper index}:\[\sum_{0 \leq k \leq n} {k \choose m} = @@ -1345,7 +1385,7 @@ by simp -subsection \Binomial coefficients\ +subsection \More on Binomial Coefficients\ lemma choose_one: "(n::nat) choose 1 = n" by simp @@ -1547,6 +1587,9 @@ (simp_all only: ac_simps diff_Suc_Suc Suc_diff_le diff_add_inverse fact_Suc of_nat_id) qed + +subsection \Misc\ + lemma fact_code [code]: "fact n = (of_nat (fold_atLeastAtMost_nat (op *) 2 n 1) :: 'a :: semiring_char_0)" proof - @@ -1562,7 +1605,6 @@ "setprod f {.. f) 0 n 1" by (simp add: lessThan_Suc_atMost atLeast0AtMost [symmetric] setprod_atLeastAtMost_code comp_def) - lemma pochhammer_code [code]: "pochhammer a n = (if n = 0 then 1 else fold_atLeastAtMost_nat (\n acc. (a + of_nat n) * acc) 0 (n - 1) 1)" diff -r 370cce7ad9b9 -r 0d6adf2d5035 src/HOL/Hilbert_Choice.thy --- a/src/HOL/Hilbert_Choice.thy Mon Jul 04 18:20:51 2016 +0200 +++ b/src/HOL/Hilbert_Choice.thy Tue Jul 05 09:50:20 2016 +0200 @@ -811,6 +811,73 @@ subsection \More on injections, bijections, and inverses\ +locale bijection = + fixes f :: "'a \ 'a" + assumes bij: "bij f" +begin + +lemma bij_inv: + "bij (inv f)" + using bij by (rule bij_imp_bij_inv) + +lemma surj [simp]: + "surj f" + using bij by (rule bij_is_surj) + +lemma inj: + "inj f" + using bij by (rule bij_is_inj) + +lemma surj_inv [simp]: + "surj (inv f)" + using inj by (rule inj_imp_surj_inv) + +lemma inj_inv: + "inj (inv f)" + using surj by (rule surj_imp_inj_inv) + +lemma eqI: + "f a = f b \ a = b" + using inj by (rule injD) + +lemma eq_iff [simp]: + "f a = f b \ a = b" + by (auto intro: eqI) + +lemma eq_invI: + "inv f a = inv f b \ a = b" + using inj_inv by (rule injD) + +lemma eq_inv_iff [simp]: + "inv f a = inv f b \ a = b" + by (auto intro: eq_invI) + +lemma inv_left [simp]: + "inv f (f a) = a" + using inj by (simp add: inv_f_eq) + +lemma inv_comp_left [simp]: + "inv f \ f = id" + by (simp add: fun_eq_iff) + +lemma inv_right [simp]: + "f (inv f a) = a" + using surj by (simp add: surj_f_inv_f) + +lemma inv_comp_right [simp]: + "f \ inv f = id" + by (simp add: fun_eq_iff) + +lemma inv_left_eq_iff [simp]: + "inv f a = b \ f b = a" + by auto + +lemma inv_right_eq_iff [simp]: + "b = inv f a \ f b = a" + by auto + +end + lemma infinite_imp_bij_betw: assumes INF: "\ finite A" shows "\h. bij_betw h A (A - {a})" diff -r 370cce7ad9b9 -r 0d6adf2d5035 src/HOL/Library/Combine_PER.thy --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/HOL/Library/Combine_PER.thy Tue Jul 05 09:50:20 2016 +0200 @@ -0,0 +1,60 @@ +(* Author: Florian Haftmann, TU Muenchen *) + +section \A combinator to build partial equivalence relations from a predicate and an equivalence relation\ + +theory Combine_PER +imports Main "~~/src/HOL/Library/Lattice_Syntax" +begin + +definition combine_per :: "('a \ bool) \ ('a \ 'a \ bool) \ 'a \ 'a \ bool" +where + "combine_per P R = (\x y. P x \ P y) \ R" + +lemma combine_per_simp [simp]: + fixes R (infixl "\" 50) + shows "combine_per P R x y \ P x \ P y \ x \ y" + by (simp add: combine_per_def) + +lemma combine_per_top [simp]: + "combine_per \ R = R" + by (simp add: fun_eq_iff) + +lemma combine_per_eq [simp]: + "combine_per P HOL.eq = HOL.eq \ (\x y. P x)" + by (auto simp add: fun_eq_iff) + +lemma symp_combine_per: + "symp R \ symp (combine_per P R)" + by (auto simp add: symp_def sym_def combine_per_def) + +lemma transp_combine_per: + "transp R \ transp (combine_per P R)" + by (auto simp add: transp_def trans_def combine_per_def) + +lemma combine_perI: + fixes R (infixl "\" 50) + shows "P x \ P y \ x \ y \ combine_per P R x y" + by (simp add: combine_per_def) + +lemma symp_combine_per_symp: + "symp R \ symp (combine_per P R)" + by (auto intro!: sympI elim: sympE) + +lemma transp_combine_per_transp: + "transp R \ transp (combine_per P R)" + by (auto intro!: transpI elim: transpE) + +lemma equivp_combine_per_part_equivp: + fixes R (infixl "\" 50) + assumes "\x. P x" and "equivp R" + shows "part_equivp (combine_per P R)" +proof - + from \\x. P x\ obtain x where "P x" .. + moreover from \equivp R\ have "x \ x" by (rule equivp_reflp) + ultimately have "\x. P x \ x \ x" by blast + with \equivp R\ show ?thesis + by (auto intro!: part_equivpI symp_combine_per_symp transp_combine_per_transp + elim: equivpE) +qed + +end \ No newline at end of file diff -r 370cce7ad9b9 -r 0d6adf2d5035 src/HOL/Library/Dlist.thy --- a/src/HOL/Library/Dlist.thy Mon Jul 04 18:20:51 2016 +0200 +++ b/src/HOL/Library/Dlist.thy Tue Jul 05 09:50:20 2016 +0200 @@ -67,6 +67,9 @@ qualified definition filter :: "('a \ bool) \ 'a dlist \ 'a dlist" where "filter P dxs = Dlist (List.filter P (list_of_dlist dxs))" +qualified definition rotate :: "nat \ 'a dlist \ 'a dlist" where + "rotate n dxs = Dlist (List.rotate n (list_of_dlist dxs))" + end @@ -115,6 +118,10 @@ "list_of_dlist (Dlist.filter P dxs) = List.filter P (list_of_dlist dxs)" by (simp add: Dlist.filter_def) +lemma list_of_dlist_rotate [simp, code abstract]: + "list_of_dlist (Dlist.rotate n dxs) = List.rotate n (list_of_dlist dxs)" + by (simp add: Dlist.rotate_def) + text \Explicit executable conversion\ diff -r 370cce7ad9b9 -r 0d6adf2d5035 src/HOL/Library/Library.thy --- a/src/HOL/Library/Library.thy Mon Jul 04 18:20:51 2016 +0200 +++ b/src/HOL/Library/Library.thy Tue Jul 05 09:50:20 2016 +0200 @@ -12,6 +12,7 @@ Code_Test ContNotDenum Convex + Combine_PER Complete_Partial_Order2 Countable Countable_Complete_Lattices @@ -55,6 +56,7 @@ Option_ord Order_Continuity Parallel + Perm Permutation Permutations Polynomial diff -r 370cce7ad9b9 -r 0d6adf2d5035 src/HOL/Library/Perm.thy --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/HOL/Library/Perm.thy Tue Jul 05 09:50:20 2016 +0200 @@ -0,0 +1,807 @@ +(* Author: Florian Haftmann, TU Muenchen *) + +section \Permutations as abstract type\ + +theory Perm +imports Main +begin + +text \ + This theory introduces basics about permutations, i.e. almost + everywhere fix bijections. But it is by no means complete. + Grieviously missing are cycles since these would require more + elaboration, e.g. the concept of distinct lists equivalent + under rotation, which maybe would also deserve its own theory. + But see theory @{text "src/HOL/ex/Perm_Fragments.thy"} for + fragments on that. +\ + +subsection \Abstract type of permutations\ + +typedef 'a perm = "{f :: 'a \ 'a. bij f \ finite {a. f a \ a}}" + morphisms "apply" Perm + by (rule exI [of _ id]) simp + +setup_lifting type_definition_perm + +notation "apply" (infixl "\$\" 999) +no_notation "apply" ("op \$\") + +lemma bij_apply [simp]: + "bij (apply f)" + using "apply" [of f] by simp + +lemma perm_eqI: + assumes "\a. f \$\ a = g \$\ a" + shows "f = g" + using assms by transfer (simp add: fun_eq_iff) + +lemma perm_eq_iff: + "f = g \ (\a. f \$\ a = g \$\ a)" + by (auto intro: perm_eqI) + +lemma apply_inj: + "f \$\ a = f \$\ b \ a = b" + by (rule inj_eq) (rule bij_is_inj, simp) + +lift_definition affected :: "'a perm \ 'a set" + is "\f. {a. f a \ a}" . + +lemma in_affected: + "a \ affected f \ f \$\ a \ a" + by transfer simp + +lemma finite_affected [simp]: + "finite (affected f)" + by transfer simp + +lemma apply_affected [simp]: + "f \$\ a \ affected f \ a \ affected f" +proof transfer + fix f :: "'a \ 'a" and a :: 'a + assume "bij f \ finite {b. f b \ b}" + then have "bij f" by simp + interpret bijection f by standard (rule \bij f\) + have "f a \ {a. f a = a} \ a \ {a. f a = a}" (is "?P \ ?Q") + by auto + then show "f a \ {a. f a \ a} \ a \ {a. f a \ a}" + by simp +qed + +lemma card_affected_not_one: + "card (affected f) \ 1" +proof + interpret bijection "apply f" + by standard (rule bij_apply) + assume "card (affected f) = 1" + then obtain a where *: "affected f = {a}" + by (rule card_1_singletonE) + then have "f \$\ a \ a" + by (simp add: in_affected [symmetric]) + moreover with * have "f \$\ a \ affected f" + by simp + then have "f \$\ (f \$\ a) = f \$\ a" + by (simp add: in_affected) + then have "inv (apply f) (f \$\ (f \$\ a)) = inv (apply f) (f \$\ a)" + by simp + ultimately show False by simp +qed + + +subsection \Identity, composition and inversion\ + +instantiation Perm.perm :: (type) "{monoid_mult, inverse}" +begin + +lift_definition one_perm :: "'a perm" + is id + by simp + +lemma apply_one [simp]: + "apply 1 = id" + by (fact one_perm.rep_eq) + +lemma affected_one [simp]: + "affected 1 = {}" + by transfer simp + +lemma affected_empty_iff [simp]: + "affected f = {} \ f = 1" + by transfer auto + +lift_definition times_perm :: "'a perm \ 'a perm \ 'a perm" + is comp +proof + fix f g :: "'a \ 'a" + assume "bij f \ finite {a. f a \ a}" + "bij g \finite {a. g a \ a}" + then have "finite ({a. f a \ a} \ {a. g a \ a})" + by simp + moreover have "{a. (f \ g) a \ a} \ {a. f a \ a} \ {a. g a \ a}" + by auto + ultimately show "finite {a. (f \ g) a \ a}" + by (auto intro: finite_subset) +qed (auto intro: bij_comp) + +lemma apply_times: + "apply (f * g) = apply f \ apply g" + by (fact times_perm.rep_eq) + +lemma apply_sequence: + "f \$\ (g \$\ a) = apply (f * g) a" + by (simp add: apply_times) + +lemma affected_times [simp]: + "affected (f * g) \ affected f \ affected g" + by transfer auto + +lift_definition inverse_perm :: "'a perm \ 'a perm" + is inv +proof transfer + fix f :: "'a \ 'a" and a + assume "bij f \ finite {b. f b \ b}" + then have "bij f" and fin: "finite {b. f b \ b}" + by auto + interpret bijection f by standard (rule \bij f\) + from fin show "bij (inv f) \ finite {a. inv f a \ a}" + by (simp add: bij_inv) +qed + +instance + by standard (transfer; simp add: comp_assoc)+ + +end + +lemma apply_inverse: + "apply (inverse f) = inv (apply f)" + by (fact inverse_perm.rep_eq) + +lemma affected_inverse [simp]: + "affected (inverse f) = affected f" +proof transfer + fix f :: "'a \ 'a" and a + assume "bij f \ finite {b. f b \ b}" + then have "bij f" by simp + interpret bijection f by standard (rule \bij f\) + show "{a. inv f a \ a} = {a. f a \ a}" + by simp +qed + +global_interpretation perm: group times "1::'a perm" inverse +proof + fix f :: "'a perm" + show "1 * f = f" + by transfer simp + show "inverse f * f = 1" + proof transfer + fix f :: "'a \ 'a" and a + assume "bij f \ finite {b. f b \ b}" + then have "bij f" by simp + interpret bijection f by standard (rule \bij f\) + show "inv f \ f = id" + by simp + qed +qed + +declare perm.inverse_distrib_swap [simp] + +lemma perm_mult_commute: + assumes "affected f \ affected g = {}" + shows "g * f = f * g" +proof (rule perm_eqI) + fix a + from assms have *: "a \ affected f \ a \ affected g" + "a \ affected g \ a \ affected f" for a + by auto + consider "a \ affected f \ a \ affected g + \ f \$\ a \ affected f" + | "a \ affected f \ a \ affected g + \ f \$\ a \ affected f" + | "a \ affected f \ a \ affected g" + using assms by auto + then show "(g * f) \$\ a = (f * g) \$\ a" + proof cases + case 1 moreover with * have "f \$\ a \ affected g" + by auto + ultimately show ?thesis by (simp add: in_affected apply_times) + next + case 2 moreover with * have "g \$\ a \ affected f" + by auto + ultimately show ?thesis by (simp add: in_affected apply_times) + next + case 3 then show ?thesis by (simp add: in_affected apply_times) + qed +qed + +lemma apply_power: + "apply (f ^ n) = apply f ^^ n" + by (induct n) (simp_all add: apply_times) + +lemma perm_power_inverse: + "inverse f ^ n = inverse ((f :: 'a perm) ^ n)" +proof (induct n) + case 0 then show ?case by simp +next + case (Suc n) + then show ?case + unfolding power_Suc2 [of f] by simp +qed + + +subsection \Orbit and order of elements\ + +definition orbit :: "'a perm \ 'a \ 'a set" +where + "orbit f a = range (\n. (f ^ n) \$\ a)" + +lemma in_orbitI: + assumes "(f ^ n) \$\ a = b" + shows "b \ orbit f a" + using assms by (auto simp add: orbit_def) + +lemma apply_power_self_in_orbit [simp]: + "(f ^ n) \$\ a \ orbit f a" + by (rule in_orbitI) rule + +lemma in_orbit_self [simp]: + "a \ orbit f a" + using apply_power_self_in_orbit [of _ 0] by simp + +lemma apply_self_in_orbit [simp]: + "f \$\ a \ orbit f a" + using apply_power_self_in_orbit [of _ 1] by simp + +lemma orbit_not_empty [simp]: + "orbit f a \ {}" + using in_orbit_self [of a f] by blast + +lemma not_in_affected_iff_orbit_eq_singleton: + "a \ affected f \ orbit f a = {a}" (is "?P \ ?Q") +proof + assume ?P + then have "f \$\ a = a" + by (simp add: in_affected) + then have "(f ^ n) \$\ a = a" for n + by (induct n) (simp_all add: apply_times) + then show ?Q + by (auto simp add: orbit_def) +next + assume ?Q + then show ?P + by (auto simp add: orbit_def in_affected dest: range_eq_singletonD [of _ _ 1]) +qed + +definition order :: "'a perm \ 'a \ nat" +where + "order f = card \ orbit f" + +lemma orbit_subset_eq_affected: + assumes "a \ affected f" + shows "orbit f a \ affected f" +proof (rule ccontr) + assume "\ orbit f a \ affected f" + then obtain b where "b \ orbit f a" and "b \ affected f" + by auto + then have "b \ range (\n. (f ^ n) \$\ a)" + by (simp add: orbit_def) + then obtain n where "b = (f ^ n) \$\ a" + by blast + with \b \ affected f\ + have "(f ^ n) \$\ a \ affected f" + by simp + then have "f \$\ a \ affected f" + by (induct n) (simp_all add: apply_times) + with assms show False + by simp +qed + +lemma finite_orbit [simp]: + "finite (orbit f a)" +proof (cases "a \ affected f") + case False then show ?thesis + by (simp add: not_in_affected_iff_orbit_eq_singleton) +next + case True then have "orbit f a \ affected f" + by (rule orbit_subset_eq_affected) + then show ?thesis using finite_affected + by (rule finite_subset) +qed + +lemma orbit_1 [simp]: + "orbit 1 a = {a}" + by (auto simp add: orbit_def) + +lemma order_1 [simp]: + "order 1 a = 1" + unfolding order_def by simp + +lemma card_orbit_eq [simp]: + "card (orbit f a) = order f a" + by (simp add: order_def) + +lemma order_greater_zero [simp]: + "order f a > 0" + by (simp only: card_gt_0_iff order_def comp_def) simp + +lemma order_eq_one_iff: + "order f a = Suc 0 \ a \ affected f" (is "?P \ ?Q") +proof + assume ?P then have "card (orbit f a) = 1" + by simp + then obtain b where "orbit f a = {b}" + by (rule card_1_singletonE) + with in_orbit_self [of a f] + have "b = a" by simp + with \orbit f a = {b}\ show ?Q + by (simp add: not_in_affected_iff_orbit_eq_singleton) +next + assume ?Q + then have "orbit f a = {a}" + by (simp add: not_in_affected_iff_orbit_eq_singleton) + then have "card (orbit f a) = 1" + by simp + then show ?P + by simp +qed + +lemma order_greater_eq_two_iff: + "order f a \ 2 \ a \ affected f" + using order_eq_one_iff [of f a] + apply (auto simp add: neq_iff) + using order_greater_zero [of f a] + apply simp + done + +lemma order_less_eq_affected: + assumes "f \ 1" + shows "order f a \ card (affected f)" +proof (cases "a \ affected f") + from assms have "affected f \ {}" + by simp + then obtain B b where "affected f = insert b B" + by blast + with finite_affected [of f] have "card (affected f) \ 1" + by (simp add: card_insert) + case False then have "order f a = 1" + by (simp add: order_eq_one_iff) + with \card (affected f) \ 1\ show ?thesis + by simp +next + case True + have "card (orbit f a) \ card (affected f)" + by (rule card_mono) (simp_all add: True orbit_subset_eq_affected card_mono) + then show ?thesis + by simp +qed + +lemma affected_order_greater_eq_two: + assumes "a \ affected f" + shows "order f a \ 2" +proof (rule ccontr) + assume "\ 2 \ order f a" + then have "order f a < 2" + by (simp add: not_le) + with order_greater_zero [of f a] have "order f a = 1" + by arith + with assms show False + by (simp add: order_eq_one_iff) +qed + +lemma order_witness_unfold: + assumes "n > 0" and "(f ^ n) \$\ a = a" + shows "order f a = card ((\m. (f ^ m) \$\ a) ` {0..m. (f ^ m) \$\ a) ` {0.. orbit f a" + then obtain m where "(f ^ m) \$\ a = b" + by (auto simp add: orbit_def) + then have "b = (f ^ (m mod n + n * (m div n))) \$\ a" + by simp + also have "\ = (f ^ (m mod n)) \$\ ((f ^ (n * (m div n))) \$\ a)" + by (simp only: power_add apply_times) simp + also have "(f ^ (n * q)) \$\ a = a" for q + by (induct q) + (simp_all add: power_add apply_times assms) + finally have "b = (f ^ (m mod n)) \$\ a" . + moreover from \n > 0\ + have "m mod n < n" + by simp + ultimately show "b \ ?B" + by auto + next + fix b + assume "b \ ?B" + then obtain m where "(f ^ m) \$\ a = b" + by blast + then show "b \ orbit f a" + by (rule in_orbitI) + qed + then have "card (orbit f a) = card ?B" + by (simp only:) + then show ?thesis + by simp +qed + +lemma inj_on_apply_range: + "inj_on (\m. (f ^ m) \$\ a) {..m. (f ^ m) \$\ a) {.. order f a" for n + using that proof (induct n) + case 0 then show ?case by simp + next + case (Suc n) + then have prem: "n < order f a" + by simp + with Suc.hyps have hyp: "inj_on (\m. (f ^ m) \$\ a) {..$\ a \ (\m. (f ^ m) \$\ a) ` {..$\ a \ (\m. (f ^ m) \$\ a) ` {..$\ a = (f ^ n) \$\ a" and "m < n" + by auto + interpret bijection "apply (f ^ m)" + by standard simp + from \m < n\ have "n = m + (n - m)" + and nm: "0 < n - m" "n - m \ n" + by arith+ + with * have "(f ^ m) \$\ a = (f ^ (m + (n - m))) \$\ a" + by simp + then have "(f ^ m) \$\ a = (f ^ m) \$\ ((f ^ (n - m)) \$\ a)" + by (simp add: power_add apply_times) + then have "(f ^ (n - m)) \$\ a = a" + by simp + with \n - m > 0\ + have "order f a = card ((\m. (f ^ m) \$\ a) ` {0..m. (f ^ m) \$\ a) ` {0.. card {0.. n - m" + by simp + with prem show False by simp + qed + with hyp show ?case + by (simp add: lessThan_Suc) + qed + then show ?thesis by simp +qed + +lemma orbit_unfold_image: + "orbit f a = (\n. (f ^ n) \$\ a) ` {.. orbit f a" + by (auto simp add: orbit_def) + from inj_on_apply_range [of f a] + have "card ?A = order f a" + by (auto simp add: card_image) + then show "card ?A = card (orbit f a)" + by simp +qed + +lemma in_orbitE: + assumes "b \ orbit f a" + obtains n where "b = (f ^ n) \$\ a" and "n < order f a" + using assms unfolding orbit_unfold_image by blast + +lemma apply_power_order [simp]: + "(f ^ order f a) \$\ a = a" +proof - + have "(f ^ order f a) \$\ a \ orbit f a" + by simp + then obtain n where + *: "(f ^ order f a) \$\ a = (f ^ n) \$\ a" + and "n < order f a" + by (rule in_orbitE) + show ?thesis + proof (cases n) + case 0 with * show ?thesis by simp + next + case (Suc m) + from order_greater_zero [of f a] + have "Suc (order f a - 1) = order f a" + by arith + from Suc \n < order f a\ + have "m < order f a" + by simp + with Suc * + have "(inverse f) \$\ ((f ^ Suc (order f a - 1)) \$\ a) = + (inverse f) \$\ ((f ^ Suc m) \$\ a)" + by simp + then have "(f ^ (order f a - 1)) \$\ a = + (f ^ m) \$\ a" + by (simp only: power_Suc apply_times) + (simp add: apply_sequence mult.assoc [symmetric]) + with inj_on_apply_range + have "order f a - 1 = m" + by (rule inj_onD) + (simp_all add: \m < order f a\) + with Suc have "n = order f a" + by auto + with \n < order f a\ + show ?thesis by simp + qed +qed + +lemma apply_power_left_mult_order [simp]: + "(f ^ (n * order f a)) \$\ a = a" + by (induct n) (simp_all add: power_add apply_times) + +lemma apply_power_right_mult_order [simp]: + "(f ^ (order f a * n)) \$\ a = a" + by (simp add: ac_simps) + +lemma apply_power_mod_order_eq [simp]: + "(f ^ (n mod order f a)) \$\ a = (f ^ n) \$\ a" +proof - + have "(f ^ n) \$\ a = (f ^ (n mod order f a + order f a * (n div order f a))) \$\ a" + by simp + also have "\ = (f ^ (n mod order f a) * f ^ (order f a * (n div order f a))) \$\ a" + by (simp add: power_add [symmetric]) + finally show ?thesis + by (simp add: apply_times) +qed + +lemma apply_power_eq_iff: + "(f ^ m) \$\ a = (f ^ n) \$\ a \ m mod order f a = n mod order f a" (is "?P \ ?Q") +proof + assume ?Q + then have "(f ^ (m mod order f a)) \$\ a = (f ^ (n mod order f a)) \$\ a" + by simp + then show ?P + by simp +next + assume ?P + then have "(f ^ (m mod order f a)) \$\ a = (f ^ (n mod order f a)) \$\ a" + by simp + with inj_on_apply_range + show ?Q + by (rule inj_onD) simp_all +qed + +lemma apply_inverse_eq_apply_power_order_minus_one: + "(inverse f) \$\ a = (f ^ (order f a - 1)) \$\ a" +proof (cases "order f a") + case 0 with order_greater_zero [of f a] show ?thesis + by simp +next + case (Suc n) + moreover have "(f ^ order f a) \$\ a = a" + by simp + then have *: "(inverse f) \$\ ((f ^ order f a) \$\ a) = (inverse f) \$\ a" + by simp + ultimately show ?thesis + by (simp add: apply_sequence mult.assoc [symmetric]) +qed + +lemma apply_inverse_self_in_orbit [simp]: + "(inverse f) \$\ a \ orbit f a" + using apply_inverse_eq_apply_power_order_minus_one [symmetric] + by (rule in_orbitI) + +lemma apply_inverse_power_eq: + "(inverse (f ^ n)) \$\ a = (f ^ (order f a - n mod order f a)) \$\ a" +proof (induct n) + case 0 then show ?case by simp +next + case (Suc n) + define m where "m = order f a - n mod order f a - 1" + moreover have "order f a - n mod order f a > 0" + by simp + ultimately have "order f a - n mod order f a = Suc m" + by arith + moreover from this have m2: "order f a - Suc n mod order f a = (if m = 0 then order f a else m)" + by (auto simp add: mod_Suc) + ultimately show ?case + using Suc + by (simp_all add: apply_times power_Suc2 [of _ n] power_Suc [of _ m] del: power_Suc) + (simp add: apply_sequence mult.assoc [symmetric]) +qed + +lemma apply_power_eq_self_iff: + "(f ^ n) \$\ a = a \ order f a dvd n" + using apply_power_eq_iff [of f n a 0] + by (simp add: mod_eq_0_iff_dvd) + +lemma orbit_equiv: + assumes "b \ orbit f a" + shows "orbit f b = orbit f a" (is "?B = ?A") +proof + from assms obtain n where "n < order f a" and b: "b = (f ^ n) \$\ a" + by (rule in_orbitE) + then show "?B \ ?A" + by (auto simp add: apply_sequence power_add [symmetric] intro: in_orbitI elim!: in_orbitE) + from b have "(inverse (f ^ n)) \$\ b = (inverse (f ^ n)) \$\ ((f ^ n) \$\ a)" + by simp + then have a: "a = (inverse (f ^ n)) \$\ b" + by (simp add: apply_sequence) + then show "?A \ ?B" + apply (auto simp add: apply_sequence power_add [symmetric] intro: in_orbitI elim!: in_orbitE) + unfolding apply_times comp_def apply_inverse_power_eq + unfolding apply_sequence power_add [symmetric] + apply (rule in_orbitI) apply rule + done +qed + +lemma orbit_apply [simp]: + "orbit f (f \$\ a) = orbit f a" + by (rule orbit_equiv) simp + +lemma order_apply [simp]: + "order f (f \$\ a) = order f a" + by (simp only: order_def comp_def orbit_apply) + +lemma orbit_apply_inverse [simp]: + "orbit f (inverse f \$\ a) = orbit f a" + by (rule orbit_equiv) simp + +lemma order_apply_inverse [simp]: + "order f (inverse f \$\ a) = order f a" + by (simp only: order_def comp_def orbit_apply_inverse) + +lemma orbit_apply_power [simp]: + "orbit f ((f ^ n) \$\ a) = orbit f a" + by (rule orbit_equiv) simp + +lemma order_apply_power [simp]: + "order f ((f ^ n) \$\ a) = order f a" + by (simp only: order_def comp_def orbit_apply_power) + +lemma orbit_inverse [simp]: + "orbit (inverse f) = orbit f" +proof (rule ext, rule set_eqI, rule) + fix b a + assume "b \ orbit f a" + then obtain n where b: "b = (f ^ n) \$\ a" "n < order f a" + by (rule in_orbitE) + then have "b = apply (inverse (inverse f) ^ n) a" + by simp + then have "b = apply (inverse (inverse f ^ n)) a" + by (simp add: perm_power_inverse) + then have "b = apply (inverse f ^ (n * (order (inverse f ^ n) a - 1))) a" + by (simp add: apply_inverse_eq_apply_power_order_minus_one power_mult) + then show "b \ orbit (inverse f) a" + by simp +next + fix b a + assume "b \ orbit (inverse f) a" + then show "b \ orbit f a" + by (rule in_orbitE) + (simp add: apply_inverse_eq_apply_power_order_minus_one + perm_power_inverse power_mult [symmetric]) +qed + +lemma order_inverse [simp]: + "order (inverse f) = order f" + by (simp add: order_def) + +lemma orbit_disjoint: + assumes "orbit f a \ orbit f b" + shows "orbit f a \ orbit f b = {}" +proof (rule ccontr) + assume "orbit f a \ orbit f b \ {}" + then obtain c where "c \ orbit f a \ orbit f b" + by blast + then have "c \ orbit f a" and "c \ orbit f b" + by auto + then obtain m n where "c = (f ^ m) \$\ a" + and "c = apply (f ^ n) b" by (blast elim!: in_orbitE) + then have "(f ^ m) \$\ a = apply (f ^ n) b" + by simp + then have "apply (inverse f ^ m) ((f ^ m) \$\ a) = + apply (inverse f ^ m) (apply (f ^ n) b)" + by simp + then have *: "apply (inverse f ^ m * f ^ n) b = a" + by (simp add: apply_sequence perm_power_inverse) + have "a \ orbit f b" + proof (cases n m rule: linorder_cases) + case equal with * show ?thesis + by (simp add: perm_power_inverse) + next + case less + moreover define q where "q = m - n" + ultimately have "m = q + n" by arith + with * have "apply (inverse f ^ q) b = a" + by (simp add: power_add mult.assoc perm_power_inverse) + then have "a \ orbit (inverse f) b" + by (rule in_orbitI) + then show ?thesis + by simp + next + case greater + moreover define q where "q = n - m" + ultimately have "n = m + q" by arith + with * have "apply (f ^ q) b = a" + by (simp add: power_add mult.assoc [symmetric] perm_power_inverse) + then show ?thesis + by (rule in_orbitI) + qed + with assms show False + by (auto dest: orbit_equiv) +qed + + +subsection \Swaps\ + +lift_definition swap :: "'a \ 'a \ 'a perm" ("\_\_\") + is "\a b. Fun.swap a b id" +proof + fix a b :: 'a + have "{c. Fun.swap a b id c \ c} \ {a, b}" + by (auto simp add: Fun.swap_def) + then show "finite {c. Fun.swap a b id c \ c}" + by (rule finite_subset) simp +qed simp + +lemma apply_swap_simp [simp]: + "\a\b\ \$\ a = b" + "\a\b\ \$\ b = a" + by (transfer; simp)+ + +lemma apply_swap_same [simp]: + "c \ a \ c \ b \ \a\b\ \$\ c = c" + by transfer simp + +lemma apply_swap_eq_iff [simp]: + "\a\b\ \$\ c = a \ c = b" + "\a\b\ \$\ c = b \ c = a" + by (transfer; auto simp add: Fun.swap_def)+ + +lemma swap_1 [simp]: + "\a\a\ = 1" + by transfer simp + +lemma swap_sym: + "\b\a\ = \a\b\" + by (transfer; auto simp add: Fun.swap_def)+ + +lemma swap_self [simp]: + "\a\b\ * \a\b\ = 1" + by transfer (simp add: Fun.swap_def fun_eq_iff) + +lemma affected_swap: + "a \ b \ affected \a\b\ = {a, b}" + by transfer (auto simp add: Fun.swap_def) + +lemma inverse_swap [simp]: + "inverse \a\b\ = \a\b\" + by transfer (auto intro: inv_equality simp: Fun.swap_def) + + +subsection \Permutations specified by cycles\ + +fun cycle :: "'a list \ 'a perm" ("\_\") +where + "\[]\ = 1" +| "\[a]\ = 1" +| "\a # b # as\ = \a # as\ * \a\b\" + +text \ + We do not continue and restrict ourselves to syntax from here. + See also introductory note. +\ + + +subsection \Syntax\ + +bundle no_permutation_syntax +begin + no_notation swap ("\_\_\") + no_notation cycle ("\_\") + no_notation "apply" (infixl "\$\" 999) +end + +bundle permutation_syntax +begin + notation swap ("\_\_\") + notation cycle ("\_\") + notation "apply" (infixl "\$\" 999) + no_notation "apply" ("op \$\") +end + +unbundle no_permutation_syntax + +end diff -r 370cce7ad9b9 -r 0d6adf2d5035 src/HOL/ROOT --- a/src/HOL/ROOT Mon Jul 04 18:20:51 2016 +0200 +++ b/src/HOL/ROOT Tue Jul 05 09:50:20 2016 +0200 @@ -619,6 +619,7 @@ Sum_of_Powers Sudoku Code_Timing + Perm_Fragments theories [skip_proofs = false] Meson_Test document_files "root.bib" "root.tex" diff -r 370cce7ad9b9 -r 0d6adf2d5035 src/HOL/Relation.thy --- a/src/HOL/Relation.thy Mon Jul 04 18:20:51 2016 +0200 +++ b/src/HOL/Relation.thy Tue Jul 05 09:50:20 2016 +0200 @@ -51,6 +51,7 @@ declare Sup2_E [elim!] declare SUP2_E [elim!] + subsection \Fundamental\ subsubsection \Relations as sets of pairs\ @@ -141,6 +142,7 @@ lemma SUP_Sup_eq2 [pred_set_conv]: "(\i\S. (\x y. (x, y) \ i)) = (\x y. (x, y) \ \S)" by (simp add: fun_eq_iff) + subsection \Properties of relations\ subsubsection \Reflexivity\ @@ -161,7 +163,7 @@ "reflp (\x y. (x, y) \ r) \ refl r" by (simp add: refl_on_def reflp_def) -lemma refl_onI: "r \ A \ A ==> (!!x. x : A ==> (x, x) : r) ==> refl_on A r" +lemma refl_onI [intro?]: "r \ A \ A ==> (!!x. x : A ==> (x, x) : r) ==> refl_on A r" by (unfold refl_on_def) (iprover intro!: ballI) lemma refl_onD: "refl_on A r ==> a : A ==> (a, a) : r" @@ -173,7 +175,7 @@ lemma refl_onD2: "refl_on A r ==> (x, y) : r ==> y : A" by (unfold refl_on_def) blast -lemma reflpI: +lemma reflpI [intro?]: "(\x. r x x) \ reflp r" by (auto intro: refl_onI simp add: reflp_def) @@ -182,7 +184,7 @@ obtains "r x x" using assms by (auto dest: refl_onD simp add: reflp_def) -lemma reflpD: +lemma reflpD [dest?]: assumes "reflp r" shows "r x x" using assms by (auto elim: reflpE) @@ -222,6 +224,7 @@ lemma reflp_mono: "\ reflp R; \x y. R x y \ Q x y \ \ reflp Q" by(auto intro: reflpI dest: reflpD) + subsubsection \Irreflexivity\ definition irrefl :: "'a rel \ bool" @@ -236,11 +239,11 @@ "irreflp (\a b. (a, b) \ R) \ irrefl R" by (simp add: irrefl_def irreflp_def) -lemma irreflI: +lemma irreflI [intro?]: "(\a. (a, a) \ R) \ irrefl R" by (simp add: irrefl_def) -lemma irreflpI: +lemma irreflpI [intro?]: "(\a. \ R a a) \ irreflp R" by (fact irreflI [to_pred]) @@ -278,11 +281,11 @@ "symp (\x y. (x, y) \ r) \ sym r" by (simp add: sym_def symp_def) -lemma symI: +lemma symI [intro?]: "(\a b. (a, b) \ r \ (b, a) \ r) \ sym r" by (unfold sym_def) iprover -lemma sympI: +lemma sympI [intro?]: "(\a b. r a b \ r b a) \ symp r" by (fact symI [to_pred]) @@ -296,12 +299,12 @@ obtains "r a b" using assms by (rule symE [to_pred]) -lemma symD: +lemma symD [dest?]: assumes "sym r" and "(b, a) \ r" shows "(a, b) \ r" using assms by (rule symE) -lemma sympD: +lemma sympD [dest?]: assumes "symp r" and "r b a" shows "r a b" using assms by (rule symD [to_pred]) @@ -346,14 +349,14 @@ "antisym r \ (\x y. (x, y) \ r \ (y, x) \ r \ x = y)" abbreviation antisymP :: "('a \ 'a \ bool) \ bool" -where +where -- \FIXME proper logical operation\ "antisymP r \ antisym {(x, y). r x y}" -lemma antisymI: +lemma antisymI [intro?]: "(!!x y. (x, y) : r ==> (y, x) : r ==> x=y) ==> antisym r" by (unfold antisym_def) iprover -lemma antisymD: "antisym r ==> (a, b) : r ==> (b, a) : r ==> a = b" +lemma antisymD [dest?]: "antisym r ==> (a, b) : r ==> (b, a) : r ==> a = b" by (unfold antisym_def) iprover lemma antisym_subset: "r \ s ==> antisym s ==> antisym r" @@ -365,6 +368,7 @@ lemma antisymP_equality [simp]: "antisymP op =" by(auto intro: antisymI) + subsubsection \Transitivity\ definition trans :: "'a rel \ bool" @@ -379,15 +383,11 @@ "transp (\x y. (x, y) \ r) \ trans r" by (simp add: trans_def transp_def) -abbreviation transP :: "('a \ 'a \ bool) \ bool" -where \ \FIXME drop\ - "transP r \ trans {(x, y). r x y}" - -lemma transI: +lemma transI [intro?]: "(\x y z. (x, y) \ r \ (y, z) \ r \ (x, z) \ r) \ trans r" by (unfold trans_def) iprover -lemma transpI: +lemma transpI [intro?]: "(\x y z. r x y \ r y z \ r x z) \ transp r" by (fact transI [to_pred]) @@ -401,12 +401,12 @@ obtains "r x z" using assms by (rule transE [to_pred]) -lemma transD: +lemma transD [dest?]: assumes "trans r" and "(x, y) \ r" and "(y, z) \ r" shows "(x, z) \ r" using assms by (rule transE) -lemma transpD: +lemma transpD [dest?]: assumes "transp r" and "r x y" and "r y z" shows "r x z" using assms by (rule transD [to_pred]) @@ -436,6 +436,7 @@ lemma transp_equality [simp]: "transp op =" by(auto intro: transpI) + subsubsection \Totality\ definition total_on :: "'a set \ 'a rel \ bool" @@ -454,7 +455,8 @@ where "single_valued r \ (\x y. (x, y) \ r \ (\z. (x, z) \ r \ y = z))" -abbreviation single_valuedP :: "('a \ 'b \ bool) \ bool" where +abbreviation single_valuedP :: "('a \ 'b \ bool) \ bool" +where -- \FIXME proper logical operation\ "single_valuedP r \ single_valued {(x, y). r x y}" lemma single_valuedI: @@ -518,6 +520,7 @@ lemma Id_fstsnd_eq: "Id = {x. fst x = snd x}" by force + subsubsection \Diagonal: identity over a set\ definition Id_on :: "'a set \ 'a rel" @@ -684,6 +687,7 @@ lemma OO_eq: "R OO op = = R" by blast + subsubsection \Converse\ inductive_set converse :: "('a \ 'b) set \ ('b \ 'a) set" ("(_\)" [1000] 999) @@ -838,8 +842,6 @@ where DomainI [intro]: "(a, b) \ r \ a \ Domain r" -abbreviation (input) "DomainP \ Domainp" - lemmas DomainPI = Domainp.DomainI inductive_cases DomainE [elim!]: "a \ Domain r" @@ -850,8 +852,6 @@ where RangeI [intro]: "(a, b) \ r \ b \ Range r" -abbreviation (input) "RangeP \ Rangep" - lemmas RangePI = Rangep.RangeI inductive_cases RangeE [elim!]: "b \ Range r" @@ -1079,6 +1079,7 @@ lemma relcomp_Image: "(X O Y) `` Z = Y `` (X `` Z)" by auto + subsubsection \Inverse image\ definition inv_image :: "'b rel \ ('a \ 'b) \ 'a rel" @@ -1122,6 +1123,7 @@ lemmas Powp_mono [mono] = Pow_mono [to_pred] + subsubsection \Expressing relation operations via @{const Finite_Set.fold}\ lemma Id_on_fold: @@ -1196,4 +1198,17 @@ (auto simp: comp_fun_commute.fold_insert comp_fun_commute_relcomp_fold insert_relcomp_fold cong: if_cong) +text \Misc\ + +abbreviation (input) transP :: "('a \ 'a \ bool) \ bool" +where \ \FIXME drop\ + "transP r \ trans {(x, y). r x y}" + +abbreviation (input) + "RangeP \ Rangep" + +abbreviation (input) + "DomainP \ Domainp" + + end diff -r 370cce7ad9b9 -r 0d6adf2d5035 src/HOL/ex/Perm_Fragments.thy --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/HOL/ex/Perm_Fragments.thy Tue Jul 05 09:50:20 2016 +0200 @@ -0,0 +1,293 @@ +(* Author: Florian Haftmann, TU Muenchen *) + +section \Fragments on permuations\ + +theory Perm_Fragments +imports "~~/src/HOL/Library/Perm" "~~/src/HOL/Library/Dlist" +begin + +unbundle permutation_syntax + + +text \On cycles\ + +lemma cycle_listprod: + "\a # as\ = listprod (map (\b. \a\b\) (rev as))" + by (induct as) simp_all + +lemma cycle_append [simp]: + "\a # as @ bs\ = \a # bs\ * \a # as\" +proof (induct as rule: cycle.induct) + case (3 b c as) + then have "\a # (b # as) @ bs\ = \a # bs\ * \a # b # as\" + by simp + then have "\a # as @ bs\ * \a\b\ = + \a # bs\ * \a # as\ * \a\b\" + by (simp add: ac_simps) + then have "\a # as @ bs\ * \a\b\ * \a\b\ = + \a # bs\ * \a # as\ * \a\b\ * \a\b\" + by simp + then have "\a # as @ bs\ = \a # bs\ * \a # as\" + by (simp add: ac_simps) + then show "\a # (b # c # as) @ bs\ = + \a # bs\ * \a # b # c # as\" + by (simp add: ac_simps) +qed simp_all + +lemma affected_cycle: + "affected \as\ \ set as" +proof (induct as rule: cycle.induct) + case (3 a b as) + from affected_times + have "affected (\a # as\ * \a\b\) + \ affected \a # as\ \ affected \a\b\" . + moreover from 3 + have "affected (\a # as\) \ insert a (set as)" + by simp + moreover + have "affected \a\b\ \ {a, b}" + by (cases "a = b") (simp_all add: affected_swap) + ultimately have "affected (\a # as\ * \a\b\) + \ insert a (insert b (set as))" + by blast + then show ?case by auto +qed simp_all + +lemma orbit_cycle_non_elem: + assumes "a \ set as" + shows "orbit \as\ a = {a}" + unfolding not_in_affected_iff_orbit_eq_singleton [symmetric] + using assms affected_cycle [of as] by blast + +lemma inverse_cycle: + assumes "distinct as" + shows "inverse \as\ = \rev as\" +using assms proof (induct as rule: cycle.induct) + case (3 a b as) + then have *: "inverse \a # as\ = \rev (a # as)\" + and distinct: "distinct (a # b # as)" + by simp_all + show " inverse \a # b # as\ = \rev (a # b # as)\" + proof (cases as rule: rev_cases) + case Nil with * show ?thesis + by (simp add: swap_sym) + next + case (snoc cs c) + with distinct have "distinct (a # b # cs @ [c])" + by simp + then have **: "\a\b\ * \c\a\ = \c\a\ * \c\b\" + by transfer (auto simp add: comp_def Fun.swap_def) + with snoc * show ?thesis + by (simp add: mult.assoc [symmetric]) + qed +qed simp_all + +lemma order_cycle_non_elem: + assumes "a \ set as" + shows "order \as\ a = 1" +proof - + from assms have "orbit \as\ a = {a}" + by (rule orbit_cycle_non_elem) + then have "card (orbit \as\ a) = card {a}" + by simp + then show ?thesis + by simp +qed + +lemma orbit_cycle_elem: + assumes "distinct as" and "a \ set as" + shows "orbit \as\ a = set as" + oops -- \(we need rotation here\ + +lemma order_cycle_elem: + assumes "distinct as" and "a \ set as" + shows "order \as\ a = length as" + oops + + +text \Adding fixpoints\ + +definition fixate :: "'a \ 'a perm \ 'a perm" +where + "fixate a f = (if a \ affected f then f * \apply (inverse f) a\a\ else f)" + +lemma affected_fixate_trivial: + assumes "a \ affected f" + shows "affected (fixate a f) = affected f" + using assms by (simp add: fixate_def) + +lemma affected_fixate_binary_circle: + assumes "order f a = 2" + shows "affected (fixate a f) = affected f - {a, apply f a}" (is "?A = ?B") +proof (rule set_eqI) + interpret bijection "apply f" + by standard simp + fix b + from assms order_greater_eq_two_iff [of f a] have "a \ affected f" + by simp + moreover have "apply (f ^ 2) a = a" + by (simp add: assms [symmetric]) + ultimately show "b \ ?A \ b \ ?B" + by (cases "b \ {a, apply (inverse f) a}") + (auto simp add: in_affected power2_eq_square apply_inverse apply_times fixate_def) +qed + +lemma affected_fixate_no_binary_circle: + assumes "order f a > 2" + shows "affected (fixate a f) = affected f - {a}" (is "?A = ?B") +proof (rule set_eqI) + interpret bijection "apply f" + by standard simp + fix b + from assms order_greater_eq_two_iff [of f a] + have "a \ affected f" + by simp + moreover from assms + have "apply f (apply f a) \ a" + using apply_power_eq_iff [of f 2 a 0] + by (simp add: power2_eq_square apply_times) + ultimately show "b \ ?A \ b \ ?B" + by (cases "b \ {a, apply (inverse f) a}") + (auto simp add: in_affected apply_inverse apply_times fixate_def) +qed + +lemma affected_fixate: + "affected (fixate a f) \ affected f - {a}" +proof - + have "a \ affected f \ order f a = 2 \ order f a > 2" + by (auto simp add: not_less dest: affected_order_greater_eq_two) + then consider "a \ affected f" | "order f a = 2" | "order f a > 2" + by blast + then show ?thesis apply cases + using affected_fixate_trivial [of a f] + affected_fixate_binary_circle [of f a] + affected_fixate_no_binary_circle [of f a] + by auto +qed + +lemma orbit_fixate_self [simp]: + "orbit (fixate a f) a = {a}" +proof - + have "apply (f * inverse f) a = a" + by simp + then have "apply f (apply (inverse f) a) = a" + by (simp only: apply_times comp_apply) + then show ?thesis + by (simp add: fixate_def not_in_affected_iff_orbit_eq_singleton [symmetric] in_affected apply_times) +qed + +lemma order_fixate_self [simp]: + "order (fixate a f) a = 1" +proof - + have "card (orbit (fixate a f) a) = card {a}" + by simp + then show ?thesis + by (simp only: card_orbit_eq) simp +qed + +lemma + assumes "b \ orbit f a" + shows "orbit (fixate b f) a = orbit f a" + oops + +lemma + assumes "b \ orbit f a" and "b \ a" + shows "orbit (fixate b f) a = orbit f a - {b}" + oops + + +text \Distilling cycles from permutations\ + +inductive_set orbits :: "'a perm \ 'a set set" for f +where + in_orbitsI: "a \ affected f \ orbit f a \ orbits f" + +lemma orbits_unfold: + "orbits f = orbit f ` affected f" + by (auto intro: in_orbitsI elim: orbits.cases) + +lemma in_orbit_affected: + assumes "b \ orbit f a" + assumes "a \ affected f" + shows "b \ affected f" +proof (cases "a = b") + case True with assms show ?thesis by simp +next + case False with assms have "{a, b} \ orbit f a" + by auto + also from assms have "orbit f a \ affected f" + by (blast intro!: orbit_subset_eq_affected) + finally show ?thesis by simp +qed + +lemma Union_orbits [simp]: + "\orbits f = affected f" + by (auto simp add: orbits.simps intro: in_orbitsI in_orbit_affected) + +lemma finite_orbits [simp]: + "finite (orbits f)" + by (simp add: orbits_unfold) + +lemma card_in_orbits: + assumes "A \ orbits f" + shows "card A \ 2" + using assms by cases + (auto dest: affected_order_greater_eq_two) + +lemma disjoint_orbits: + assumes "A \ orbits f" and "B \ orbits f" and "A \ B" + shows "A \ B = {}" + using \A \ orbits f\ apply cases + using \B \ orbits f\ apply cases + using \A \ B\ apply (simp_all add: orbit_disjoint) + done + +definition trace :: "'a \ 'a perm \ 'a list" +where + "trace a f = map (\n. apply (f ^ n) a) [0.. 'a::linorder list" +where + "seeds f = sorted_list_of_set (Min ` orbits f)" + +definition cycles :: "'a perm \ 'a::linorder list list" +where + "cycles f = map (\a. trace a f) (seeds f)" + +lemma (in comm_monoid_list_set) sorted_list_of_set: + assumes "finite A" + shows "list.F (map h (sorted_list_of_set A)) = set.F h A" +proof - + from distinct_sorted_list_of_set + have "set.F h (set (sorted_list_of_set A)) = list.F (map h (sorted_list_of_set A))" + by (rule distinct_set_conv_list) + with \finite A\ show ?thesis + by (simp add: sorted_list_of_set) +qed + + +text \Misc\ + +primrec subtract :: "'a list \ 'a list \ 'a list" +where + "subtract [] ys = ys" +| "subtract (x # xs) ys = subtract xs (removeAll x ys)" + +lemma length_subtract_less_eq [simp]: + "length (subtract xs ys) \ length ys" +proof (induct xs arbitrary: ys) + case Nil then show ?case by simp +next + case (Cons x xs) + then have "length (subtract xs (removeAll x ys)) \ length (removeAll x ys)" . + also have "length (removeAll x ys) \ length ys" + by simp + finally show ?case + by simp +qed + +end diff -r 370cce7ad9b9 -r 0d6adf2d5035 src/Pure/General/binding.ML --- a/src/Pure/General/binding.ML Mon Jul 04 18:20:51 2016 +0200 +++ b/src/Pure/General/binding.ML Tue Jul 05 09:50:20 2016 +0200 @@ -17,6 +17,7 @@ val pos_of: binding -> Position.T val set_pos: Position.T -> binding -> binding val reset_pos: binding -> binding + val default_pos: binding -> binding val name: bstring -> binding val name_of: binding -> bstring val map_name: (bstring -> bstring) -> binding -> binding @@ -75,20 +76,28 @@ fun path_of (Binding {prefix, qualifier, ...}) = prefix @ qualifier; +fun make (name, pos) = make_binding (NONE, false, [], [], name, pos); + (** basic operations **) -(* name and position *) - -fun make (name, pos) = make_binding (NONE, false, [], [], name, pos); +(* position *) fun pos_of (Binding {pos, ...}) = pos; + fun set_pos pos = map_binding (fn (restricted, concealed, prefix, qualifier, name, _) => (restricted, concealed, prefix, qualifier, name, pos)); + val reset_pos = set_pos Position.none; +fun default_pos b = + if pos_of b = Position.none then set_pos (Position.thread_data ()) b else b; + + +(* name *) + fun name name = make (name, Position.none); fun name_of (Binding {name, ...}) = name; diff -r 370cce7ad9b9 -r 0d6adf2d5035 src/Pure/Isar/calculation.ML --- a/src/Pure/Isar/calculation.ML Mon Jul 04 18:20:51 2016 +0200 +++ b/src/Pure/Isar/calculation.ML Tue Jul 05 09:50:20 2016 +0200 @@ -61,7 +61,7 @@ fun put_calculation calc = `Proof.level #-> (fn lev => Proof.map_context (Context.proof_map (Data.map (apsnd (K (Option.map (rpair lev) calc)))))) - #> Proof.put_thms false (calculationN, calc); + #> Proof.map_context (Proof_Context.put_thms false (calculationN, calc)); diff -r 370cce7ad9b9 -r 0d6adf2d5035 src/Pure/Isar/interpretation.ML --- a/src/Pure/Isar/interpretation.ML Mon Jul 04 18:20:51 2016 +0200 +++ b/src/Pure/Isar/interpretation.ML Tue Jul 05 09:50:20 2016 +0200 @@ -116,38 +116,42 @@ local -fun meta_rewrite eqns ctxt = (map (Local_Defs.abs_def_rule ctxt) (maps snd eqns), ctxt); +fun meta_rewrite eqns ctxt = + (map (Local_Defs.abs_def_rule ctxt) (maps snd eqns), ctxt); -fun note_eqns_register note activate deps witss def_eqns eqns attrss export export' ctxt = +fun note_eqns_register pos note activate deps witss def_eqns eqns attrss export export' ctxt = let - val facts = (Binding.empty_atts, [(map (Morphism.thm (export' $> export)) def_eqns, [])]) - :: map2 (fn attrs => fn eqn => (attrs, [([Morphism.thm (export' $> export) eqn], [])])) attrss eqns; + val facts = + (Binding.empty_atts, [(map (Morphism.thm (export' $> export)) def_eqns, [])]) :: + map2 (fn attrs => fn eqn => (attrs, [([Morphism.thm (export' $> export) eqn], [])])) + attrss eqns; val (eqns', ctxt') = ctxt |> note Thm.theoremK facts |-> meta_rewrite; - val dep_morphs = map2 (fn (dep, morph) => fn wits => - (dep, morph $> Element.satisfy_morphism (map (Element.transform_witness export') wits))) deps witss; - fun activate' dep_morph ctxt = activate dep_morph - (Option.map (rpair true) (Element.eq_morphism (Proof_Context.theory_of ctxt) eqns')) export ctxt; - in - ctxt' - |> fold activate' dep_morphs - end; + val dep_morphs = + map2 (fn (dep, morph) => fn wits => + let val morph' = morph + $> Element.satisfy_morphism (map (Element.transform_witness export') wits) + $> Morphism.binding_morphism "position" (Binding.set_pos pos) + in (dep, morph') end) deps witss; + fun activate' dep_morph ctxt = + activate dep_morph + (Option.map (rpair true) (Element.eq_morphism (Proof_Context.theory_of ctxt) eqns')) + export ctxt; + in ctxt' |> fold activate' dep_morphs end; in -fun generic_interpretation_with_defs prep_interpretation setup_proof note add_registration +fun generic_interpretation prep_interpretation setup_proof note add_registration expression raw_defs raw_eqns initial_ctxt = let val (((propss, deps, export, export'), (def_eqns, eqns, attrss)), goal_ctxt) = prep_interpretation expression raw_defs raw_eqns initial_ctxt; + val pos = Position.thread_data (); fun after_qed witss eqns = - note_eqns_register note add_registration deps witss def_eqns eqns attrss export export'; + note_eqns_register pos note add_registration deps witss def_eqns eqns attrss export export'; in setup_proof after_qed propss eqns goal_ctxt end; -fun generic_interpretation prep_interpretation setup_proof note add_registration expression = - generic_interpretation_with_defs prep_interpretation setup_proof note add_registration expression []; - end; @@ -160,22 +164,21 @@ fun gen_interpret prep_interpretation expression raw_eqns state = let val _ = Proof.assert_forward_or_chain state; - val ctxt = Proof.context_of state; fun lift_after_qed after_qed witss eqns = Proof.map_context (after_qed witss eqns) #> Proof.reset_facts; fun setup_proof after_qed propss eqns goal_ctxt = Element.witness_local_proof_eqs (lift_after_qed after_qed) "interpret" propss eqns goal_ctxt state; in - generic_interpretation prep_interpretation setup_proof - Attrib.local_notes (Context.proof_map ooo Locale.add_registration) expression raw_eqns ctxt + Proof.context_of state + |> generic_interpretation prep_interpretation setup_proof + Attrib.local_notes (Context.proof_map ooo Locale.add_registration) expression [] raw_eqns end; in -fun interpret expression = gen_interpret cert_interpretation expression; - -fun interpret_cmd raw_expression = gen_interpret read_interpretation raw_expression; +val interpret = gen_interpret cert_interpretation; +val interpret_cmd = gen_interpret read_interpretation; end; @@ -184,33 +187,33 @@ fun interpretation expression = generic_interpretation cert_interpretation Element.witness_proof_eqs - Local_Theory.notes_kind Locale.activate_fragment expression; + Local_Theory.notes_kind Locale.activate_fragment expression []; -fun interpretation_cmd raw_expression = +fun interpretation_cmd expression = generic_interpretation read_interpretation Element.witness_proof_eqs - Local_Theory.notes_kind Locale.activate_fragment raw_expression; + Local_Theory.notes_kind Locale.activate_fragment expression []; (* interpretation into global theories *) fun global_interpretation expression = - generic_interpretation_with_defs cert_interpretation Element.witness_proof_eqs + generic_interpretation cert_interpretation Element.witness_proof_eqs Local_Theory.notes_kind Local_Theory.theory_registration expression; -fun global_interpretation_cmd raw_expression = - generic_interpretation_with_defs read_interpretation Element.witness_proof_eqs - Local_Theory.notes_kind Local_Theory.theory_registration raw_expression; +fun global_interpretation_cmd expression = + generic_interpretation read_interpretation Element.witness_proof_eqs + Local_Theory.notes_kind Local_Theory.theory_registration expression; (* interpretation between locales *) fun sublocale expression = - generic_interpretation_with_defs cert_interpretation Element.witness_proof_eqs + generic_interpretation cert_interpretation Element.witness_proof_eqs Local_Theory.notes_kind Local_Theory.locale_dependency expression; -fun sublocale_cmd raw_expression = - generic_interpretation_with_defs read_interpretation Element.witness_proof_eqs - Local_Theory.notes_kind Local_Theory.locale_dependency raw_expression; +fun sublocale_cmd expression = + generic_interpretation read_interpretation Element.witness_proof_eqs + Local_Theory.notes_kind Local_Theory.locale_dependency expression; local @@ -223,7 +226,7 @@ (fn wits => fn eqs => after_qed wits eqs #> Local_Theory.exit); in lthy |> - generic_interpretation_with_defs prep_interpretation setup_proof + generic_interpretation prep_interpretation setup_proof Local_Theory.notes_kind Local_Theory.locale_dependency expression raw_defs raw_eqns end; @@ -249,7 +252,7 @@ fun gen_isar_interpretation prep_interpretation expression raw_eqns lthy = generic_interpretation prep_interpretation Element.witness_proof_eqs - Local_Theory.notes_kind (register_or_activate lthy) expression raw_eqns lthy; + Local_Theory.notes_kind (register_or_activate lthy) expression [] raw_eqns lthy; in diff -r 370cce7ad9b9 -r 0d6adf2d5035 src/Pure/Isar/proof.ML --- a/src/Pure/Isar/proof.ML Mon Jul 04 18:20:51 2016 +0200 +++ b/src/Pure/Isar/proof.ML Tue Jul 05 09:50:20 2016 +0200 @@ -19,7 +19,6 @@ val map_context_result : (context -> 'a * context) -> state -> 'a * state val map_contexts: (context -> context) -> state -> state val propagate_ml_env: state -> state - val put_thms: bool -> string * thm list option -> state -> state val the_facts: state -> thm list val the_fact: state -> thm val set_facts: thm list -> state -> state @@ -241,8 +240,6 @@ fun propagate_ml_env state = map_contexts (Context.proof_map (ML_Env.inherit (Context.Proof (context_of state)))) state; -val put_thms = map_context oo Proof_Context.put_thms; - (* facts *) @@ -258,12 +255,12 @@ [thm] => thm | _ => error "Single theorem expected"); -fun put_facts facts = +fun put_facts index facts = map_top (fn (ctxt, _, mode, goal) => (ctxt, facts, mode, goal)) #> - put_thms true (Auto_Bind.thisN, facts); + map_context (Proof_Context.put_thms index (Auto_Bind.thisN, facts)); -val set_facts = put_facts o SOME; -val reset_facts = put_facts NONE; +val set_facts = put_facts false o SOME; +val reset_facts = put_facts false NONE; fun these_factss more_facts (named_factss, state) = (named_factss, state |> set_facts (maps snd named_factss @ more_facts)); @@ -274,7 +271,7 @@ | SOME thms => thms |> Proof_Context.export (context_of inner) (context_of outer) - |> (fn ths => set_facts ths outer)); + |> (fn ths => put_facts true (SOME ths) outer)); (* mode *) @@ -1100,6 +1097,7 @@ in (prems, ctxt'') end); (*result*) + val results_bindings = map (apfst Binding.default_pos) shows_bindings; fun after_qed' (result_ctxt, results) state' = let val ctxt' = context_of state'; @@ -1110,7 +1108,7 @@ val export = map export0 #> Variable.export result_ctxt ctxt'; in state' - |> local_results (shows_bindings ~~ burrow export results) + |> local_results (results_bindings ~~ burrow export results) |-> (fn res => tap (fn st => print_results (context_of st) ((kind, ""), res) : unit)) |> after_qed (result_ctxt, results) end; diff -r 370cce7ad9b9 -r 0d6adf2d5035 src/Pure/facts.ML --- a/src/Pure/facts.ML Mon Jul 04 18:20:51 2016 +0200 +++ b/src/Pure/facts.ML Tue Jul 05 09:50:20 2016 +0200 @@ -250,11 +250,12 @@ fun add_static context {strict, index} (b, ths) (Facts {facts, props}) = let val ths' = map Thm.trim_context ths; - val pos = #2 (Position.default (Binding.pos_of b)); + val pos = Binding.pos_of (Binding.default_pos b); val (name, facts') = if Binding.is_empty b then ("", facts) else Name_Space.define context strict (b, Static ths') facts; + val props' = props |> index ? fold (fn th => Net.insert_term (K false) (Thm.full_prop_of th, (th, pos))) ths'; in (name, make_facts facts' props') end;