|
1 (* Title: Provers/Arith/cancel_data.ML |
|
2 Author: Mathias Fleury, MPII |
|
3 Copyright 2017 |
|
4 |
|
5 Based on: |
|
6 Title: Tools/nat_numeral_simprocs.ML |
|
7 Author: Lawrence C Paulson, Cambridge University Computer Laboratory |
|
8 |
|
9 Datastructure for the cancelation simprocs. |
|
10 |
|
11 *) |
|
12 signature CANCEL_DATA = |
|
13 sig |
|
14 val mk_sum : typ -> term list -> term |
|
15 val dest_sum : term -> term list |
|
16 val mk_coeff : int * term -> term |
|
17 val dest_coeff : term -> int * term |
|
18 val find_first_coeff : term -> term list -> int * term list |
|
19 val trans_tac : Proof.context -> thm option -> tactic |
|
20 |
|
21 val norm_ss1 : simpset |
|
22 val norm_ss2: simpset |
|
23 val norm_tac: Proof.context -> tactic |
|
24 |
|
25 val numeral_simp_tac : Proof.context -> tactic |
|
26 val simplify_meta_eq : Proof.context -> thm -> thm |
|
27 val prove_conv : tactic list -> Proof.context -> thm list -> term * term -> thm option |
|
28 end; |
|
29 |
|
30 structure Cancel_Data : CANCEL_DATA = |
|
31 struct |
|
32 |
|
33 (*** Utilities ***) |
|
34 |
|
35 (*No reordering of the arguments.*) |
|
36 fun fast_mk_iterate_add (n, mset) = |
|
37 let val T = fastype_of mset |
|
38 in |
|
39 Const (@{const_name "iterate_add"}, @{typ nat} --> T --> T) $ n $ mset |
|
40 end; |
|
41 |
|
42 (*iterate_add is not symmetric, unlike multiplication over natural numbers.*) |
|
43 fun mk_iterate_add (t, u) = |
|
44 (if fastype_of t = @{typ nat} then (t, u) else (u, t)) |
|
45 |> fast_mk_iterate_add; |
|
46 |
|
47 (*Maps n to #n for n = 1, 2*) |
|
48 val numeral_syms = |
|
49 map (fn th => th RS sym) @{thms numeral_One numeral_2_eq_2 numeral_1_eq_Suc_0}; |
|
50 |
|
51 val numeral_sym_ss = |
|
52 simpset_of (put_simpset HOL_basic_ss @{context} addsimps numeral_syms); |
|
53 |
|
54 fun mk_number 1 = HOLogic.numeral_const HOLogic.natT $ HOLogic.one_const |
|
55 | mk_number n = HOLogic.mk_number HOLogic.natT n; |
|
56 fun dest_number t = Int.max (0, snd (HOLogic.dest_number t)); |
|
57 |
|
58 fun find_first_numeral past (t::terms) = |
|
59 ((dest_number t, t, rev past @ terms) |
|
60 handle TERM _ => find_first_numeral (t::past) terms) |
|
61 | find_first_numeral _ [] = raise TERM("find_first_numeral", []); |
|
62 |
|
63 fun typed_zero T = Const (@{const_name "Groups.zero"}, T); |
|
64 fun typed_one T = HOLogic.numeral_const T $ HOLogic.one_const |
|
65 val mk_plus = HOLogic.mk_binop @{const_name Groups.plus}; |
|
66 |
|
67 (*Thus mk_sum[t] yields t+0; longer sums don't have a trailing zero.*) |
|
68 fun mk_sum T [] = typed_zero T |
|
69 | mk_sum _ [t,u] = mk_plus (t, u) |
|
70 | mk_sum T (t :: ts) = mk_plus (t, mk_sum T ts); |
|
71 |
|
72 val dest_plus = HOLogic.dest_bin @{const_name Groups.plus} dummyT; |
|
73 |
|
74 |
|
75 (*** Other simproc items ***) |
|
76 |
|
77 val bin_simps = |
|
78 (@{thm numeral_One} RS sym) :: |
|
79 @{thms add_numeral_left diff_nat_numeral diff_0_eq_0 mult_numeral_left(1) |
|
80 if_True if_False not_False_eq_True nat_0 nat_numeral nat_neg_numeral iterate_add_simps(1) |
|
81 iterate_add_empty arith_simps rel_simps of_nat_numeral}; |
|
82 |
|
83 |
|
84 (*** CancelNumerals simprocs ***) |
|
85 |
|
86 val one = mk_number 1; |
|
87 |
|
88 fun mk_prod T [] = typed_one T |
|
89 | mk_prod _ [t] = t |
|
90 | mk_prod T (t :: ts) = if t = one then mk_prod T ts else mk_iterate_add (t, mk_prod T ts); |
|
91 |
|
92 val dest_iterate_add = HOLogic.dest_bin @{const_name iterate_add} dummyT; |
|
93 |
|
94 fun dest_iterate_adds t = |
|
95 let val (t,u) = dest_iterate_add t in |
|
96 t :: dest_iterate_adds u end |
|
97 handle TERM _ => [t]; |
|
98 |
|
99 fun mk_coeff (k,t) = mk_iterate_add (mk_number k, t); |
|
100 |
|
101 (*Express t as a product of (possibly) a numeral with other factors, sorted*) |
|
102 fun dest_coeff t = |
|
103 let |
|
104 val T = fastype_of t |
|
105 val ts = sort Term_Ord.term_ord (dest_iterate_adds t); |
|
106 val (n, _, ts') = |
|
107 find_first_numeral [] ts |
|
108 handle TERM _ => (1, one, ts); |
|
109 in (n, mk_prod T ts') end; |
|
110 |
|
111 (*Find first coefficient-term THAT MATCHES u*) |
|
112 fun find_first_coeff _ _ [] = raise TERM("find_first_coeff", []) |
|
113 | find_first_coeff past u (t::terms) = |
|
114 let val (n,u') = dest_coeff t in |
|
115 if u aconv u' then (n, rev past @ terms) else find_first_coeff (t::past) u terms end |
|
116 handle TERM _ => find_first_coeff (t::past) u terms; |
|
117 |
|
118 (* |
|
119 Split up a sum into the list of its constituent terms. |
|
120 *) |
|
121 fun dest_summation (t, ts) = |
|
122 let val (t1,t2) = dest_plus t in |
|
123 dest_summation (t1, dest_summation (t2, ts)) end |
|
124 handle TERM _ => t :: ts; |
|
125 |
|
126 fun dest_sum t = dest_summation (t, []); |
|
127 |
|
128 val rename_numerals = simplify (put_simpset numeral_sym_ss @{context}) o Thm.transfer @{theory}; |
|
129 |
|
130 (*Simplify \<open>iterate_add (Suc 0) n\<close>, \<open>iterate_add n (Suc 0)\<close>, \<open>n+0\<close>, and \<open>0+n\<close> to \<open>n\<close>*) |
|
131 val add_0s = map rename_numerals @{thms monoid_add_class.add_0_left monoid_add_class.add_0_right}; |
|
132 val mult_1s = map rename_numerals @{thms iterate_add_1 iterate_add_simps(2)[of 0]}; |
|
133 |
|
134 (*And these help the simproc return False when appropriate. We use the same list as the |
|
135 simproc for natural numbers, but adapted.*) |
|
136 fun contra_rules ctxt = |
|
137 @{thms le_zero_eq} @ Named_Theorems.get ctxt @{named_theorems cancelation_simproc_eq_elim}; |
|
138 |
|
139 fun simplify_meta_eq ctxt = |
|
140 Arith_Data.simplify_meta_eq |
|
141 (@{thms numeral_1_eq_Suc_0 Nat.add_0_right |
|
142 mult_0 mult_0_right mult_1 mult_1_right iterate_add_Numeral1 of_nat_numeral |
|
143 monoid_add_class.add_0_left iterate_add_simps(1) monoid_add_class.add_0_right |
|
144 iterate_add_Numeral1} @ |
|
145 contra_rules ctxt) ctxt; |
|
146 |
|
147 val mk_sum = mk_sum; |
|
148 val dest_sum = dest_sum; |
|
149 val mk_coeff = mk_coeff; |
|
150 val dest_coeff = dest_coeff; |
|
151 val find_first_coeff = find_first_coeff []; |
|
152 val trans_tac = Numeral_Simprocs.trans_tac; |
|
153 |
|
154 val norm_ss1 = |
|
155 simpset_of (put_simpset Numeral_Simprocs.num_ss @{context} addsimps |
|
156 numeral_syms @ add_0s @ mult_1s @ @{thms ac_simps iterate_add_simps}); |
|
157 |
|
158 val norm_ss2 = |
|
159 simpset_of (put_simpset Numeral_Simprocs.num_ss @{context} addsimps |
|
160 bin_simps @ |
|
161 @{thms ac_simps}); |
|
162 |
|
163 fun norm_tac ctxt = |
|
164 ALLGOALS (simp_tac (put_simpset norm_ss1 ctxt)) |
|
165 THEN ALLGOALS (simp_tac (put_simpset norm_ss2 ctxt)); |
|
166 |
|
167 val mset_simps_ss = |
|
168 simpset_of (put_simpset HOL_basic_ss @{context} addsimps bin_simps); |
|
169 |
|
170 fun numeral_simp_tac ctxt = ALLGOALS (simp_tac (put_simpset mset_simps_ss ctxt)); |
|
171 |
|
172 val simplify_meta_eq = simplify_meta_eq; |
|
173 val prove_conv = Arith_Data.prove_conv; |
|
174 |
|
175 end |
|
176 |