7072
|
1 |
(* Title: Provers/Arith/combine_coeff.ML
|
|
2 |
ID: $Id$
|
|
3 |
Author: Lawrence C Paulson, Cambridge University Computer Laboratory
|
|
4 |
Copyright 1999 University of Cambridge
|
|
5 |
|
|
6 |
Simplification procedure to combine literal coefficients in sums of products
|
|
7 |
|
|
8 |
Example, #3*x + y - (x*#2) goes to x + y
|
|
9 |
|
|
10 |
For the relations <, <= and =, the difference is simplified
|
|
11 |
|
|
12 |
[COULD BE GENERALIZED to products of exponentials?]
|
|
13 |
*)
|
|
14 |
|
|
15 |
signature COMBINE_COEFF_DATA =
|
|
16 |
sig
|
|
17 |
val ss : simpset (*basic simpset of object-logtic*)
|
|
18 |
val eq_reflection : thm (*object-equality to meta-equality*)
|
|
19 |
val thy : theory (*the theory of the group*)
|
|
20 |
val T : typ (*the type of group elements*)
|
|
21 |
|
|
22 |
val trans : thm (*transitivity of equals*)
|
|
23 |
val add_ac : thm list (*AC-rules for the addition operator*)
|
|
24 |
val diff_def : thm (*Defines x-y as x + -y *)
|
|
25 |
val minus_add_distrib : thm (* -(x+y) = -x + -y *)
|
|
26 |
val minus_minus : thm (* - -x = x *)
|
|
27 |
val mult_commute : thm (*commutative law for the product*)
|
|
28 |
val mult_1_right : thm (*the law x*1=x *)
|
|
29 |
val add_mult_distrib : thm (*law w*(x+y) = w*x + w*y *)
|
|
30 |
val diff_mult_distrib : thm (*law w*(x-y) = w*x - w*y *)
|
|
31 |
val mult_minus_right : thm (*law x * -y = -(x*y) *)
|
|
32 |
|
|
33 |
val rel_iff_rel_0_rls : thm list (*e.g. (x < y) = (x-y < 0) *)
|
|
34 |
val dest_eqI : thm -> term (*to get patterns from the rel rules*)
|
|
35 |
end;
|
|
36 |
|
|
37 |
|
|
38 |
functor Combine_Coeff (Data: COMBINE_COEFF_DATA) =
|
|
39 |
struct
|
|
40 |
|
|
41 |
local open Data
|
|
42 |
in
|
|
43 |
val rhs_ss = ss addsimps
|
|
44 |
[add_mult_distrib, diff_mult_distrib,
|
|
45 |
mult_minus_right, mult_1_right];
|
|
46 |
|
|
47 |
val lhs_ss = ss addsimps
|
|
48 |
add_ac @
|
|
49 |
[diff_def, minus_add_distrib, minus_minus, mult_commute];
|
|
50 |
end;
|
|
51 |
|
|
52 |
(*prove while suppressing timing information*)
|
|
53 |
fun prove name ct tacf =
|
|
54 |
setmp Goals.proof_timing false (prove_goalw_cterm [] ct) tacf
|
|
55 |
handle ERROR =>
|
|
56 |
error(name ^ " simproc:\nfailed to prove " ^ string_of_cterm ct);
|
|
57 |
|
|
58 |
val plus = Const ("op +", [Data.T,Data.T] ---> Data.T);
|
|
59 |
val minus = Const ("op -", [Data.T,Data.T] ---> Data.T);
|
|
60 |
val uminus = Const ("uminus", Data.T --> Data.T);
|
|
61 |
val times = Const ("op *", [Data.T,Data.T] ---> Data.T);
|
|
62 |
|
|
63 |
val number_of = Const ("Numeral.number_of",
|
|
64 |
Type ("Numeral.bin", []) --> Data.T);
|
|
65 |
|
|
66 |
val zero = number_of $ HOLogic.pls_const;
|
|
67 |
val one = number_of $ (HOLogic.bit_const $
|
|
68 |
HOLogic.pls_const $
|
|
69 |
HOLogic.true_const);
|
|
70 |
|
|
71 |
(*We map -t to t and (in other cases) t to -t. No need to check the type of
|
|
72 |
uminus, since the simproc is only called on sums of type T.*)
|
|
73 |
fun negate (Const("uminus",_) $ t) = t
|
|
74 |
| negate t = uminus $ t;
|
|
75 |
|
|
76 |
fun mk_sum [] = zero
|
|
77 |
| mk_sum tms = foldr1 (fn (x,y) => plus $ x $ y) tms;
|
|
78 |
|
|
79 |
fun attach_coeff (Bound ~1,ns) = mk_sum ns (*just a literal*)
|
|
80 |
| attach_coeff (x,ns) = times $ x $ (mk_sum ns);
|
|
81 |
|
|
82 |
fun add_atom (x, (neg,m)) pairs =
|
|
83 |
let val m' = if neg then negate m else m
|
|
84 |
in
|
|
85 |
case gen_assoc (op aconv) (pairs, x) of
|
|
86 |
Some n => gen_overwrite (op aconv) (pairs, (x, m'::n))
|
|
87 |
| None => (x,[m']) :: pairs
|
|
88 |
end;
|
|
89 |
|
|
90 |
(**STILL MISSING: a treatment of nested coeffs, e.g. a*(b*3) **)
|
|
91 |
(*Convert a formula built from +, * and - (binary and unary) to a
|
|
92 |
(atom, coeff) association list. Handles t+t, t-t, -t, a*n, n*a, n, a
|
|
93 |
where n denotes a numeric literal and a is any other term.
|
|
94 |
No need to check types PROVIDED they are checked upon entry!*)
|
|
95 |
fun add_terms neg (Const("op +", _) $ x $ y, pairs) =
|
|
96 |
add_terms neg (x, add_terms neg (y, pairs))
|
|
97 |
| add_terms neg (Const("op -", _) $ x $ y, pairs) =
|
|
98 |
add_terms neg (x, add_terms (not neg) (y, pairs))
|
|
99 |
| add_terms neg (Const("uminus", _) $ x, pairs) =
|
|
100 |
add_terms (not neg) (x, pairs)
|
|
101 |
| add_terms neg (lit as Const("Numeral.number_of", _) $ _, pairs) =
|
|
102 |
(*literal: make it the coefficient of a dummy term*)
|
|
103 |
add_atom (Bound ~1, (neg, lit)) pairs
|
|
104 |
| add_terms neg (Const("op *", _) $ x
|
|
105 |
$ (lit as Const("Numeral.number_of", _) $ _),
|
|
106 |
pairs) =
|
|
107 |
(*coefficient on the right*)
|
|
108 |
add_atom (x, (neg, lit)) pairs
|
|
109 |
| add_terms neg (Const("op *", _)
|
|
110 |
$ (lit as Const("Numeral.number_of", _) $ _)
|
|
111 |
$ x, pairs) =
|
|
112 |
(*coefficient on the left*)
|
|
113 |
add_atom (x, (neg, lit)) pairs
|
|
114 |
| add_terms neg (x, pairs) = add_atom (x, (neg, one)) pairs;
|
|
115 |
|
|
116 |
fun terms fml = add_terms false (fml, []);
|
|
117 |
|
|
118 |
exception CC_fail;
|
|
119 |
|
|
120 |
(*The number of terms in t, assuming no collapsing takes place*)
|
|
121 |
fun term_count (Const("op +", _) $ x $ y) = term_count x + term_count y
|
|
122 |
| term_count (Const("op -", _) $ x $ y) = term_count x + term_count y
|
|
123 |
| term_count (Const("uminus", _) $ x) = term_count x
|
|
124 |
| term_count x = 1;
|
|
125 |
|
|
126 |
|
|
127 |
val trace = ref false;
|
|
128 |
|
|
129 |
(*The simproc for sums*)
|
|
130 |
fun sum_proc sg _ lhs =
|
|
131 |
let fun show t = string_of_cterm (Thm.cterm_of sg t)
|
|
132 |
val _ = if !trace then writeln
|
|
133 |
("combine_coeff sum simproc: LHS = " ^ show lhs)
|
|
134 |
else ()
|
|
135 |
val ts = terms lhs
|
|
136 |
val _ = if term_count lhs = length ts
|
|
137 |
then raise CC_fail (*we can't reduce the number of terms*)
|
|
138 |
else ()
|
|
139 |
val rhs = mk_sum (map attach_coeff ts)
|
|
140 |
val _ = if !trace then writeln ("RHS = " ^ show rhs) else ()
|
|
141 |
val th = prove "combine_coeff"
|
|
142 |
(Thm.cterm_of sg (Logic.mk_equals (lhs, rhs)))
|
|
143 |
(fn _ => [rtac Data.eq_reflection 1,
|
|
144 |
simp_tac rhs_ss 1,
|
|
145 |
IF_UNSOLVED (simp_tac lhs_ss 1)])
|
|
146 |
in Some th end
|
|
147 |
handle CC_fail => None;
|
|
148 |
|
|
149 |
val sum_conv =
|
|
150 |
Simplifier.mk_simproc "combine_coeff_sums"
|
|
151 |
(map (Thm.read_cterm (Theory.sign_of Data.thy))
|
|
152 |
[("x + y", Data.T), ("x - y", Data.T)])
|
|
153 |
sum_proc;
|
|
154 |
|
|
155 |
|
|
156 |
(*The simproc for relations, which just replaces x<y by x-y<0 and simplifies*)
|
|
157 |
|
|
158 |
val trans_eq_reflection = Data.trans RS Data.eq_reflection |> standard;
|
|
159 |
|
|
160 |
fun rel_proc sg asms (lhs as (rel$lt$rt)) =
|
|
161 |
let val _ = if !trace then writeln
|
|
162 |
("cc_rel simproc: LHS = " ^
|
|
163 |
string_of_cterm (cterm_of sg lhs))
|
|
164 |
else ()
|
|
165 |
val _ = if lt=zero orelse rt=zero then raise CC_fail
|
|
166 |
else () (*this simproc can do nothing if either side is zero*)
|
|
167 |
val cc_th = the (sum_proc sg asms (minus $ lt $ rt))
|
|
168 |
handle OPTION => raise CC_fail
|
|
169 |
val _ = if !trace then
|
|
170 |
writeln ("cc_th = " ^ string_of_thm cc_th)
|
|
171 |
else ()
|
|
172 |
val cc_lr = #2 (Logic.dest_equals (concl_of cc_th))
|
|
173 |
|
|
174 |
val rhs = rel $ cc_lr $ zero
|
|
175 |
val _ = if !trace then
|
|
176 |
writeln ("RHS = " ^ string_of_cterm (Thm.cterm_of sg rhs))
|
|
177 |
else ()
|
|
178 |
val ct = Thm.cterm_of sg (Logic.mk_equals (lhs,rhs))
|
|
179 |
|
|
180 |
val th = prove "cc_rel" ct
|
|
181 |
(fn _ => [rtac trans_eq_reflection 1,
|
|
182 |
resolve_tac Data.rel_iff_rel_0_rls 1,
|
|
183 |
simp_tac (Data.ss addsimps [cc_th]) 1])
|
|
184 |
in Some th end
|
|
185 |
handle CC_fail => None;
|
|
186 |
|
|
187 |
val rel_conv =
|
|
188 |
Simplifier.mk_simproc "cc_relations"
|
|
189 |
(map (Thm.cterm_of (Theory.sign_of Data.thy) o Data.dest_eqI)
|
|
190 |
Data.rel_iff_rel_0_rls)
|
|
191 |
rel_proc;
|
|
192 |
|
|
193 |
end;
|