1921 assumes "mset xs = mset ys" |
1921 assumes "mset xs = mset ys" |
1922 shows "length (filter (\<lambda>x. z = x) xs) = length (filter (\<lambda>y. z = y) ys)" |
1922 shows "length (filter (\<lambda>x. z = x) xs) = length (filter (\<lambda>y. z = y) ys)" |
1923 using assms by (metis count_mset) |
1923 using assms by (metis count_mset) |
1924 |
1924 |
1925 lemma fold_multiset_equiv: |
1925 lemma fold_multiset_equiv: |
1926 assumes f: "\<And>x y. x \<in> set xs \<Longrightarrow> y \<in> set xs \<Longrightarrow> f x \<circ> f y = f y \<circ> f x" |
1926 \<open>List.fold f xs = List.fold f ys\<close> |
1927 and equiv: "mset xs = mset ys" |
1927 if f: \<open>\<And>x y. x \<in> set xs \<Longrightarrow> y \<in> set xs \<Longrightarrow> f x \<circ> f y = f y \<circ> f x\<close> |
1928 shows "List.fold f xs = List.fold f ys" |
1928 and \<open>mset xs = mset ys\<close> |
1929 using f equiv [symmetric] |
1929 using f \<open>mset xs = mset ys\<close> [symmetric] proof (induction xs arbitrary: ys) |
1930 proof (induct xs arbitrary: ys) |
|
1931 case Nil |
1930 case Nil |
1932 then show ?case by simp |
1931 then show ?case by simp |
1933 next |
1932 next |
1934 case (Cons x xs) |
1933 case (Cons x xs) |
1935 then have *: "set ys = set (x # xs)" |
1934 then have *: \<open>set ys = set (x # xs)\<close> |
1936 by (blast dest: mset_eq_setD) |
1935 by (blast dest: mset_eq_setD) |
1937 have "\<And>x y. x \<in> set ys \<Longrightarrow> y \<in> set ys \<Longrightarrow> f x \<circ> f y = f y \<circ> f x" |
1936 have \<open>\<And>x y. x \<in> set ys \<Longrightarrow> y \<in> set ys \<Longrightarrow> f x \<circ> f y = f y \<circ> f x\<close> |
1938 by (rule Cons.prems(1)) (simp_all add: *) |
1937 by (rule Cons.prems(1)) (simp_all add: *) |
1939 moreover from * have "x \<in> set ys" |
1938 moreover from * have \<open>x \<in> set ys\<close> |
1940 by simp |
1939 by simp |
1941 ultimately have "List.fold f ys = List.fold f (remove1 x ys) \<circ> f x" |
1940 ultimately have \<open>List.fold f ys = List.fold f (remove1 x ys) \<circ> f x\<close> |
1942 by (fact fold_remove1_split) |
1941 by (fact fold_remove1_split) |
1943 moreover from Cons.prems have "List.fold f xs = List.fold f (remove1 x ys)" |
1942 moreover from Cons.prems have \<open>List.fold f xs = List.fold f (remove1 x ys)\<close> |
1944 by (auto intro: Cons.hyps) |
1943 by (auto intro: Cons.IH) |
1945 ultimately show ?case by simp |
1944 ultimately show ?case |
|
1945 by simp |
|
1946 qed |
|
1947 |
|
1948 lemma fold_permuted_eq: |
|
1949 \<open>List.fold (\<odot>) xs z = List.fold (\<odot>) ys z\<close> |
|
1950 if \<open>mset xs = mset ys\<close> |
|
1951 and \<open>P z\<close> and P: \<open>\<And>x z. x \<in> set xs \<Longrightarrow> P z \<Longrightarrow> P (x \<odot> z)\<close> |
|
1952 and f: \<open>\<And>x y z. x \<in> set xs \<Longrightarrow> y \<in> set xs \<Longrightarrow> P z \<Longrightarrow> x \<odot> (y \<odot> z) = y \<odot> (x \<odot> z)\<close> |
|
1953 for f (infixl \<open>\<odot>\<close> 70) |
|
1954 using \<open>P z\<close> P f \<open>mset xs = mset ys\<close> [symmetric] proof (induction xs arbitrary: ys z) |
|
1955 case Nil |
|
1956 then show ?case by simp |
|
1957 next |
|
1958 case (Cons x xs) |
|
1959 then have *: \<open>set ys = set (x # xs)\<close> |
|
1960 by (blast dest: mset_eq_setD) |
|
1961 have \<open>P z\<close> |
|
1962 by (fact Cons.prems(1)) |
|
1963 moreover have \<open>\<And>x z. x \<in> set ys \<Longrightarrow> P z \<Longrightarrow> P (x \<odot> z)\<close> |
|
1964 by (rule Cons.prems(2)) (simp_all add: *) |
|
1965 moreover have \<open>\<And>x y z. x \<in> set ys \<Longrightarrow> y \<in> set ys \<Longrightarrow> P z \<Longrightarrow> x \<odot> (y \<odot> z) = y \<odot> (x \<odot> z)\<close> |
|
1966 by (rule Cons.prems(3)) (simp_all add: *) |
|
1967 moreover from * have \<open>x \<in> set ys\<close> |
|
1968 by simp |
|
1969 ultimately have \<open>fold (\<odot>) ys z = fold (\<odot>) (remove1 x ys) (x \<odot> z)\<close> |
|
1970 by (induction ys arbitrary: z) auto |
|
1971 moreover from Cons.prems have \<open>fold (\<odot>) xs (x \<odot> z) = fold (\<odot>) (remove1 x ys) (x \<odot> z)\<close> |
|
1972 by (auto intro: Cons.IH) |
|
1973 ultimately show ?case |
|
1974 by simp |
1946 qed |
1975 qed |
1947 |
1976 |
1948 lemma mset_shuffles: "zs \<in> shuffles xs ys \<Longrightarrow> mset zs = mset xs + mset ys" |
1977 lemma mset_shuffles: "zs \<in> shuffles xs ys \<Longrightarrow> mset zs = mset xs + mset ys" |
1949 by (induction xs ys arbitrary: zs rule: shuffles.induct) auto |
1978 by (induction xs ys arbitrary: zs rule: shuffles.induct) auto |
1950 |
1979 |