817 "arg_min f P = (SOME x. is_arg_min f P x)" |
817 "arg_min f P = (SOME x. is_arg_min f P x)" |
818 |
818 |
819 abbreviation arg_min_on :: "('a \<Rightarrow> 'b::ord) \<Rightarrow> 'a set \<Rightarrow> 'a" where |
819 abbreviation arg_min_on :: "('a \<Rightarrow> 'b::ord) \<Rightarrow> 'a set \<Rightarrow> 'a" where |
820 "arg_min_on f S \<equiv> arg_min f (\<lambda>x. x \<in> S)" |
820 "arg_min_on f S \<equiv> arg_min f (\<lambda>x. x \<in> S)" |
821 |
821 |
|
822 syntax |
|
823 "_arg_min" :: "('a \<Rightarrow> 'b) \<Rightarrow> pttrn \<Rightarrow> bool \<Rightarrow> 'a" |
|
824 ("(3ARG'_MIN _ _./ _)" [0, 0, 10] 10) |
|
825 translations |
|
826 "ARG_MIN f x. P" \<rightleftharpoons> "CONST arg_min f (\<lambda>x. P)" |
|
827 |
822 lemma is_arg_min_linorder: fixes f :: "'a \<Rightarrow> 'b :: linorder" |
828 lemma is_arg_min_linorder: fixes f :: "'a \<Rightarrow> 'b :: linorder" |
823 shows "is_arg_min f P x = (P x \<and> (\<forall>y. P y \<longrightarrow> f x \<le> f y))" |
829 shows "is_arg_min f P x = (P x \<and> (\<forall>y. P y \<longrightarrow> f x \<le> f y))" |
824 by(auto simp add: is_arg_min_def) |
830 by(auto simp add: is_arg_min_def) |
825 |
831 |
826 lemma arg_min_nat_lemma: "P k \<Longrightarrow> P(arg_min m P) \<and> (\<forall>y. P y \<longrightarrow> m (arg_min m P) \<le> m y)" |
832 lemma arg_minI: |
|
833 "\<lbrakk> P x; |
|
834 \<And>y. P y \<Longrightarrow> \<not> f y < f x; |
|
835 \<And>x. \<lbrakk> P x; \<forall>y. P y \<longrightarrow> \<not> f y < f x \<rbrakk> \<Longrightarrow> Q x \<rbrakk> |
|
836 \<Longrightarrow> Q (arg_min f P)" |
|
837 apply (simp add: arg_min_def is_arg_min_def) |
|
838 apply (rule someI2_ex) |
|
839 apply blast |
|
840 apply blast |
|
841 done |
|
842 |
|
843 lemma arg_min_equality: |
|
844 "P k \<Longrightarrow> (\<And>x. P x \<Longrightarrow> f k \<le> f x) \<Longrightarrow> f (arg_min f P) = f k" |
|
845 for f :: "_ \<Rightarrow> 'a::order" |
|
846 apply (rule arg_minI) |
|
847 apply assumption |
|
848 apply (simp add: less_le_not_le) |
|
849 by (metis le_less) |
|
850 |
|
851 lemma arg_min_nat_lemma: |
|
852 "P k \<Longrightarrow> P(arg_min m P) \<and> (\<forall>y. P y \<longrightarrow> m (arg_min m P) \<le> m y)" |
827 for m :: "'a \<Rightarrow> nat" |
853 for m :: "'a \<Rightarrow> nat" |
828 apply (simp add: arg_min_def is_arg_min_linorder) |
854 apply (simp add: arg_min_def is_arg_min_linorder) |
829 apply (rule someI_ex) |
855 apply (rule someI_ex) |
830 apply (erule ex_has_least_nat) |
856 apply (erule ex_has_least_nat) |
831 done |
857 done |
832 |
858 |
833 lemmas arg_min_natI = arg_min_nat_lemma [THEN conjunct1] |
859 lemmas arg_min_natI = arg_min_nat_lemma [THEN conjunct1] |
|
860 |
|
861 lemma is_arg_min_arg_min_nat: fixes m :: "'a \<Rightarrow> nat" |
|
862 shows "P x \<Longrightarrow> is_arg_min m P (arg_min m P)" |
|
863 by (metis arg_min_nat_lemma is_arg_min_linorder) |
834 |
864 |
835 lemma arg_min_nat_le: "P x \<Longrightarrow> m (arg_min m P) \<le> m x" |
865 lemma arg_min_nat_le: "P x \<Longrightarrow> m (arg_min m P) \<le> m x" |
836 for m :: "'a \<Rightarrow> nat" |
866 for m :: "'a \<Rightarrow> nat" |
837 by (rule arg_min_nat_lemma [THEN conjunct2, THEN spec, THEN mp]) |
867 by (rule arg_min_nat_lemma [THEN conjunct2, THEN spec, THEN mp]) |
838 |
868 |