src/HOL/Library/Permutations.thy
changeset 73466 ee1c4962671c
parent 73410 7b59d2945e54
equal deleted inserted replaced
73465:1e5c1f8a35cd 73466:ee1c4962671c
     6 
     6 
     7 theory Permutations
     7 theory Permutations
     8   imports Multiset Disjoint_Sets
     8   imports Multiset Disjoint_Sets
     9 begin
     9 begin
    10 
    10 
       
    11 subsection \<open>Auxiliary\<close>
       
    12 
       
    13 abbreviation (input) fixpoints :: \<open>('a \<Rightarrow> 'a) \<Rightarrow> 'a set\<close>
       
    14   where \<open>fixpoints f \<equiv> {x. f x = x}\<close>
       
    15 
       
    16 lemma inj_on_fixpoints:
       
    17   \<open>inj_on f (fixpoints f)\<close>
       
    18   by (rule inj_onI) simp
       
    19 
       
    20 lemma bij_betw_fixpoints:
       
    21   \<open>bij_betw f (fixpoints f) (fixpoints f)\<close>
       
    22   using inj_on_fixpoints by (auto simp add: bij_betw_def)
       
    23 
       
    24 
    11 subsection \<open>Basic definition and consequences\<close>
    25 subsection \<open>Basic definition and consequences\<close>
    12 
    26 
    13 definition permutes  (infixr "permutes" 41)
    27 definition permutes :: \<open>('a \<Rightarrow> 'a) \<Rightarrow> 'a set \<Rightarrow> bool\<close>  (infixr \<open>permutes\<close> 41)
    14   where "(p permutes S) \<longleftrightarrow> (\<forall>x. x \<notin> S \<longrightarrow> p x = x) \<and> (\<forall>y. \<exists>!x. p x = y)"
    28   where \<open>p permutes S \<longleftrightarrow> (\<forall>x. x \<notin> S \<longrightarrow> p x = x) \<and> (\<forall>y. \<exists>!x. p x = y)\<close>
    15 
    29 
    16 lemma permutes_in_image: "p permutes S \<Longrightarrow> p x \<in> S \<longleftrightarrow> x \<in> S"
    30 lemma bij_imp_permutes:
    17   unfolding permutes_def by metis
    31   \<open>p permutes S\<close> if \<open>bij_betw p S S\<close> and stable: \<open>\<And>x. x \<notin> S \<Longrightarrow> p x = x\<close>
    18 
    32 proof -
    19 lemma permutes_not_in: "f permutes S \<Longrightarrow> x \<notin> S \<Longrightarrow> f x = x"
    33   note \<open>bij_betw p S S\<close>
    20   by (auto simp: permutes_def)
    34   moreover have \<open>bij_betw p (- S) (- S)\<close>
    21 
    35     by (auto simp add: stable intro!: bij_betw_imageI inj_onI)
    22 lemma permutes_image: "p permutes S \<Longrightarrow> p ` S = S"
    36   ultimately have \<open>bij_betw p (S \<union> - S) (S \<union> - S)\<close>
    23   unfolding permutes_def
    37     by (rule bij_betw_combine) simp
    24   apply (rule set_eqI)
    38   then have \<open>\<exists>!x. p x = y\<close> for y
    25   apply (simp add: image_iff)
    39     by (simp add: bij_iff)
    26   apply metis
    40   with stable show ?thesis
    27   done
    41     by (simp add: permutes_def)
    28 
    42 qed
    29 lemma permutes_inj: "p permutes S \<Longrightarrow> inj p"
    43 
    30   unfolding permutes_def inj_def by blast
    44 context
    31 
    45   fixes p :: \<open>'a \<Rightarrow> 'a\<close> and S :: \<open>'a set\<close>
    32 lemma permutes_inj_on: "f permutes S \<Longrightarrow> inj_on f A"
    46   assumes perm: \<open>p permutes S\<close>
    33   by (auto simp: permutes_def inj_on_def)
    47 begin
    34 
    48 
    35 lemma permutes_surj: "p permutes s \<Longrightarrow> surj p"
    49 lemma permutes_inj:
    36   unfolding permutes_def surj_def by metis
    50   \<open>inj p\<close>
    37 
    51   using perm by (auto simp: permutes_def inj_on_def)
    38 lemma permutes_bij: "p permutes s \<Longrightarrow> bij p"
    52 
    39   unfolding bij_def by (metis permutes_inj permutes_surj)
    53 lemma permutes_image:
    40 
    54   \<open>p ` S = S\<close>
    41 lemma permutes_imp_bij: "p permutes S \<Longrightarrow> bij_betw p S S"
    55 proof (rule set_eqI)
    42   by (metis UNIV_I bij_betw_subset permutes_bij permutes_image subsetI)
    56   fix x
    43 
    57   show \<open>x \<in> p ` S \<longleftrightarrow> x \<in> S\<close>
    44 lemma bij_imp_permutes: "bij_betw p S S \<Longrightarrow> (\<And>x. x \<notin> S \<Longrightarrow> p x = x) \<Longrightarrow> p permutes S"
    58   proof
    45   unfolding permutes_def bij_betw_def inj_on_def
    59     assume \<open>x \<in> p ` S\<close>
    46   by auto (metis image_iff)+
    60     then obtain y where \<open>y \<in> S\<close> \<open>p y = x\<close>
       
    61       by blast
       
    62     with perm show \<open>x \<in> S\<close>
       
    63       by (cases \<open>y = x\<close>) (auto simp add: permutes_def)
       
    64   next
       
    65     assume \<open>x \<in> S\<close>
       
    66     with perm obtain y where \<open>y \<in> S\<close> \<open>p y = x\<close>
       
    67       by (metis permutes_def)
       
    68     then show \<open>x \<in> p ` S\<close>
       
    69       by blast
       
    70   qed
       
    71 qed
       
    72 
       
    73 lemma permutes_not_in:
       
    74   \<open>x \<notin> S \<Longrightarrow> p x = x\<close>
       
    75   using perm by (auto simp: permutes_def)
       
    76 
       
    77 lemma permutes_image_complement:
       
    78   \<open>p ` (- S) = - S\<close>
       
    79   by (auto simp add: permutes_not_in)
       
    80 
       
    81 lemma permutes_in_image:
       
    82   \<open>p x \<in> S \<longleftrightarrow> x \<in> S\<close>
       
    83   using permutes_image permutes_inj by (auto dest: inj_image_mem_iff)
       
    84 
       
    85 lemma permutes_surj:
       
    86   \<open>surj p\<close>
       
    87 proof -
       
    88   have \<open>p ` (S \<union> - S) = p ` S \<union> p ` (- S)\<close>
       
    89     by (rule image_Un)
       
    90   then show ?thesis
       
    91     by (simp add: permutes_image permutes_image_complement)
       
    92 qed
    47 
    93 
    48 lemma permutes_inv_o:
    94 lemma permutes_inv_o:
    49   assumes permutes: "p permutes S"
       
    50   shows "p \<circ> inv p = id"
    95   shows "p \<circ> inv p = id"
    51     and "inv p \<circ> p = id"
    96     and "inv p \<circ> p = id"
    52   using permutes_inj[OF permutes] permutes_surj[OF permutes]
    97   using permutes_inj permutes_surj
    53   unfolding inj_iff[symmetric] surj_iff[symmetric] by blast+
    98   unfolding inj_iff [symmetric] surj_iff [symmetric] by auto
    54 
    99 
    55 lemma permutes_inverses:
   100 lemma permutes_inverses:
    56   fixes p :: "'a \<Rightarrow> 'a"
       
    57   assumes permutes: "p permutes S"
       
    58   shows "p (inv p x) = x"
   101   shows "p (inv p x) = x"
    59     and "inv p (p x) = x"
   102     and "inv p (p x) = x"
    60   using permutes_inv_o[OF permutes, unfolded fun_eq_iff o_def] by auto
   103   using permutes_inv_o [unfolded fun_eq_iff o_def] by auto
    61 
   104 
    62 lemma permutes_subset: "p permutes S \<Longrightarrow> S \<subseteq> T \<Longrightarrow> p permutes T"
   105 lemma permutes_inv_eq:
    63   unfolding permutes_def by blast
   106   \<open>inv p y = x \<longleftrightarrow> p x = y\<close>
       
   107   by (auto simp add: permutes_inverses)
       
   108 
       
   109 lemma permutes_inj_on:
       
   110   \<open>inj_on p A\<close>
       
   111   by (rule inj_on_subset [of _ UNIV]) (auto intro: permutes_inj)
       
   112 
       
   113 lemma permutes_bij:
       
   114   \<open>bij p\<close>
       
   115   unfolding bij_def by (metis permutes_inj permutes_surj)
       
   116 
       
   117 lemma permutes_imp_bij:
       
   118   \<open>bij_betw p S S\<close>
       
   119   by (simp add: bij_betw_def permutes_image permutes_inj_on)
       
   120 
       
   121 lemma permutes_subset:
       
   122   \<open>p permutes T\<close> if \<open>S \<subseteq> T\<close>
       
   123 proof (rule bij_imp_permutes)
       
   124   define R where \<open>R = T - S\<close>
       
   125   with that have \<open>T = R \<union> S\<close> \<open>R \<inter> S = {}\<close>
       
   126     by auto
       
   127   then have \<open>p x = x\<close> if \<open>x \<in> R\<close> for x
       
   128     using that by (auto intro: permutes_not_in)
       
   129   then have \<open>p ` R = R\<close>
       
   130     by simp
       
   131   with \<open>T = R \<union> S\<close> show \<open>bij_betw p T T\<close>
       
   132     by (simp add: bij_betw_def permutes_inj_on image_Un permutes_image)
       
   133   fix x
       
   134   assume \<open>x \<notin> T\<close>
       
   135   with \<open>T = R \<union> S\<close> show \<open>p x = x\<close>
       
   136     by (simp add: permutes_not_in)
       
   137 qed
    64 
   138 
    65 lemma permutes_imp_permutes_insert:
   139 lemma permutes_imp_permutes_insert:
    66   \<open>p permutes insert x S\<close> if \<open>p permutes S\<close>
   140   \<open>p permutes insert x S\<close>
    67   using that by (rule permutes_subset) auto
   141   by (rule permutes_subset) auto
    68 
   142 
    69 lemma permutes_empty[simp]: "p permutes {} \<longleftrightarrow> p = id"
   143 end
    70   by (auto simp add: fun_eq_iff permutes_def)
   144 
    71 
   145 lemma permutes_id [simp]:
    72 lemma permutes_sing[simp]: "p permutes {a} \<longleftrightarrow> p = id"
   146   \<open>id permutes S\<close>
    73   by (simp add: fun_eq_iff permutes_def) metis  (*somewhat slow*)
   147   by (auto intro: bij_imp_permutes)
       
   148 
       
   149 lemma permutes_empty [simp]:
       
   150   \<open>p permutes {} \<longleftrightarrow> p = id\<close>
       
   151 proof
       
   152   assume \<open>p permutes {}\<close>
       
   153   then show \<open>p = id\<close>
       
   154     by (auto simp add: fun_eq_iff permutes_not_in)
       
   155 next
       
   156   assume \<open>p = id\<close>
       
   157   then show \<open>p permutes {}\<close>
       
   158     by simp
       
   159 qed
       
   160 
       
   161 lemma permutes_sing [simp]:
       
   162   \<open>p permutes {a} \<longleftrightarrow> p = id\<close>
       
   163 proof
       
   164   assume perm: \<open>p permutes {a}\<close>
       
   165   show \<open>p = id\<close>
       
   166   proof
       
   167     fix x
       
   168     from perm have \<open>p ` {a} = {a}\<close>
       
   169       by (rule permutes_image)
       
   170     with perm show \<open>p x = id x\<close>
       
   171       by (cases \<open>x = a\<close>) (auto simp add: permutes_not_in)
       
   172   qed
       
   173 next
       
   174   assume \<open>p = id\<close>
       
   175   then show \<open>p permutes {a}\<close>
       
   176     by simp
       
   177 qed
    74 
   178 
    75 lemma permutes_univ: "p permutes UNIV \<longleftrightarrow> (\<forall>y. \<exists>!x. p x = y)"
   179 lemma permutes_univ: "p permutes UNIV \<longleftrightarrow> (\<forall>y. \<exists>!x. p x = y)"
    76   by (simp add: permutes_def)
   180   by (simp add: permutes_def)
    77 
   181 
    78 lemma permutes_inv_eq: "p permutes S \<Longrightarrow> inv p y = x \<longleftrightarrow> p x = y"
       
    79   unfolding permutes_def inv_def
       
    80   apply auto
       
    81   apply (erule allE[where x=y])
       
    82   apply (erule allE[where x=y])
       
    83   apply (rule someI_ex)
       
    84   apply blast
       
    85   apply (rule some1_equality)
       
    86   apply blast
       
    87   apply blast
       
    88   done
       
    89 
       
    90 lemma permutes_swap_id: "a \<in> S \<Longrightarrow> b \<in> S \<Longrightarrow> Fun.swap a b id permutes S"
   182 lemma permutes_swap_id: "a \<in> S \<Longrightarrow> b \<in> S \<Longrightarrow> Fun.swap a b id permutes S"
    91   unfolding permutes_def Fun.swap_def fun_upd_def by auto metis
   183   by (rule bij_imp_permutes) (auto simp add: swap_id_eq)
    92 
   184 
    93 lemma permutes_superset: "p permutes S \<Longrightarrow> (\<forall>x \<in> S - T. p x = x) \<Longrightarrow> p permutes T"
   185 lemma permutes_superset:
    94   by (simp add: Ball_def permutes_def) metis
   186   \<open>p permutes T\<close> if \<open>p permutes S\<close> \<open>\<And>x. x \<in> S - T \<Longrightarrow> p x = x\<close>
       
   187 proof -
       
   188   define R U where \<open>R = T \<inter> S\<close> and \<open>U = S - T\<close>
       
   189   then have \<open>T = R \<union> (T - S)\<close> \<open>S = R \<union> U\<close> \<open>R \<inter> U = {}\<close>
       
   190     by auto
       
   191   from that \<open>U = S - T\<close> have \<open>p ` U = U\<close>
       
   192     by simp
       
   193   from \<open>p permutes S\<close> have \<open>bij_betw p (R \<union> U) (R \<union> U)\<close>
       
   194     by (simp add: permutes_imp_bij \<open>S = R \<union> U\<close>)
       
   195   moreover have \<open>bij_betw p U U\<close>
       
   196     using that \<open>U = S - T\<close> by (simp add: bij_betw_def permutes_inj_on)
       
   197   ultimately have \<open>bij_betw p R R\<close>
       
   198     using \<open>R \<inter> U = {}\<close> \<open>R \<inter> U = {}\<close> by (rule bij_betw_partition)
       
   199   then have \<open>p permutes R\<close>
       
   200   proof (rule bij_imp_permutes)
       
   201     fix x
       
   202     assume \<open>x \<notin> R\<close>
       
   203     with \<open>R = T \<inter> S\<close> \<open>p permutes S\<close> show \<open>p x = x\<close>
       
   204       by (cases \<open>x \<in> S\<close>) (auto simp add: permutes_not_in that(2))
       
   205   qed
       
   206   then have \<open>p permutes R \<union> (T - S)\<close>
       
   207     by (rule permutes_subset) simp
       
   208   with \<open>T = R \<union> (T - S)\<close> show ?thesis
       
   209     by simp
       
   210 qed
    95 
   211 
    96 lemma permutes_bij_inv_into: \<^marker>\<open>contributor \<open>Lukas Bulwahn\<close>\<close>
   212 lemma permutes_bij_inv_into: \<^marker>\<open>contributor \<open>Lukas Bulwahn\<close>\<close>
    97   fixes A :: "'a set"
   213   fixes A :: "'a set"
    98     and B :: "'b set"
   214     and B :: "'b set"
    99   assumes "p permutes A"
   215   assumes "p permutes A"
   136   finally show ?thesis ..
   252   finally show ?thesis ..
   137 qed
   253 qed
   138 
   254 
   139 
   255 
   140 subsection \<open>Group properties\<close>
   256 subsection \<open>Group properties\<close>
   141 
       
   142 lemma permutes_id: "id permutes S"
       
   143   by (simp add: permutes_def)
       
   144 
   257 
   145 lemma permutes_compose: "p permutes S \<Longrightarrow> q permutes S \<Longrightarrow> q \<circ> p permutes S"
   258 lemma permutes_compose: "p permutes S \<Longrightarrow> q permutes S \<Longrightarrow> q \<circ> p permutes S"
   146   unfolding permutes_def o_def by metis
   259   unfolding permutes_def o_def by metis
   147 
   260 
   148 lemma permutes_inv:
   261 lemma permutes_inv:
   344         from bp cq have pF: "p permutes F" and qF: "q permutes F"
   457         from bp cq have pF: "p permutes F" and qF: "q permutes F"
   345           by auto
   458           by auto
   346         from pF \<open>x \<notin> F\<close> eq have "b = ?g (b, p) x"
   459         from pF \<open>x \<notin> F\<close> eq have "b = ?g (b, p) x"
   347           by (auto simp: permutes_def Fun.swap_def fun_upd_def fun_eq_iff)
   460           by (auto simp: permutes_def Fun.swap_def fun_upd_def fun_eq_iff)
   348         also from qF \<open>x \<notin> F\<close> eq have "\<dots> = ?g (c, q) x"
   461         also from qF \<open>x \<notin> F\<close> eq have "\<dots> = ?g (c, q) x"
   349           by (auto simp: swap_def fun_upd_def fun_eq_iff)
   462           by (auto simp: fun_upd_def fun_eq_iff)
   350         also from qF \<open>x \<notin> F\<close> have "\<dots> = c"
   463         also from qF \<open>x \<notin> F\<close> have "\<dots> = c"
   351           by (auto simp: permutes_def Fun.swap_def fun_upd_def fun_eq_iff)
   464           by (auto simp: permutes_def Fun.swap_def fun_upd_def fun_eq_iff)
   352         finally have "b = c" .
   465         finally have "b = c" .
   353         then have "Fun.swap x b id = Fun.swap x c id"
   466         then have "Fun.swap x b id = Fun.swap x c id"
   354           by simp
   467           by simp
   384 
   497 
   385 lemma finite_permutations:
   498 lemma finite_permutations:
   386   assumes "finite S"
   499   assumes "finite S"
   387   shows "finite {p. p permutes S}"
   500   shows "finite {p. p permutes S}"
   388   using card_permutations[OF refl assms] by (auto intro: card_ge_0_finite)
   501   using card_permutations[OF refl assms] by (auto intro: card_ge_0_finite)
       
   502 
       
   503 
       
   504 subsection \<open>Hence a sort of induction principle composing by swaps\<close>
       
   505 
       
   506 lemma permutes_induct [consumes 2, case_names id swap]:
       
   507   \<open>P p\<close> if \<open>p permutes S\<close> \<open>finite S\<close>
       
   508   and id: \<open>P id\<close>
       
   509   and swap: \<open>\<And>a b p. a \<in> S \<Longrightarrow> b \<in> S \<Longrightarrow> p permutes S \<Longrightarrow> P p \<Longrightarrow> P (Fun.swap a b id \<circ> p)\<close>
       
   510 using \<open>finite S\<close> \<open>p permutes S\<close> swap proof (induction S arbitrary: p)
       
   511   case empty
       
   512   with id show ?case
       
   513     by (simp only: permutes_empty)
       
   514 next
       
   515   case (insert x S p)
       
   516   define q where \<open>q = Fun.swap x (p x) id \<circ> p\<close>
       
   517   then have swap_q: \<open>Fun.swap x (p x) id \<circ> q = p\<close>
       
   518     by (simp add: o_assoc)
       
   519   from \<open>p permutes insert x S\<close> have \<open>q permutes S\<close>
       
   520     by (simp add: q_def permutes_insert_lemma)
       
   521   then have \<open>q permutes insert x S\<close>
       
   522     by (simp add: permutes_imp_permutes_insert)
       
   523   from \<open>q permutes S\<close> have \<open>P q\<close>
       
   524     by (auto intro: insert.IH insert.prems(2) permutes_imp_permutes_insert)
       
   525   have \<open>x \<in> insert x S\<close>
       
   526     by simp
       
   527   moreover from \<open>p permutes insert x S\<close> have \<open>p x \<in> insert x S\<close>
       
   528     using permutes_in_image [of p \<open>insert x S\<close> x] by simp
       
   529   ultimately have \<open>P (Fun.swap x (p x) id \<circ> q)\<close>
       
   530     using \<open>q permutes insert x S\<close> \<open>P q\<close>
       
   531     by (rule insert.prems(2))
       
   532   then show ?case
       
   533     by (simp add: swap_q)
       
   534 qed
       
   535 
       
   536 lemma permutes_rev_induct [consumes 2, case_names id swap]:
       
   537   \<open>P p\<close> if \<open>p permutes S\<close> \<open>finite S\<close>
       
   538   and id': \<open>P id\<close>
       
   539   and swap': \<open>\<And>a b p. a \<in> S \<Longrightarrow> b \<in> S \<Longrightarrow> p permutes S \<Longrightarrow> P p \<Longrightarrow> P (Fun.swap a b p)\<close>
       
   540 using \<open>p permutes S\<close> \<open>finite S\<close> proof (induction rule: permutes_induct)
       
   541   case id
       
   542   from id' show ?case .
       
   543 next
       
   544   case (swap a b p)
       
   545   have \<open>P (Fun.swap (inv p a) (inv p b) p)\<close>
       
   546     by (rule swap') (auto simp add: swap permutes_in_image permutes_inv)
       
   547   also have \<open>Fun.swap (inv p a) (inv p b) p = Fun.swap a b id \<circ> p\<close>
       
   548     by (rule bij_swap_comp [symmetric]) (rule permutes_bij, rule swap)
       
   549   finally show ?case .
       
   550 qed
   389 
   551 
   390 
   552 
   391 subsection \<open>Permutations of index set for iterated operations\<close>
   553 subsection \<open>Permutations of index set for iterated operations\<close>
   392 
   554 
   393 lemma (in comm_monoid_set) permute:
   555 lemma (in comm_monoid_set) permute:
   832 qed
   994 qed
   833 
   995 
   834 
   996 
   835 subsection \<open>Relation to \<open>permutes\<close>\<close>
   997 subsection \<open>Relation to \<open>permutes\<close>\<close>
   836 
   998 
       
   999 lemma permutes_imp_permutation:
       
  1000   \<open>permutation p\<close> if \<open>finite S\<close> \<open>p permutes S\<close>
       
  1001 proof -
       
  1002   from \<open>p permutes S\<close> have \<open>{x. p x \<noteq> x} \<subseteq> S\<close>
       
  1003     by (auto dest: permutes_not_in)
       
  1004   then have \<open>finite {x. p x \<noteq> x}\<close>
       
  1005     using \<open>finite S\<close> by (rule finite_subset)
       
  1006   moreover from \<open>p permutes S\<close> have \<open>bij p\<close>
       
  1007     by (auto dest: permutes_bij)
       
  1008   ultimately show ?thesis
       
  1009     by (simp add: permutation)
       
  1010 qed
       
  1011 
       
  1012 lemma permutation_permutesE:
       
  1013   assumes \<open>permutation p\<close>
       
  1014   obtains S where \<open>finite S\<close> \<open>p permutes S\<close>
       
  1015 proof -
       
  1016   from assms have fin: \<open>finite {x. p x \<noteq> x}\<close>
       
  1017     by (simp add: permutation)
       
  1018   from assms have \<open>bij p\<close>
       
  1019     by (simp add: permutation)
       
  1020   also have \<open>UNIV = {x. p x \<noteq> x} \<union> {x. p x = x}\<close>
       
  1021     by auto
       
  1022   finally have \<open>bij_betw p {x. p x \<noteq> x} {x. p x \<noteq> x}\<close>
       
  1023     by (rule bij_betw_partition) (auto simp add: bij_betw_fixpoints)
       
  1024   then have \<open>p permutes {x. p x \<noteq> x}\<close>
       
  1025     by (auto intro: bij_imp_permutes)
       
  1026   with fin show thesis ..
       
  1027 qed
       
  1028 
   837 lemma permutation_permutes: "permutation p \<longleftrightarrow> (\<exists>S. finite S \<and> p permutes S)"
  1029 lemma permutation_permutes: "permutation p \<longleftrightarrow> (\<exists>S. finite S \<and> p permutes S)"
   838   unfolding permutation permutes_def bij_iff[symmetric]
  1030   by (auto elim: permutation_permutesE intro: permutes_imp_permutation)
   839   apply (rule iffI, clarify)
       
   840    apply (rule exI[where x="{x. p x \<noteq> x}"])
       
   841    apply simp
       
   842   apply clarsimp
       
   843   apply (rule_tac B="S" in finite_subset)
       
   844    apply auto
       
   845   done
       
   846 
       
   847 
       
   848 subsection \<open>Hence a sort of induction principle composing by swaps\<close>
       
   849 
       
   850 lemma permutes_induct [consumes 2, case_names id swap]:
       
   851   \<open>P p\<close> if \<open>p permutes S\<close> \<open>finite S\<close>
       
   852   and id: \<open>P id\<close>
       
   853   and swap: \<open>\<And>a b p. a \<in> S \<Longrightarrow> b \<in> S \<Longrightarrow> permutation p \<Longrightarrow> P p \<Longrightarrow> P (Fun.swap a b id \<circ> p)\<close>
       
   854 using \<open>finite S\<close> \<open>p permutes S\<close> id swap proof (induction S arbitrary: p)
       
   855   case empty
       
   856   then show ?case by auto
       
   857 next
       
   858   case (insert x F p)
       
   859   let ?r = "Fun.swap x (p x) id \<circ> p"
       
   860   let ?q = "Fun.swap x (p x) id \<circ> ?r"
       
   861   have qp: "?q = p"
       
   862     by (simp add: o_assoc)
       
   863   from permutes_insert_lemma[OF \<open>p permutes insert x F\<close>] insert have Pr: "P ?r"
       
   864     by blast
       
   865   from permutes_in_image[OF \<open>p permutes insert x F\<close>, of x]
       
   866   have pxF: "p x \<in> insert x F"
       
   867     by simp
       
   868   have xF: "x \<in> insert x F"
       
   869     by simp
       
   870   have rp: "permutation ?r"
       
   871     unfolding permutation_permutes
       
   872     using insert.hyps(1) permutes_insert_lemma[OF \<open>p permutes insert x F\<close>]
       
   873     by blast
       
   874   from insert.prems(3)[OF xF pxF rp Pr] qp show ?case
       
   875     by (simp only:)
       
   876 qed
       
   877 
  1031 
   878 
  1032 
   879 subsection \<open>Sign of a permutation as a real number\<close>
  1033 subsection \<open>Sign of a permutation as a real number\<close>
   880 
  1034 
   881 definition sign :: \<open>('a \<Rightarrow> 'a) \<Rightarrow> int\<close> \<comment> \<open>TODO: prefer less generic name\<close>
  1035 definition sign :: \<open>('a \<Rightarrow> 'a) \<Rightarrow> int\<close> \<comment> \<open>TODO: prefer less generic name\<close>
  1081   qed
  1235   qed
  1082   moreover from p have "\<forall>x\<in>A. f x = f' (p' x)"
  1236   moreover from p have "\<forall>x\<in>A. f x = f' (p' x)"
  1083     unfolding p'_def using bij_betwE by fastforce
  1237     unfolding p'_def using bij_betwE by fastforce
  1084   ultimately show ?thesis ..
  1238   ultimately show ?thesis ..
  1085 qed
  1239 qed
  1086 
       
  1087 lemma mset_set_upto_eq_mset_upto: "mset_set {..<n} = mset [0..<n]"
       
  1088   by (induct n) (auto simp: add.commute lessThan_Suc)
       
  1089 
  1240 
  1090 \<comment> \<open>... and derive the existing property:\<close>
  1241 \<comment> \<open>... and derive the existing property:\<close>
  1091 lemma mset_eq_permutation:
  1242 lemma mset_eq_permutation:
  1092   fixes xs ys :: "'a list"
  1243   fixes xs ys :: "'a list"
  1093   assumes mset_eq: "mset xs = mset ys"
  1244   assumes mset_eq: "mset xs = mset ys"