2505 |
2521 |
2506 lemma (in complete_lattice) SUPR_set_fold: |
2522 lemma (in complete_lattice) SUPR_set_fold: |
2507 "SUPR (set xs) f = foldl (\<lambda>y x. sup (f x) y) bot xs" |
2523 "SUPR (set xs) f = foldl (\<lambda>y x. sup (f x) y) bot xs" |
2508 unfolding SUPR_def set_map [symmetric] Sup_set_fold foldl_map |
2524 unfolding SUPR_def set_map [symmetric] Sup_set_fold foldl_map |
2509 by (simp add: sup_commute) |
2525 by (simp add: sup_commute) |
2510 |
|
2511 |
|
2512 subsubsection {* List summation: @{const listsum} and @{text"\<Sum>"}*} |
|
2513 |
|
2514 lemma listsum_append [simp]: "listsum (xs @ ys) = listsum xs + listsum ys" |
|
2515 by (induct xs) (simp_all add:add_assoc) |
|
2516 |
|
2517 lemma listsum_rev [simp]: |
|
2518 fixes xs :: "'a\<Colon>comm_monoid_add list" |
|
2519 shows "listsum (rev xs) = listsum xs" |
|
2520 by (induct xs) (simp_all add:add_ac) |
|
2521 |
|
2522 lemma listsum_map_remove1: |
|
2523 fixes f :: "'a \<Rightarrow> ('b::comm_monoid_add)" |
|
2524 shows "x : set xs \<Longrightarrow> listsum(map f xs) = f x + listsum(map f (remove1 x xs))" |
|
2525 by (induct xs)(auto simp add:add_ac) |
|
2526 |
|
2527 lemma list_size_conv_listsum: |
|
2528 "list_size f xs = listsum (map f xs) + size xs" |
|
2529 by(induct xs) auto |
|
2530 |
|
2531 lemma listsum_foldr: "listsum xs = foldr (op +) xs 0" |
|
2532 by (induct xs) auto |
|
2533 |
|
2534 lemma length_concat: "length (concat xss) = listsum (map length xss)" |
|
2535 by (induct xss) simp_all |
|
2536 |
|
2537 lemma listsum_map_filter: |
|
2538 fixes f :: "'a \<Rightarrow> 'b \<Colon> comm_monoid_add" |
|
2539 assumes "\<And> x. \<lbrakk> x \<in> set xs ; \<not> P x \<rbrakk> \<Longrightarrow> f x = 0" |
|
2540 shows "listsum (map f (filter P xs)) = listsum (map f xs)" |
|
2541 using assms by (induct xs) auto |
|
2542 |
|
2543 text{* For efficient code generation --- |
|
2544 @{const listsum} is not tail recursive but @{const foldl} is. *} |
|
2545 lemma listsum[code_unfold]: "listsum xs = foldl (op +) 0 xs" |
|
2546 by(simp add:listsum_foldr foldl_foldr1) |
|
2547 |
|
2548 lemma distinct_listsum_conv_Setsum: |
|
2549 "distinct xs \<Longrightarrow> listsum xs = Setsum(set xs)" |
|
2550 by (induct xs) simp_all |
|
2551 |
|
2552 lemma listsum_eq_0_nat_iff_nat[simp]: |
|
2553 "listsum ns = (0::nat) \<longleftrightarrow> (\<forall> n \<in> set ns. n = 0)" |
|
2554 by(simp add: listsum) |
|
2555 |
|
2556 lemma elem_le_listsum_nat: "k<size ns \<Longrightarrow> ns!k <= listsum(ns::nat list)" |
|
2557 apply(induct ns arbitrary: k) |
|
2558 apply simp |
|
2559 apply(fastsimp simp add:nth_Cons split: nat.split) |
|
2560 done |
|
2561 |
|
2562 lemma listsum_update_nat: "k<size ns \<Longrightarrow> |
|
2563 listsum (ns[k := (n::nat)]) = listsum ns + n - ns!k" |
|
2564 apply(induct ns arbitrary:k) |
|
2565 apply (auto split:nat.split) |
|
2566 apply(drule elem_le_listsum_nat) |
|
2567 apply arith |
|
2568 done |
|
2569 |
|
2570 text{* Some syntactic sugar for summing a function over a list: *} |
|
2571 |
|
2572 syntax |
|
2573 "_listsum" :: "pttrn => 'a list => 'b => 'b" ("(3SUM _<-_. _)" [0, 51, 10] 10) |
|
2574 syntax (xsymbols) |
|
2575 "_listsum" :: "pttrn => 'a list => 'b => 'b" ("(3\<Sum>_\<leftarrow>_. _)" [0, 51, 10] 10) |
|
2576 syntax (HTML output) |
|
2577 "_listsum" :: "pttrn => 'a list => 'b => 'b" ("(3\<Sum>_\<leftarrow>_. _)" [0, 51, 10] 10) |
|
2578 |
|
2579 translations -- {* Beware of argument permutation! *} |
|
2580 "SUM x<-xs. b" == "CONST listsum (CONST map (%x. b) xs)" |
|
2581 "\<Sum>x\<leftarrow>xs. b" == "CONST listsum (CONST map (%x. b) xs)" |
|
2582 |
|
2583 lemma listsum_triv: "(\<Sum>x\<leftarrow>xs. r) = of_nat (length xs) * r" |
|
2584 by (induct xs) (simp_all add: left_distrib) |
|
2585 |
|
2586 lemma listsum_0 [simp]: "(\<Sum>x\<leftarrow>xs. 0) = 0" |
|
2587 by (induct xs) (simp_all add: left_distrib) |
|
2588 |
|
2589 text{* For non-Abelian groups @{text xs} needs to be reversed on one side: *} |
|
2590 lemma uminus_listsum_map: |
|
2591 fixes f :: "'a \<Rightarrow> 'b\<Colon>ab_group_add" |
|
2592 shows "- listsum (map f xs) = (listsum (map (uminus o f) xs))" |
|
2593 by (induct xs) simp_all |
|
2594 |
|
2595 lemma listsum_addf: |
|
2596 fixes f g :: "'a \<Rightarrow> 'b::comm_monoid_add" |
|
2597 shows "(\<Sum>x\<leftarrow>xs. f x + g x) = listsum (map f xs) + listsum (map g xs)" |
|
2598 by (induct xs) (simp_all add: algebra_simps) |
|
2599 |
|
2600 lemma listsum_subtractf: |
|
2601 fixes f g :: "'a \<Rightarrow> 'b::ab_group_add" |
|
2602 shows "(\<Sum>x\<leftarrow>xs. f x - g x) = listsum (map f xs) - listsum (map g xs)" |
|
2603 by (induct xs) simp_all |
|
2604 |
|
2605 lemma listsum_const_mult: |
|
2606 fixes f :: "'a \<Rightarrow> 'b::semiring_0" |
|
2607 shows "(\<Sum>x\<leftarrow>xs. c * f x) = c * (\<Sum>x\<leftarrow>xs. f x)" |
|
2608 by (induct xs, simp_all add: algebra_simps) |
|
2609 |
|
2610 lemma listsum_mult_const: |
|
2611 fixes f :: "'a \<Rightarrow> 'b::semiring_0" |
|
2612 shows "(\<Sum>x\<leftarrow>xs. f x * c) = (\<Sum>x\<leftarrow>xs. f x) * c" |
|
2613 by (induct xs, simp_all add: algebra_simps) |
|
2614 |
|
2615 lemma listsum_abs: |
|
2616 fixes xs :: "'a::ordered_ab_group_add_abs list" |
|
2617 shows "\<bar>listsum xs\<bar> \<le> listsum (map abs xs)" |
|
2618 by (induct xs, simp, simp add: order_trans [OF abs_triangle_ineq]) |
|
2619 |
|
2620 lemma listsum_mono: |
|
2621 fixes f g :: "'a \<Rightarrow> 'b::{comm_monoid_add, ordered_ab_semigroup_add}" |
|
2622 shows "(\<And>x. x \<in> set xs \<Longrightarrow> f x \<le> g x) \<Longrightarrow> (\<Sum>x\<leftarrow>xs. f x) \<le> (\<Sum>x\<leftarrow>xs. g x)" |
|
2623 by (induct xs, simp, simp add: add_mono) |
|
2624 |
2526 |
2625 |
2527 |
2626 subsubsection {* @{text upt} *} |
2528 subsubsection {* @{text upt} *} |
2627 |
2529 |
2628 lemma upt_rec[code]: "[i..<j] = (if i<j then i#[Suc i..<j] else [])" |
2530 lemma upt_rec[code]: "[i..<j] = (if i<j then i#[Suc i..<j] else [])" |
2957 shows "distinct (butlast xs)" |
2859 shows "distinct (butlast xs)" |
2958 proof - |
2860 proof - |
2959 from `xs \<noteq> []` obtain ys y where "xs = ys @ [y]" by (cases xs rule: rev_cases) auto |
2861 from `xs \<noteq> []` obtain ys y where "xs = ys @ [y]" by (cases xs rule: rev_cases) auto |
2960 with `distinct xs` show ?thesis by simp |
2862 with `distinct xs` show ?thesis by simp |
2961 qed |
2863 qed |
|
2864 |
|
2865 |
|
2866 subsubsection {* List summation: @{const listsum} and @{text"\<Sum>"}*} |
|
2867 |
|
2868 lemma listsum_append [simp]: "listsum (xs @ ys) = listsum xs + listsum ys" |
|
2869 by (induct xs) (simp_all add:add_assoc) |
|
2870 |
|
2871 lemma listsum_rev [simp]: |
|
2872 fixes xs :: "'a\<Colon>comm_monoid_add list" |
|
2873 shows "listsum (rev xs) = listsum xs" |
|
2874 by (induct xs) (simp_all add:add_ac) |
|
2875 |
|
2876 lemma listsum_map_remove1: |
|
2877 fixes f :: "'a \<Rightarrow> ('b::comm_monoid_add)" |
|
2878 shows "x : set xs \<Longrightarrow> listsum(map f xs) = f x + listsum(map f (remove1 x xs))" |
|
2879 by (induct xs)(auto simp add:add_ac) |
|
2880 |
|
2881 lemma list_size_conv_listsum: |
|
2882 "list_size f xs = listsum (map f xs) + size xs" |
|
2883 by(induct xs) auto |
|
2884 |
|
2885 lemma listsum_foldr: "listsum xs = foldr (op +) xs 0" |
|
2886 by (induct xs) auto |
|
2887 |
|
2888 lemma length_concat: "length (concat xss) = listsum (map length xss)" |
|
2889 by (induct xss) simp_all |
|
2890 |
|
2891 lemma listsum_map_filter: |
|
2892 fixes f :: "'a \<Rightarrow> 'b \<Colon> comm_monoid_add" |
|
2893 assumes "\<And> x. \<lbrakk> x \<in> set xs ; \<not> P x \<rbrakk> \<Longrightarrow> f x = 0" |
|
2894 shows "listsum (map f (filter P xs)) = listsum (map f xs)" |
|
2895 using assms by (induct xs) auto |
|
2896 |
|
2897 text{* For efficient code generation --- |
|
2898 @{const listsum} is not tail recursive but @{const foldl} is. *} |
|
2899 lemma listsum[code_unfold]: "listsum xs = foldl (op +) 0 xs" |
|
2900 by(simp add:listsum_foldr foldl_foldr1) |
|
2901 |
|
2902 lemma distinct_listsum_conv_Setsum: |
|
2903 "distinct xs \<Longrightarrow> listsum xs = Setsum(set xs)" |
|
2904 by (induct xs) simp_all |
|
2905 |
|
2906 lemma listsum_eq_0_nat_iff_nat[simp]: |
|
2907 "listsum ns = (0::nat) \<longleftrightarrow> (\<forall> n \<in> set ns. n = 0)" |
|
2908 by(simp add: listsum) |
|
2909 |
|
2910 lemma elem_le_listsum_nat: "k<size ns \<Longrightarrow> ns!k <= listsum(ns::nat list)" |
|
2911 apply(induct ns arbitrary: k) |
|
2912 apply simp |
|
2913 apply(fastsimp simp add:nth_Cons split: nat.split) |
|
2914 done |
|
2915 |
|
2916 lemma listsum_update_nat: "k<size ns \<Longrightarrow> |
|
2917 listsum (ns[k := (n::nat)]) = listsum ns + n - ns!k" |
|
2918 apply(induct ns arbitrary:k) |
|
2919 apply (auto split:nat.split) |
|
2920 apply(drule elem_le_listsum_nat) |
|
2921 apply arith |
|
2922 done |
|
2923 |
|
2924 text{* Some syntactic sugar for summing a function over a list: *} |
|
2925 |
|
2926 syntax |
|
2927 "_listsum" :: "pttrn => 'a list => 'b => 'b" ("(3SUM _<-_. _)" [0, 51, 10] 10) |
|
2928 syntax (xsymbols) |
|
2929 "_listsum" :: "pttrn => 'a list => 'b => 'b" ("(3\<Sum>_\<leftarrow>_. _)" [0, 51, 10] 10) |
|
2930 syntax (HTML output) |
|
2931 "_listsum" :: "pttrn => 'a list => 'b => 'b" ("(3\<Sum>_\<leftarrow>_. _)" [0, 51, 10] 10) |
|
2932 |
|
2933 translations -- {* Beware of argument permutation! *} |
|
2934 "SUM x<-xs. b" == "CONST listsum (CONST map (%x. b) xs)" |
|
2935 "\<Sum>x\<leftarrow>xs. b" == "CONST listsum (CONST map (%x. b) xs)" |
|
2936 |
|
2937 lemma listsum_triv: "(\<Sum>x\<leftarrow>xs. r) = of_nat (length xs) * r" |
|
2938 by (induct xs) (simp_all add: left_distrib) |
|
2939 |
|
2940 lemma listsum_0 [simp]: "(\<Sum>x\<leftarrow>xs. 0) = 0" |
|
2941 by (induct xs) (simp_all add: left_distrib) |
|
2942 |
|
2943 text{* For non-Abelian groups @{text xs} needs to be reversed on one side: *} |
|
2944 lemma uminus_listsum_map: |
|
2945 fixes f :: "'a \<Rightarrow> 'b\<Colon>ab_group_add" |
|
2946 shows "- listsum (map f xs) = (listsum (map (uminus o f) xs))" |
|
2947 by (induct xs) simp_all |
|
2948 |
|
2949 lemma listsum_addf: |
|
2950 fixes f g :: "'a \<Rightarrow> 'b::comm_monoid_add" |
|
2951 shows "(\<Sum>x\<leftarrow>xs. f x + g x) = listsum (map f xs) + listsum (map g xs)" |
|
2952 by (induct xs) (simp_all add: algebra_simps) |
|
2953 |
|
2954 lemma listsum_subtractf: |
|
2955 fixes f g :: "'a \<Rightarrow> 'b::ab_group_add" |
|
2956 shows "(\<Sum>x\<leftarrow>xs. f x - g x) = listsum (map f xs) - listsum (map g xs)" |
|
2957 by (induct xs) simp_all |
|
2958 |
|
2959 lemma listsum_const_mult: |
|
2960 fixes f :: "'a \<Rightarrow> 'b::semiring_0" |
|
2961 shows "(\<Sum>x\<leftarrow>xs. c * f x) = c * (\<Sum>x\<leftarrow>xs. f x)" |
|
2962 by (induct xs, simp_all add: algebra_simps) |
|
2963 |
|
2964 lemma listsum_mult_const: |
|
2965 fixes f :: "'a \<Rightarrow> 'b::semiring_0" |
|
2966 shows "(\<Sum>x\<leftarrow>xs. f x * c) = (\<Sum>x\<leftarrow>xs. f x) * c" |
|
2967 by (induct xs, simp_all add: algebra_simps) |
|
2968 |
|
2969 lemma listsum_abs: |
|
2970 fixes xs :: "'a::ordered_ab_group_add_abs list" |
|
2971 shows "\<bar>listsum xs\<bar> \<le> listsum (map abs xs)" |
|
2972 by (induct xs, simp, simp add: order_trans [OF abs_triangle_ineq]) |
|
2973 |
|
2974 lemma listsum_mono: |
|
2975 fixes f g :: "'a \<Rightarrow> 'b::{comm_monoid_add, ordered_ab_semigroup_add}" |
|
2976 shows "(\<And>x. x \<in> set xs \<Longrightarrow> f x \<le> g x) \<Longrightarrow> (\<Sum>x\<leftarrow>xs. f x) \<le> (\<Sum>x\<leftarrow>xs. g x)" |
|
2977 by (induct xs, simp, simp add: add_mono) |
|
2978 |
|
2979 lemma listsum_distinct_conv_setsum_set: |
|
2980 "distinct xs \<Longrightarrow> listsum (map f xs) = setsum f (set xs)" |
|
2981 by (induct xs) simp_all |
|
2982 |
|
2983 lemma interv_listsum_conv_setsum_set_nat: |
|
2984 "listsum (map f [m..<n]) = setsum f (set [m..<n])" |
|
2985 by (simp add: listsum_distinct_conv_setsum_set) |
|
2986 |
|
2987 lemma interv_listsum_conv_setsum_set_int: |
|
2988 "listsum (map f [k..l]) = setsum f (set [k..l])" |
|
2989 by (simp add: listsum_distinct_conv_setsum_set) |
|
2990 |
|
2991 text {* General equivalence between @{const listsum} and @{const setsum} *} |
|
2992 lemma listsum_setsum_nth: |
|
2993 "listsum xs = (\<Sum> i = 0 ..< length xs. xs ! i)" |
|
2994 using interv_listsum_conv_setsum_set_nat [of "op ! xs" 0 "length xs"] by (simp add: map_nth) |
2962 |
2995 |
2963 |
2996 |
2964 subsubsection {* @{const insert} *} |
2997 subsubsection {* @{const insert} *} |
2965 |
2998 |
2966 lemma in_set_insert [simp]: |
2999 lemma in_set_insert [simp]: |
4511 lemma transfer_nat_int_fold1: "fold f l x = |
4544 lemma transfer_nat_int_fold1: "fold f l x = |
4512 fold (%x. f (nat x)) (embed_list l) x"; |
4545 fold (%x. f (nat x)) (embed_list l) x"; |
4513 *) |
4546 *) |
4514 |
4547 |
4515 |
4548 |
4516 subsection {* Code generator *} |
4549 subsection {* Code generation *} |
4517 |
4550 |
4518 subsubsection {* Setup *} |
4551 subsubsection {* Counterparts for set-related operations *} |
|
4552 |
|
4553 definition member :: "'a list \<Rightarrow> 'a \<Rightarrow> bool" where |
|
4554 [code_post]: "member xs x \<longleftrightarrow> x \<in> set xs" |
|
4555 |
|
4556 text {* |
|
4557 Only use @{text member} for generating executable code. Otherwise use |
|
4558 @{prop "x \<in> set xs"} instead --- it is much easier to reason about. |
|
4559 *} |
|
4560 |
|
4561 lemma member_set: |
|
4562 "member = set" |
|
4563 by (simp add: expand_fun_eq member_def mem_def) |
|
4564 |
|
4565 lemma member_rec [code]: |
|
4566 "member (x # xs) y \<longleftrightarrow> x = y \<or> member xs y" |
|
4567 "member [] y \<longleftrightarrow> False" |
|
4568 by (auto simp add: member_def) |
|
4569 |
|
4570 lemma in_set_member [code_unfold]: |
|
4571 "x \<in> set xs \<longleftrightarrow> member xs x" |
|
4572 by (simp add: member_def) |
|
4573 |
|
4574 declare INFI_def [code_unfold] |
|
4575 declare SUPR_def [code_unfold] |
|
4576 |
|
4577 declare set_map [symmetric, code_unfold] |
|
4578 |
|
4579 definition list_all :: "('a \<Rightarrow> bool) \<Rightarrow> 'a list \<Rightarrow> bool" where |
|
4580 list_all_iff [code_post]: "list_all P xs \<longleftrightarrow> (\<forall>x \<in> set xs. P x)" |
|
4581 |
|
4582 definition list_ex :: "('a \<Rightarrow> bool) \<Rightarrow> 'a list \<Rightarrow> bool" where |
|
4583 list_ex_iff [code_post]: "list_ex P xs \<longleftrightarrow> (\<exists>x \<in> set xs. P x)" |
|
4584 |
|
4585 text {* |
|
4586 Usually you should prefer @{text "\<forall>x\<in>set xs"} and @{text "\<exists>x\<in>set xs"} |
|
4587 over @{const list_all} and @{const list_ex} in specifications. |
|
4588 *} |
|
4589 |
|
4590 lemma list_all_simps [simp, code]: |
|
4591 "list_all P (x # xs) \<longleftrightarrow> P x \<and> list_all P xs" |
|
4592 "list_all P [] \<longleftrightarrow> True" |
|
4593 by (simp_all add: list_all_iff) |
|
4594 |
|
4595 lemma list_ex_simps [simp, code]: |
|
4596 "list_ex P (x # xs) \<longleftrightarrow> P x \<or> list_ex P xs" |
|
4597 "list_ex P [] \<longleftrightarrow> False" |
|
4598 by (simp_all add: list_ex_iff) |
|
4599 |
|
4600 lemma Ball_set_list_all [code_unfold]: |
|
4601 "Ball (set xs) P \<longleftrightarrow> list_all P xs" |
|
4602 by (simp add: list_all_iff) |
|
4603 |
|
4604 lemma Bex_set_list_ex [code_unfold]: |
|
4605 "Bex (set xs) P \<longleftrightarrow> list_ex P xs" |
|
4606 by (simp add: list_ex_iff) |
|
4607 |
|
4608 lemma list_all_append [simp]: |
|
4609 "list_all P (xs @ ys) \<longleftrightarrow> list_all P xs \<and> list_all P ys" |
|
4610 by (auto simp add: list_all_iff) |
|
4611 |
|
4612 lemma list_ex_append [simp]: |
|
4613 "list_ex P (xs @ ys) \<longleftrightarrow> list_ex P xs \<or> list_ex P ys" |
|
4614 by (auto simp add: list_ex_iff) |
|
4615 |
|
4616 lemma list_all_rev [simp]: |
|
4617 "list_all P (rev xs) \<longleftrightarrow> list_all P xs" |
|
4618 by (simp add: list_all_iff) |
|
4619 |
|
4620 lemma list_ex_rev [simp]: |
|
4621 "list_ex P (rev xs) \<longleftrightarrow> list_ex P xs" |
|
4622 by (simp add: list_ex_iff) |
|
4623 |
|
4624 lemma list_all_length: |
|
4625 "list_all P xs \<longleftrightarrow> (\<forall>n < length xs. P (xs ! n))" |
|
4626 by (auto simp add: list_all_iff set_conv_nth) |
|
4627 |
|
4628 lemma list_ex_length: |
|
4629 "list_ex P xs \<longleftrightarrow> (\<exists>n < length xs. P (xs ! n))" |
|
4630 by (auto simp add: list_ex_iff set_conv_nth) |
|
4631 |
|
4632 lemma list_all_cong [fundef_cong]: |
|
4633 "xs = ys \<Longrightarrow> (\<And>x. x \<in> set ys \<Longrightarrow> f x = g x) \<Longrightarrow> list_all f xs = list_all g ys" |
|
4634 by (simp add: list_all_iff) |
|
4635 |
|
4636 lemma list_any_cong [fundef_cong]: |
|
4637 "xs = ys \<Longrightarrow> (\<And>x. x \<in> set ys \<Longrightarrow> f x = g x) \<Longrightarrow> list_ex f xs = list_ex g ys" |
|
4638 by (simp add: list_ex_iff) |
|
4639 |
|
4640 text {* Bounded quantification and summation over nats. *} |
|
4641 |
|
4642 lemma atMost_upto [code_unfold]: |
|
4643 "{..n} = set [0..<Suc n]" |
|
4644 by auto |
|
4645 |
|
4646 lemma atLeast_upt [code_unfold]: |
|
4647 "{..<n} = set [0..<n]" |
|
4648 by auto |
|
4649 |
|
4650 lemma greaterThanLessThan_upt [code_unfold]: |
|
4651 "{n<..<m} = set [Suc n..<m]" |
|
4652 by auto |
|
4653 |
|
4654 lemmas atLeastLessThan_upt [code_unfold] = set_upt [symmetric] |
|
4655 |
|
4656 lemma greaterThanAtMost_upt [code_unfold]: |
|
4657 "{n<..m} = set [Suc n..<Suc m]" |
|
4658 by auto |
|
4659 |
|
4660 lemma atLeastAtMost_upt [code_unfold]: |
|
4661 "{n..m} = set [n..<Suc m]" |
|
4662 by auto |
|
4663 |
|
4664 lemma all_nat_less_eq [code_unfold]: |
|
4665 "(\<forall>m<n\<Colon>nat. P m) \<longleftrightarrow> (\<forall>m \<in> {0..<n}. P m)" |
|
4666 by auto |
|
4667 |
|
4668 lemma ex_nat_less_eq [code_unfold]: |
|
4669 "(\<exists>m<n\<Colon>nat. P m) \<longleftrightarrow> (\<exists>m \<in> {0..<n}. P m)" |
|
4670 by auto |
|
4671 |
|
4672 lemma all_nat_less [code_unfold]: |
|
4673 "(\<forall>m\<le>n\<Colon>nat. P m) \<longleftrightarrow> (\<forall>m \<in> {0..n}. P m)" |
|
4674 by auto |
|
4675 |
|
4676 lemma ex_nat_less [code_unfold]: |
|
4677 "(\<exists>m\<le>n\<Colon>nat. P m) \<longleftrightarrow> (\<exists>m \<in> {0..n}. P m)" |
|
4678 by auto |
|
4679 |
|
4680 lemma setsum_set_upt_conv_listsum_nat [code_unfold]: |
|
4681 "setsum f (set [m..<n]) = listsum (map f [m..<n])" |
|
4682 by (simp add: interv_listsum_conv_setsum_set_nat) |
|
4683 |
|
4684 text {* Summation over ints. *} |
|
4685 |
|
4686 lemma greaterThanLessThan_upto [code_unfold]: |
|
4687 "{i<..<j::int} = set [i+1..j - 1]" |
|
4688 by auto |
|
4689 |
|
4690 lemma atLeastLessThan_upto [code_unfold]: |
|
4691 "{i..<j::int} = set [i..j - 1]" |
|
4692 by auto |
|
4693 |
|
4694 lemma greaterThanAtMost_upto [code_unfold]: |
|
4695 "{i<..j::int} = set [i+1..j]" |
|
4696 by auto |
|
4697 |
|
4698 lemmas atLeastAtMost_upto [code_unfold] = set_upto [symmetric] |
|
4699 |
|
4700 lemma setsum_set_upto_conv_listsum_int [code_unfold]: |
|
4701 "setsum f (set [i..j::int]) = listsum (map f [i..j])" |
|
4702 by (simp add: interv_listsum_conv_setsum_set_int) |
|
4703 |
|
4704 |
|
4705 subsubsection {* Optimizing by rewriting *} |
|
4706 |
|
4707 definition null :: "'a list \<Rightarrow> bool" where |
|
4708 [code_post]: "null xs \<longleftrightarrow> xs = []" |
|
4709 |
|
4710 text {* |
|
4711 Efficient emptyness check is implemented by @{const null}. |
|
4712 *} |
|
4713 |
|
4714 lemma null_rec [code]: |
|
4715 "null (x # xs) \<longleftrightarrow> False" |
|
4716 "null [] \<longleftrightarrow> True" |
|
4717 by (simp_all add: null_def) |
|
4718 |
|
4719 lemma eq_Nil_null [code_unfold]: |
|
4720 "xs = [] \<longleftrightarrow> null xs" |
|
4721 by (simp add: null_def) |
|
4722 |
|
4723 lemma equal_Nil_null [code_unfold]: |
|
4724 "eq_class.eq xs [] \<longleftrightarrow> null xs" |
|
4725 by (simp add: eq eq_Nil_null) |
|
4726 |
|
4727 definition maps :: "('a \<Rightarrow> 'b list) \<Rightarrow> 'a list \<Rightarrow> 'b list" where |
|
4728 [code_post]: "maps f xs = concat (map f xs)" |
|
4729 |
|
4730 definition map_filter :: "('a \<Rightarrow> 'b option) \<Rightarrow> 'a list \<Rightarrow> 'b list" where |
|
4731 [code_post]: "map_filter f xs = map (the \<circ> f) (filter (\<lambda>x. f x \<noteq> None) xs)" |
|
4732 |
|
4733 text {* |
|
4734 Operations @{const maps} and @{const map_filter} avoid |
|
4735 intermediate lists on execution -- do not use for proving. |
|
4736 *} |
|
4737 |
|
4738 lemma maps_simps [code]: |
|
4739 "maps f (x # xs) = f x @ maps f xs" |
|
4740 "maps f [] = []" |
|
4741 by (simp_all add: maps_def) |
|
4742 |
|
4743 lemma map_filter_simps [code]: |
|
4744 "map_filter f (x # xs) = (case f x of None \<Rightarrow> map_filter f xs | Some y \<Rightarrow> y # map_filter f xs)" |
|
4745 "map_filter f [] = []" |
|
4746 by (simp_all add: map_filter_def split: option.split) |
|
4747 |
|
4748 lemma concat_map_maps [code_unfold]: |
|
4749 "concat (map f xs) = maps f xs" |
|
4750 by (simp add: maps_def) |
|
4751 |
|
4752 lemma map_filter_map_filter [code_unfold]: |
|
4753 "map f (filter P xs) = map_filter (\<lambda>x. if P x then Some (f x) else None) xs" |
|
4754 by (simp add: map_filter_def) |
|
4755 |
|
4756 text {* Optimized code for @{text"\<forall>i\<in>{a..b::int}"} and @{text"\<forall>n:{a..<b::nat}"} |
|
4757 and similiarly for @{text"\<exists>"}. *} |
|
4758 |
|
4759 definition all_interval_nat :: "(nat \<Rightarrow> bool) \<Rightarrow> nat \<Rightarrow> nat \<Rightarrow> bool" where |
|
4760 "all_interval_nat P i j \<longleftrightarrow> (\<forall>n \<in> {i..<j}. P n)" |
|
4761 |
|
4762 lemma [code]: |
|
4763 "all_interval_nat P i j \<longleftrightarrow> i \<ge> j \<or> P i \<and> all_interval_nat P (Suc i) j" |
|
4764 proof - |
|
4765 have *: "\<And>n. P i \<Longrightarrow> \<forall>n\<in>{Suc i..<j}. P n \<Longrightarrow> i \<le> n \<Longrightarrow> n < j \<Longrightarrow> P n" |
|
4766 proof - |
|
4767 fix n |
|
4768 assume "P i" "\<forall>n\<in>{Suc i..<j}. P n" "i \<le> n" "n < j" |
|
4769 then show "P n" by (cases "n = i") simp_all |
|
4770 qed |
|
4771 show ?thesis by (auto simp add: all_interval_nat_def intro: *) |
|
4772 qed |
|
4773 |
|
4774 lemma list_all_iff_all_interval_nat [code_unfold]: |
|
4775 "list_all P [i..<j] \<longleftrightarrow> all_interval_nat P i j" |
|
4776 by (simp add: list_all_iff all_interval_nat_def) |
|
4777 |
|
4778 lemma list_ex_iff_not_all_inverval_nat [code_unfold]: |
|
4779 "list_ex P [i..<j] \<longleftrightarrow> \<not> (all_interval_nat (Not \<circ> P) i j)" |
|
4780 by (simp add: list_ex_iff all_interval_nat_def) |
|
4781 |
|
4782 definition all_interval_int :: "(int \<Rightarrow> bool) \<Rightarrow> int \<Rightarrow> int \<Rightarrow> bool" where |
|
4783 "all_interval_int P i j \<longleftrightarrow> (\<forall>k \<in> {i..j}. P k)" |
|
4784 |
|
4785 lemma [code]: |
|
4786 "all_interval_int P i j \<longleftrightarrow> i > j \<or> P i \<and> all_interval_int P (i + 1) j" |
|
4787 proof - |
|
4788 have *: "\<And>k. P i \<Longrightarrow> \<forall>k\<in>{i+1..j}. P k \<Longrightarrow> i \<le> k \<Longrightarrow> k \<le> j \<Longrightarrow> P k" |
|
4789 proof - |
|
4790 fix k |
|
4791 assume "P i" "\<forall>k\<in>{i+1..j}. P k" "i \<le> k" "k \<le> j" |
|
4792 then show "P k" by (cases "k = i") simp_all |
|
4793 qed |
|
4794 show ?thesis by (auto simp add: all_interval_int_def intro: *) |
|
4795 qed |
|
4796 |
|
4797 lemma list_all_iff_all_interval_int [code_unfold]: |
|
4798 "list_all P [i..j] \<longleftrightarrow> all_interval_int P i j" |
|
4799 by (simp add: list_all_iff all_interval_int_def) |
|
4800 |
|
4801 lemma list_ex_iff_not_all_inverval_int [code_unfold]: |
|
4802 "list_ex P [i..j] \<longleftrightarrow> \<not> (all_interval_int (Not \<circ> P) i j)" |
|
4803 by (simp add: list_ex_iff all_interval_int_def) |
|
4804 |
|
4805 hide_const (open) member null maps map_filter all_interval_nat all_interval_int |
|
4806 |
|
4807 |
|
4808 subsubsection {* Pretty lists *} |
4519 |
4809 |
4520 use "Tools/list_code.ML" |
4810 use "Tools/list_code.ML" |
4521 |
4811 |
4522 code_type list |
4812 code_type list |
4523 (SML "_ list") |
4813 (SML "_ list") |
4576 #> Codegen.add_codegen "list_codegen" list_codegen |
4866 #> Codegen.add_codegen "list_codegen" list_codegen |
4577 end |
4867 end |
4578 *} |
4868 *} |
4579 |
4869 |
4580 |
4870 |
4581 subsubsection {* Generation of efficient code *} |
|
4582 |
|
4583 definition member :: "'a list \<Rightarrow> 'a \<Rightarrow> bool" where |
|
4584 mem_iff [code_post]: "member xs x \<longleftrightarrow> x \<in> set xs" |
|
4585 |
|
4586 primrec |
|
4587 null:: "'a list \<Rightarrow> bool" |
|
4588 where |
|
4589 "null [] = True" |
|
4590 | "null (x#xs) = False" |
|
4591 |
|
4592 primrec |
|
4593 list_inter :: "'a list \<Rightarrow> 'a list \<Rightarrow> 'a list" |
|
4594 where |
|
4595 "list_inter [] bs = []" |
|
4596 | "list_inter (a#as) bs = |
|
4597 (if a \<in> set bs then a # list_inter as bs else list_inter as bs)" |
|
4598 |
|
4599 primrec |
|
4600 list_all :: "('a \<Rightarrow> bool) \<Rightarrow> ('a list \<Rightarrow> bool)" |
|
4601 where |
|
4602 "list_all P [] = True" |
|
4603 | "list_all P (x#xs) = (P x \<and> list_all P xs)" |
|
4604 |
|
4605 primrec |
|
4606 list_ex :: "('a \<Rightarrow> bool) \<Rightarrow> 'a list \<Rightarrow> bool" |
|
4607 where |
|
4608 "list_ex P [] = False" |
|
4609 | "list_ex P (x#xs) = (P x \<or> list_ex P xs)" |
|
4610 |
|
4611 primrec |
|
4612 filtermap :: "('a \<Rightarrow> 'b option) \<Rightarrow> 'a list \<Rightarrow> 'b list" |
|
4613 where |
|
4614 "filtermap f [] = []" |
|
4615 | "filtermap f (x#xs) = |
|
4616 (case f x of None \<Rightarrow> filtermap f xs |
|
4617 | Some y \<Rightarrow> y # filtermap f xs)" |
|
4618 |
|
4619 primrec |
|
4620 map_filter :: "('a \<Rightarrow> 'b) \<Rightarrow> ('a \<Rightarrow> bool) \<Rightarrow> 'a list \<Rightarrow> 'b list" |
|
4621 where |
|
4622 "map_filter f P [] = []" |
|
4623 | "map_filter f P (x#xs) = |
|
4624 (if P x then f x # map_filter f P xs else map_filter f P xs)" |
|
4625 |
|
4626 primrec |
|
4627 length_unique :: "'a list \<Rightarrow> nat" |
|
4628 where |
|
4629 "length_unique [] = 0" |
|
4630 | "length_unique (x#xs) = |
|
4631 (if x \<in> set xs then length_unique xs else Suc (length_unique xs))" |
|
4632 |
|
4633 primrec |
|
4634 concat_map :: "('a => 'b list) => 'a list => 'b list" |
|
4635 where |
|
4636 "concat_map f [] = []" |
|
4637 | "concat_map f (x#xs) = f x @ concat_map f xs" |
|
4638 |
|
4639 text {* |
|
4640 Only use @{text member} for generating executable code. Otherwise use |
|
4641 @{prop "x : set xs"} instead --- it is much easier to reason about. |
|
4642 The same is true for @{const list_all} and @{const list_ex}: write |
|
4643 @{text "\<forall>x\<in>set xs"} and @{text "\<exists>x\<in>set xs"} instead because the HOL |
|
4644 quantifiers are aleady known to the automatic provers. In fact, the |
|
4645 declarations in the code subsection make sure that @{text "\<in>"}, |
|
4646 @{text "\<forall>x\<in>set xs"} and @{text "\<exists>x\<in>set xs"} are implemented |
|
4647 efficiently. |
|
4648 |
|
4649 Efficient emptyness check is implemented by @{const null}. |
|
4650 |
|
4651 The functions @{const filtermap} and @{const map_filter} are just |
|
4652 there to generate efficient code. Do not use |
|
4653 them for modelling and proving. |
|
4654 *} |
|
4655 |
|
4656 lemma rev_foldl_cons [code]: |
|
4657 "rev xs = foldl (\<lambda>xs x. x # xs) [] xs" |
|
4658 proof (induct xs) |
|
4659 case Nil then show ?case by simp |
|
4660 next |
|
4661 case Cons |
|
4662 { |
|
4663 fix x xs ys |
|
4664 have "foldl (\<lambda>xs x. x # xs) ys xs @ [x] |
|
4665 = foldl (\<lambda>xs x. x # xs) (ys @ [x]) xs" |
|
4666 by (induct xs arbitrary: ys) auto |
|
4667 } |
|
4668 note aux = this |
|
4669 show ?case by (induct xs) (auto simp add: Cons aux) |
|
4670 qed |
|
4671 |
|
4672 lemmas in_set_code [code_unfold] = mem_iff [symmetric] |
|
4673 |
|
4674 lemma member_simps [simp, code]: |
|
4675 "member (x # xs) y \<longleftrightarrow> x = y \<or> member xs y" |
|
4676 "member [] y \<longleftrightarrow> False" |
|
4677 by (auto simp add: mem_iff) |
|
4678 |
|
4679 lemma member_set: |
|
4680 "member = set" |
|
4681 by (simp add: expand_fun_eq mem_iff mem_def) |
|
4682 |
|
4683 abbreviation (input) mem :: "'a \<Rightarrow> 'a list \<Rightarrow> bool" (infixl "mem" 55) where |
|
4684 "x mem xs \<equiv> member xs x" -- "for backward compatibility" |
|
4685 |
|
4686 lemma empty_null: |
|
4687 "xs = [] \<longleftrightarrow> null xs" |
|
4688 by (cases xs) simp_all |
|
4689 |
|
4690 lemma [code_unfold]: |
|
4691 "eq_class.eq xs [] \<longleftrightarrow> null xs" |
|
4692 by (simp add: eq empty_null) |
|
4693 |
|
4694 lemmas null_empty [code_post] = |
|
4695 empty_null [symmetric] |
|
4696 |
|
4697 lemma list_inter_conv: |
|
4698 "set (list_inter xs ys) = set xs \<inter> set ys" |
|
4699 by (induct xs) auto |
|
4700 |
|
4701 lemma list_all_iff [code_post]: |
|
4702 "list_all P xs \<longleftrightarrow> (\<forall>x \<in> set xs. P x)" |
|
4703 by (induct xs) auto |
|
4704 |
|
4705 lemmas list_ball_code [code_unfold] = list_all_iff [symmetric] |
|
4706 |
|
4707 lemma list_all_append [simp]: |
|
4708 "list_all P (xs @ ys) \<longleftrightarrow> (list_all P xs \<and> list_all P ys)" |
|
4709 by (induct xs) auto |
|
4710 |
|
4711 lemma list_all_rev [simp]: |
|
4712 "list_all P (rev xs) \<longleftrightarrow> list_all P xs" |
|
4713 by (simp add: list_all_iff) |
|
4714 |
|
4715 lemma list_all_length: |
|
4716 "list_all P xs \<longleftrightarrow> (\<forall>n < length xs. P (xs ! n))" |
|
4717 unfolding list_all_iff by (auto intro: all_nth_imp_all_set) |
|
4718 |
|
4719 lemma list_all_cong[fundef_cong]: |
|
4720 "xs = ys \<Longrightarrow> (\<And>x. x \<in> set ys \<Longrightarrow> f x = g x) \<Longrightarrow> list_all f xs = list_all g ys" |
|
4721 by (simp add: list_all_iff) |
|
4722 |
|
4723 lemma list_ex_iff [code_post]: |
|
4724 "list_ex P xs \<longleftrightarrow> (\<exists>x \<in> set xs. P x)" |
|
4725 by (induct xs) simp_all |
|
4726 |
|
4727 lemmas list_bex_code [code_unfold] = |
|
4728 list_ex_iff [symmetric] |
|
4729 |
|
4730 lemma list_ex_length: |
|
4731 "list_ex P xs \<longleftrightarrow> (\<exists>n < length xs. P (xs ! n))" |
|
4732 unfolding list_ex_iff set_conv_nth by auto |
|
4733 |
|
4734 lemma list_ex_cong[fundef_cong]: |
|
4735 "xs = ys \<Longrightarrow> (\<And>x. x \<in> set ys \<Longrightarrow> f x = g x) \<Longrightarrow> list_ex f xs = list_ex g ys" |
|
4736 by (simp add: list_ex_iff) |
|
4737 |
|
4738 lemma filtermap_conv: |
|
4739 "filtermap f xs = map (\<lambda>x. the (f x)) (filter (\<lambda>x. f x \<noteq> None) xs)" |
|
4740 by (induct xs) (simp_all split: option.split) |
|
4741 |
|
4742 lemma map_filter_conv [simp]: |
|
4743 "map_filter f P xs = map f (filter P xs)" |
|
4744 by (induct xs) auto |
|
4745 |
|
4746 lemma length_remdups_length_unique [code_unfold]: |
|
4747 "length (remdups xs) = length_unique xs" |
|
4748 by (induct xs) simp_all |
|
4749 |
|
4750 lemma concat_map_code[code_unfold]: |
|
4751 "concat(map f xs) = concat_map f xs" |
|
4752 by (induct xs) simp_all |
|
4753 |
|
4754 declare INFI_def [code_unfold] |
|
4755 declare SUPR_def [code_unfold] |
|
4756 |
|
4757 declare set_map [symmetric, code_unfold] |
|
4758 |
|
4759 hide_const (open) length_unique |
|
4760 |
|
4761 |
|
4762 text {* Code for bounded quantification and summation over nats. *} |
|
4763 |
|
4764 lemma atMost_upto [code_unfold]: |
|
4765 "{..n} = set [0..<Suc n]" |
|
4766 by auto |
|
4767 |
|
4768 lemma atLeast_upt [code_unfold]: |
|
4769 "{..<n} = set [0..<n]" |
|
4770 by auto |
|
4771 |
|
4772 lemma greaterThanLessThan_upt [code_unfold]: |
|
4773 "{n<..<m} = set [Suc n..<m]" |
|
4774 by auto |
|
4775 |
|
4776 lemmas atLeastLessThan_upt [code_unfold] = set_upt [symmetric] |
|
4777 |
|
4778 lemma greaterThanAtMost_upt [code_unfold]: |
|
4779 "{n<..m} = set [Suc n..<Suc m]" |
|
4780 by auto |
|
4781 |
|
4782 lemma atLeastAtMost_upt [code_unfold]: |
|
4783 "{n..m} = set [n..<Suc m]" |
|
4784 by auto |
|
4785 |
|
4786 lemma all_nat_less_eq [code_unfold]: |
|
4787 "(\<forall>m<n\<Colon>nat. P m) \<longleftrightarrow> (\<forall>m \<in> {0..<n}. P m)" |
|
4788 by auto |
|
4789 |
|
4790 lemma ex_nat_less_eq [code_unfold]: |
|
4791 "(\<exists>m<n\<Colon>nat. P m) \<longleftrightarrow> (\<exists>m \<in> {0..<n}. P m)" |
|
4792 by auto |
|
4793 |
|
4794 lemma all_nat_less [code_unfold]: |
|
4795 "(\<forall>m\<le>n\<Colon>nat. P m) \<longleftrightarrow> (\<forall>m \<in> {0..n}. P m)" |
|
4796 by auto |
|
4797 |
|
4798 lemma ex_nat_less [code_unfold]: |
|
4799 "(\<exists>m\<le>n\<Colon>nat. P m) \<longleftrightarrow> (\<exists>m \<in> {0..n}. P m)" |
|
4800 by auto |
|
4801 |
|
4802 lemma setsum_set_distinct_conv_listsum: |
|
4803 "distinct xs \<Longrightarrow> setsum f (set xs) = listsum (map f xs)" |
|
4804 by (induct xs) simp_all |
|
4805 |
|
4806 lemma setsum_set_upt_conv_listsum [code_unfold]: |
|
4807 "setsum f (set [m..<n]) = listsum (map f [m..<n])" |
|
4808 by (rule setsum_set_distinct_conv_listsum) simp |
|
4809 |
|
4810 text {* General equivalence between @{const listsum} and @{const setsum} *} |
|
4811 lemma listsum_setsum_nth: |
|
4812 "listsum xs = (\<Sum> i = 0 ..< length xs. xs ! i)" |
|
4813 using setsum_set_upt_conv_listsum[of "op ! xs" 0 "length xs"] |
|
4814 by (simp add: map_nth) |
|
4815 |
|
4816 text {* Code for summation over ints. *} |
|
4817 |
|
4818 lemma greaterThanLessThan_upto [code_unfold]: |
|
4819 "{i<..<j::int} = set [i+1..j - 1]" |
|
4820 by auto |
|
4821 |
|
4822 lemma atLeastLessThan_upto [code_unfold]: |
|
4823 "{i..<j::int} = set [i..j - 1]" |
|
4824 by auto |
|
4825 |
|
4826 lemma greaterThanAtMost_upto [code_unfold]: |
|
4827 "{i<..j::int} = set [i+1..j]" |
|
4828 by auto |
|
4829 |
|
4830 lemmas atLeastAtMost_upto [code_unfold] = set_upto[symmetric] |
|
4831 |
|
4832 lemma setsum_set_upto_conv_listsum [code_unfold]: |
|
4833 "setsum f (set [i..j::int]) = listsum (map f [i..j])" |
|
4834 by (rule setsum_set_distinct_conv_listsum) simp |
|
4835 |
|
4836 |
|
4837 text {* Optimized code for @{text"\<forall>i\<in>{a..b::int}"} and @{text"\<forall>n:{a..<b::nat}"} |
|
4838 and similiarly for @{text"\<exists>"}. *} |
|
4839 |
|
4840 function all_from_to_nat :: "(nat \<Rightarrow> bool) \<Rightarrow> nat \<Rightarrow> nat \<Rightarrow> bool" where |
|
4841 "all_from_to_nat P i j = |
|
4842 (if i < j then if P i then all_from_to_nat P (i+1) j else False |
|
4843 else True)" |
|
4844 by auto |
|
4845 termination |
|
4846 by (relation "measure(%(P,i,j). j - i)") auto |
|
4847 |
|
4848 declare all_from_to_nat.simps[simp del] |
|
4849 |
|
4850 lemma all_from_to_nat_iff_ball: |
|
4851 "all_from_to_nat P i j = (ALL n : {i ..< j}. P n)" |
|
4852 proof(induct P i j rule:all_from_to_nat.induct) |
|
4853 case (1 P i j) |
|
4854 let ?yes = "i < j & P i" |
|
4855 show ?case |
|
4856 proof (cases) |
|
4857 assume ?yes |
|
4858 hence "all_from_to_nat P i j = (P i & all_from_to_nat P (i+1) j)" |
|
4859 by(simp add: all_from_to_nat.simps) |
|
4860 also have "... = (P i & (ALL n : {i+1 ..< j}. P n))" using `?yes` 1 by simp |
|
4861 also have "... = (ALL n : {i ..< j}. P n)" (is "?L = ?R") |
|
4862 proof |
|
4863 assume L: ?L |
|
4864 show ?R |
|
4865 proof clarify |
|
4866 fix n assume n: "n : {i..<j}" |
|
4867 show "P n" |
|
4868 proof cases |
|
4869 assume "n = i" thus "P n" using L by simp |
|
4870 next |
|
4871 assume "n ~= i" |
|
4872 hence "i+1 <= n" using n by auto |
|
4873 thus "P n" using L n by simp |
|
4874 qed |
|
4875 qed |
|
4876 next |
|
4877 assume R: ?R thus ?L using `?yes` 1 by auto |
|
4878 qed |
|
4879 finally show ?thesis . |
|
4880 next |
|
4881 assume "~?yes" thus ?thesis by(auto simp add: all_from_to_nat.simps) |
|
4882 qed |
|
4883 qed |
|
4884 |
|
4885 |
|
4886 lemma list_all_iff_all_from_to_nat[code_unfold]: |
|
4887 "list_all P [i..<j] = all_from_to_nat P i j" |
|
4888 by(simp add: all_from_to_nat_iff_ball list_all_iff) |
|
4889 |
|
4890 lemma list_ex_iff_not_all_from_to_not_nat[code_unfold]: |
|
4891 "list_ex P [i..<j] = (~all_from_to_nat (%x. ~P x) i j)" |
|
4892 by(simp add: all_from_to_nat_iff_ball list_ex_iff) |
|
4893 |
|
4894 |
|
4895 function all_from_to_int :: "(int \<Rightarrow> bool) \<Rightarrow> int \<Rightarrow> int \<Rightarrow> bool" where |
|
4896 "all_from_to_int P i j = |
|
4897 (if i <= j then if P i then all_from_to_int P (i+1) j else False |
|
4898 else True)" |
|
4899 by auto |
|
4900 termination |
|
4901 by (relation "measure(%(P,i,j). nat(j - i + 1))") auto |
|
4902 |
|
4903 declare all_from_to_int.simps[simp del] |
|
4904 |
|
4905 lemma all_from_to_int_iff_ball: |
|
4906 "all_from_to_int P i j = (ALL n : {i .. j}. P n)" |
|
4907 proof(induct P i j rule:all_from_to_int.induct) |
|
4908 case (1 P i j) |
|
4909 let ?yes = "i <= j & P i" |
|
4910 show ?case |
|
4911 proof (cases) |
|
4912 assume ?yes |
|
4913 hence "all_from_to_int P i j = (P i & all_from_to_int P (i+1) j)" |
|
4914 by(simp add: all_from_to_int.simps) |
|
4915 also have "... = (P i & (ALL n : {i+1 .. j}. P n))" using `?yes` 1 by simp |
|
4916 also have "... = (ALL n : {i .. j}. P n)" (is "?L = ?R") |
|
4917 proof |
|
4918 assume L: ?L |
|
4919 show ?R |
|
4920 proof clarify |
|
4921 fix n assume n: "n : {i..j}" |
|
4922 show "P n" |
|
4923 proof cases |
|
4924 assume "n = i" thus "P n" using L by simp |
|
4925 next |
|
4926 assume "n ~= i" |
|
4927 hence "i+1 <= n" using n by auto |
|
4928 thus "P n" using L n by simp |
|
4929 qed |
|
4930 qed |
|
4931 next |
|
4932 assume R: ?R thus ?L using `?yes` 1 by auto |
|
4933 qed |
|
4934 finally show ?thesis . |
|
4935 next |
|
4936 assume "~?yes" thus ?thesis by(auto simp add: all_from_to_int.simps) |
|
4937 qed |
|
4938 qed |
|
4939 |
|
4940 lemma list_all_iff_all_from_to_int[code_unfold]: |
|
4941 "list_all P [i..j] = all_from_to_int P i j" |
|
4942 by(simp add: all_from_to_int_iff_ball list_all_iff) |
|
4943 |
|
4944 lemma list_ex_iff_not_all_from_to_not_int[code_unfold]: |
|
4945 "list_ex P [i..j] = (~ all_from_to_int (%x. ~P x) i j)" |
|
4946 by(simp add: all_from_to_int_iff_ball list_ex_iff) |
|
4947 |
|
4948 |
|
4949 subsubsection {* Use convenient predefined operations *} |
4871 subsubsection {* Use convenient predefined operations *} |
4950 |
4872 |
4951 code_const "op @" |
4873 code_const "op @" |
4952 (SML infixr 7 "@") |
4874 (SML infixr 7 "@") |
4953 (OCaml infixr 6 "@") |
4875 (OCaml infixr 6 "@") |