1 (* ========================================================================= *)
2 (* Products of natural numbers and real numbers. *)
3 (* ========================================================================= *)
7 (* ------------------------------------------------------------------------- *)
8 (* Products over natural numbers. *)
9 (* ------------------------------------------------------------------------- *)
11 let nproduct = new_definition
12 `nproduct = iterate(( * ):num->num->num)`;;
14 let NPRODUCT_CLAUSES = prove
15 (`(!f. nproduct {} f = 1) /\
17 ==> (nproduct (x INSERT s) f =
18 if x IN s then nproduct s f else f(x) * nproduct s f))`,
19 REWRITE_TAC[nproduct; GSYM NEUTRAL_MUL] THEN
20 ONCE_REWRITE_TAC[SWAP_FORALL_THM] THEN
21 MATCH_MP_TAC ITERATE_CLAUSES THEN REWRITE_TAC[MONOIDAL_MUL]);;
23 let NPRODUCT_SUPPORT = prove
24 (`!f s. nproduct (support ( * ) f s) f = nproduct s f`,
25 REWRITE_TAC[nproduct; ITERATE_SUPPORT]);;
27 let NPRODUCT_UNION = prove
28 (`!f s t. FINITE s /\ FINITE t /\ DISJOINT s t
29 ==> (nproduct (s UNION t) f = nproduct s f * nproduct t f)`,
30 SIMP_TAC[nproduct; ITERATE_UNION; MONOIDAL_MUL]);;
32 let NPRODUCT_IMAGE = prove
33 (`!f g s. (!x y. x IN s /\ y IN s /\ f x = f y ==> x = y)
34 ==> (nproduct (IMAGE f s) g = nproduct s (g o f))`,
35 REWRITE_TAC[nproduct; GSYM NEUTRAL_MUL] THEN
36 MATCH_MP_TAC ITERATE_IMAGE THEN REWRITE_TAC[MONOIDAL_MUL]);;
38 let NPRODUCT_ADD_SPLIT = prove
41 ==> (nproduct (m..(n+p)) f = nproduct(m..n) f * nproduct(n+1..n+p) f)`,
42 SIMP_TAC[NUMSEG_ADD_SPLIT; NPRODUCT_UNION; DISJOINT_NUMSEG; FINITE_NUMSEG;
43 ARITH_RULE `x < x + 1`]);;
45 let NPRODUCT_POS_LT = prove
46 (`!f s. FINITE s /\ (!x. x IN s ==> 0 < f x) ==> 0 < nproduct s f`,
47 GEN_TAC THEN REWRITE_TAC[IMP_CONJ] THEN
48 MATCH_MP_TAC FINITE_INDUCT_STRONG THEN
49 SIMP_TAC[NPRODUCT_CLAUSES; ARITH; IN_INSERT; LT_MULT]);;
51 let NPRODUCT_POS_LT_NUMSEG = prove
52 (`!f m n. (!x. m <= x /\ x <= n ==> 0 < f x) ==> 0 < nproduct(m..n) f`,
53 SIMP_TAC[NPRODUCT_POS_LT; FINITE_NUMSEG; IN_NUMSEG]);;
55 let NPRODUCT_OFFSET = prove
56 (`!f m p. nproduct(m+p..n+p) f = nproduct(m..n) (\i. f(i + p))`,
57 SIMP_TAC[NUMSEG_OFFSET_IMAGE; NPRODUCT_IMAGE;
58 EQ_ADD_RCANCEL; FINITE_NUMSEG] THEN
61 let NPRODUCT_SING = prove
62 (`!f x. nproduct {x} f = f(x)`,
63 SIMP_TAC[NPRODUCT_CLAUSES; FINITE_RULES; NOT_IN_EMPTY; MULT_CLAUSES]);;
65 let NPRODUCT_SING_NUMSEG = prove
66 (`!f n. nproduct(n..n) f = f(n)`,
67 REWRITE_TAC[NUMSEG_SING; NPRODUCT_SING]);;
69 let NPRODUCT_CLAUSES_NUMSEG = prove
70 (`(!m. nproduct(m..0) f = if m = 0 then f(0) else 1) /\
71 (!m n. nproduct(m..SUC n) f = if m <= SUC n then nproduct(m..n) f * f(SUC n)
72 else nproduct(m..n) f)`,
73 REWRITE_TAC[NUMSEG_CLAUSES] THEN REPEAT STRIP_TAC THEN
75 ASM_SIMP_TAC[NPRODUCT_SING; NPRODUCT_CLAUSES; FINITE_NUMSEG; IN_NUMSEG] THEN
76 REWRITE_TAC[ARITH_RULE `~(SUC n <= n)`; MULT_AC]);;
78 let NPRODUCT_EQ = prove
79 (`!f g s. (!x. x IN s ==> (f x = g x)) ==> nproduct s f = nproduct s g`,
80 REWRITE_TAC[nproduct] THEN MATCH_MP_TAC ITERATE_EQ THEN
81 REWRITE_TAC[MONOIDAL_MUL]);;
83 let NPRODUCT_EQ_NUMSEG = prove
84 (`!f g m n. (!i. m <= i /\ i <= n ==> (f(i) = g(i)))
85 ==> (nproduct(m..n) f = nproduct(m..n) g)`,
86 MESON_TAC[NPRODUCT_EQ; FINITE_NUMSEG; IN_NUMSEG]);;
88 let NPRODUCT_EQ_0 = prove
89 (`!f s. FINITE s ==> (nproduct s f = 0 <=> ?x. x IN s /\ f(x) = 0)`,
90 GEN_TAC THEN MATCH_MP_TAC FINITE_INDUCT_STRONG THEN
91 SIMP_TAC[NPRODUCT_CLAUSES; MULT_EQ_0; IN_INSERT; ARITH; NOT_IN_EMPTY] THEN
94 let NPRODUCT_EQ_0_NUMSEG = prove
95 (`!f m n. nproduct(m..n) f = 0 <=> ?x. m <= x /\ x <= n /\ f(x) = 0`,
96 SIMP_TAC[NPRODUCT_EQ_0; FINITE_NUMSEG; IN_NUMSEG; GSYM CONJ_ASSOC]);;
98 let NPRODUCT_LE = prove
99 (`!f s. FINITE s /\ (!x. x IN s ==> 0 <= f(x) /\ f(x) <= g(x))
100 ==> nproduct s f <= nproduct s g`,
101 GEN_TAC THEN REWRITE_TAC[IMP_CONJ] THEN
102 MATCH_MP_TAC FINITE_INDUCT_STRONG THEN
103 SIMP_TAC[IN_INSERT; NPRODUCT_CLAUSES; NOT_IN_EMPTY; LE_REFL] THEN
104 MESON_TAC[LE_MULT2; LE_0]);;
106 let NPRODUCT_LE_NUMSEG = prove
107 (`!f m n. (!i. m <= i /\ i <= n ==> 0 <= f(i) /\ f(i) <= g(i))
108 ==> nproduct(m..n) f <= nproduct(m..n) g`,
109 SIMP_TAC[NPRODUCT_LE; FINITE_NUMSEG; IN_NUMSEG]);;
111 let NPRODUCT_EQ_1 = prove
112 (`!f s. (!x:A. x IN s ==> (f(x) = 1)) ==> (nproduct s f = 1)`,
113 REWRITE_TAC[nproduct; GSYM NEUTRAL_MUL] THEN
114 SIMP_TAC[ITERATE_EQ_NEUTRAL; MONOIDAL_MUL]);;
116 let NPRODUCT_EQ_1_NUMSEG = prove
117 (`!f m n. (!i. m <= i /\ i <= n ==> (f(i) = 1)) ==> (nproduct(m..n) f = 1)`,
118 SIMP_TAC[NPRODUCT_EQ_1; IN_NUMSEG]);;
120 let NPRODUCT_MUL = prove
122 ==> nproduct s (\x. f x * g x) = nproduct s f * nproduct s g`,
123 GEN_TAC THEN GEN_TAC THEN MATCH_MP_TAC FINITE_INDUCT_STRONG THEN
124 SIMP_TAC[NPRODUCT_CLAUSES; MULT_AC; MULT_CLAUSES]);;
126 let NPRODUCT_MUL_NUMSEG = prove
128 nproduct(m..n) (\x. f x * g x) = nproduct(m..n) f * nproduct(m..n) g`,
129 SIMP_TAC[NPRODUCT_MUL; FINITE_NUMSEG]);;
131 let NPRODUCT_CONST = prove
132 (`!c s. FINITE s ==> nproduct s (\x. c) = c EXP (CARD s)`,
133 GEN_TAC THEN MATCH_MP_TAC FINITE_INDUCT_STRONG THEN
134 SIMP_TAC[NPRODUCT_CLAUSES; CARD_CLAUSES; EXP]);;
136 let NPRODUCT_CONST_NUMSEG = prove
137 (`!c m n. nproduct (m..n) (\x. c) = c EXP ((n + 1) - m)`,
138 SIMP_TAC[NPRODUCT_CONST; CARD_NUMSEG; FINITE_NUMSEG]);;
140 let NPRODUCT_CONST_NUMSEG_1 = prove
141 (`!c n. nproduct(1..n) (\x. c) = c EXP n`,
142 SIMP_TAC[NPRODUCT_CONST; CARD_NUMSEG_1; FINITE_NUMSEG]);;
144 let NPRODUCT_ONE = prove
145 (`!s. nproduct s (\n. 1) = 1`,
146 SIMP_TAC[NPRODUCT_EQ_1]);;
148 let NPRODUCT_CLOSED = prove
150 P(1) /\ (!x y. P x /\ P y ==> P(x * y)) /\ (!a. a IN s ==> P(f a))
151 ==> P(nproduct s f)`,
152 REPEAT STRIP_TAC THEN MP_TAC(MATCH_MP ITERATE_CLOSED MONOIDAL_MUL) THEN
153 DISCH_THEN(MP_TAC o SPEC `P:num->bool`) THEN
154 ASM_SIMP_TAC[NEUTRAL_MUL; GSYM nproduct]);;
156 let NPRODUCT_CLAUSES_LEFT = prove
157 (`!f m n. m <= n ==> nproduct(m..n) f = f(m) * nproduct(m+1..n) f`,
158 SIMP_TAC[GSYM NUMSEG_LREC; NPRODUCT_CLAUSES; FINITE_NUMSEG; IN_NUMSEG] THEN
161 let NPRODUCT_CLAUSES_RIGHT = prove
162 (`!f m n. 0 < n /\ m <= n ==> nproduct(m..n) f = nproduct(m..n-1) f * f(n)`,
163 GEN_TAC THEN GEN_TAC THEN INDUCT_TAC THEN
164 SIMP_TAC[LT_REFL; NPRODUCT_CLAUSES_NUMSEG; SUC_SUB1]);;
166 let NPRODUCT_SUPERSET = prove
168 u SUBSET v /\ (!x. x IN v /\ ~(x IN u) ==> f(x) = 1)
169 ==> nproduct v f = nproduct u f`,
170 SIMP_TAC[nproduct; GSYM NEUTRAL_MUL; ITERATE_SUPERSET; MONOIDAL_MUL]);;
172 let NPRODUCT_PAIR = prove
173 (`!f m n. nproduct(2*m..2*n+1) f = nproduct(m..n) (\i. f(2*i) * f(2*i+1))`,
174 MP_TAC(MATCH_MP ITERATE_PAIR MONOIDAL_MUL) THEN
175 REWRITE_TAC[nproduct; NEUTRAL_MUL]);;
177 let NPRODUCT_DELETE = prove
178 (`!f s a. FINITE s /\ a IN s
179 ==> f(a) * nproduct(s DELETE a) f = nproduct s f`,
180 SIMP_TAC[nproduct; ITERATE_DELETE; MONOIDAL_MUL]);;
182 let NPRODUCT_FACT = prove
183 (`!n. nproduct(1..n) (\m. m) = FACT n`,
184 INDUCT_TAC THEN REWRITE_TAC[NPRODUCT_CLAUSES_NUMSEG; FACT; ARITH] THEN
185 ASM_REWRITE_TAC[ARITH_RULE `1 <= SUC n`; MULT_SYM]);;
188 (`(!f g s. (!x. x IN s ==> f(x) = g(x))
189 ==> nproduct s (\i. f(i)) = nproduct s g) /\
190 (!f g a b. (!i. a <= i /\ i <= b ==> f(i) = g(i))
191 ==> nproduct(a..b) (\i. f(i)) = nproduct(a..b) g) /\
192 (!f g p. (!x. p x ==> f x = g x)
193 ==> nproduct {y | p y} (\i. f(i)) = nproduct {y | p y} g)`,
194 REPEAT STRIP_TAC THEN MATCH_MP_TAC NPRODUCT_EQ THEN
195 ASM_SIMP_TAC[IN_ELIM_THM; IN_NUMSEG]) in
196 extend_basic_congs (map SPEC_ALL (CONJUNCTS th));;
198 (* ------------------------------------------------------------------------- *)
199 (* Now products over real numbers. *)
200 (* ------------------------------------------------------------------------- *)
204 let product = new_definition
205 `product = iterate (( * ):real->real->real)`;;
207 let PRODUCT_CLAUSES = prove
208 (`(!f. product {} f = &1) /\
210 ==> (product (x INSERT s) f =
211 if x IN s then product s f else f(x) * product s f))`,
212 REWRITE_TAC[product; GSYM NEUTRAL_REAL_MUL] THEN
213 ONCE_REWRITE_TAC[SWAP_FORALL_THM] THEN
214 MATCH_MP_TAC ITERATE_CLAUSES THEN REWRITE_TAC[MONOIDAL_REAL_MUL]);;
216 let PRODUCT_SUPPORT = prove
217 (`!f s. product (support ( * ) f s) f = product s f`,
218 REWRITE_TAC[product; ITERATE_SUPPORT]);;
220 let PRODUCT_UNION = prove
221 (`!f s t. FINITE s /\ FINITE t /\ DISJOINT s t
222 ==> (product (s UNION t) f = product s f * product t f)`,
223 SIMP_TAC[product; ITERATE_UNION; MONOIDAL_REAL_MUL]);;
225 let PRODUCT_IMAGE = prove
226 (`!f g s. (!x y. x IN s /\ y IN s /\ f x = f y ==> x = y)
227 ==> (product (IMAGE f s) g = product s (g o f))`,
228 REWRITE_TAC[product; GSYM NEUTRAL_REAL_MUL] THEN
229 MATCH_MP_TAC ITERATE_IMAGE THEN REWRITE_TAC[MONOIDAL_REAL_MUL]);;
231 let PRODUCT_ADD_SPLIT = prove
234 ==> (product (m..(n+p)) f = product(m..n) f * product(n+1..n+p) f)`,
235 SIMP_TAC[NUMSEG_ADD_SPLIT; PRODUCT_UNION; DISJOINT_NUMSEG; FINITE_NUMSEG;
236 ARITH_RULE `x < x + 1`]);;
238 let PRODUCT_POS_LE = prove
239 (`!f s. FINITE s /\ (!x. x IN s ==> &0 <= f x) ==> &0 <= product s f`,
240 GEN_TAC THEN REWRITE_TAC[IMP_CONJ] THEN
241 MATCH_MP_TAC FINITE_INDUCT_STRONG THEN
242 SIMP_TAC[PRODUCT_CLAUSES; REAL_POS; IN_INSERT; REAL_LE_MUL]);;
244 let PRODUCT_POS_LE_NUMSEG = prove
245 (`!f m n. (!x. m <= x /\ x <= n ==> &0 <= f x) ==> &0 <= product(m..n) f`,
246 SIMP_TAC[PRODUCT_POS_LE; FINITE_NUMSEG; IN_NUMSEG]);;
248 let PRODUCT_POS_LT = prove
249 (`!f s. FINITE s /\ (!x. x IN s ==> &0 < f x) ==> &0 < product s f`,
250 GEN_TAC THEN REWRITE_TAC[IMP_CONJ] THEN
251 MATCH_MP_TAC FINITE_INDUCT_STRONG THEN
252 SIMP_TAC[PRODUCT_CLAUSES; REAL_LT_01; IN_INSERT; REAL_LT_MUL]);;
254 let PRODUCT_POS_LT_NUMSEG = prove
255 (`!f m n. (!x. m <= x /\ x <= n ==> &0 < f x) ==> &0 < product(m..n) f`,
256 SIMP_TAC[PRODUCT_POS_LT; FINITE_NUMSEG; IN_NUMSEG]);;
258 let PRODUCT_OFFSET = prove
259 (`!f m p. product(m+p..n+p) f = product(m..n) (\i. f(i + p))`,
260 SIMP_TAC[NUMSEG_OFFSET_IMAGE; PRODUCT_IMAGE;
261 EQ_ADD_RCANCEL; FINITE_NUMSEG] THEN
262 REWRITE_TAC[o_DEF]);;
264 let PRODUCT_SING = prove
265 (`!f x. product {x} f = f(x)`,
266 SIMP_TAC[PRODUCT_CLAUSES; FINITE_RULES; NOT_IN_EMPTY; REAL_MUL_RID]);;
268 let PRODUCT_SING_NUMSEG = prove
269 (`!f n. product(n..n) f = f(n)`,
270 REWRITE_TAC[NUMSEG_SING; PRODUCT_SING]);;
272 let PRODUCT_CLAUSES_NUMSEG = prove
273 (`(!m. product(m..0) f = if m = 0 then f(0) else &1) /\
274 (!m n. product(m..SUC n) f = if m <= SUC n then product(m..n) f * f(SUC n)
275 else product(m..n) f)`,
276 REWRITE_TAC[NUMSEG_CLAUSES] THEN REPEAT STRIP_TAC THEN
278 ASM_SIMP_TAC[PRODUCT_SING; PRODUCT_CLAUSES; FINITE_NUMSEG; IN_NUMSEG] THEN
279 REWRITE_TAC[ARITH_RULE `~(SUC n <= n)`; REAL_MUL_AC]);;
281 let PRODUCT_EQ = prove
282 (`!f g s. (!x. x IN s ==> (f x = g x)) ==> product s f = product s g`,
283 REWRITE_TAC[product] THEN MATCH_MP_TAC ITERATE_EQ THEN
284 REWRITE_TAC[MONOIDAL_REAL_MUL]);;
286 let PRODUCT_EQ_NUMSEG = prove
287 (`!f g m n. (!i. m <= i /\ i <= n ==> (f(i) = g(i)))
288 ==> (product(m..n) f = product(m..n) g)`,
289 MESON_TAC[PRODUCT_EQ; FINITE_NUMSEG; IN_NUMSEG]);;
291 let PRODUCT_EQ_0 = prove
292 (`!f s. FINITE s ==> (product s f = &0 <=> ?x. x IN s /\ f(x) = &0)`,
293 GEN_TAC THEN MATCH_MP_TAC FINITE_INDUCT_STRONG THEN
294 SIMP_TAC[PRODUCT_CLAUSES; REAL_ENTIRE; IN_INSERT; REAL_OF_NUM_EQ; ARITH;
298 let PRODUCT_EQ_0_NUMSEG = prove
299 (`!f m n. product(m..n) f = &0 <=> ?x. m <= x /\ x <= n /\ f(x) = &0`,
300 SIMP_TAC[PRODUCT_EQ_0; FINITE_NUMSEG; IN_NUMSEG; GSYM CONJ_ASSOC]);;
302 let PRODUCT_LE = prove
303 (`!f s. FINITE s /\ (!x. x IN s ==> &0 <= f(x) /\ f(x) <= g(x))
304 ==> product s f <= product s g`,
305 GEN_TAC THEN REWRITE_TAC[IMP_CONJ] THEN
306 MATCH_MP_TAC FINITE_INDUCT_STRONG THEN
307 SIMP_TAC[IN_INSERT; PRODUCT_CLAUSES; NOT_IN_EMPTY; REAL_LE_REFL] THEN
308 MESON_TAC[REAL_LE_MUL2; PRODUCT_POS_LE]);;
310 let PRODUCT_LE_NUMSEG = prove
311 (`!f m n. (!i. m <= i /\ i <= n ==> &0 <= f(i) /\ f(i) <= g(i))
312 ==> product(m..n) f <= product(m..n) g`,
313 SIMP_TAC[PRODUCT_LE; FINITE_NUMSEG; IN_NUMSEG]);;
315 let PRODUCT_EQ_1 = prove
316 (`!f s. (!x:A. x IN s ==> (f(x) = &1)) ==> (product s f = &1)`,
317 REWRITE_TAC[product; GSYM NEUTRAL_REAL_MUL] THEN
318 SIMP_TAC[ITERATE_EQ_NEUTRAL; MONOIDAL_REAL_MUL]);;
320 let PRODUCT_EQ_1_NUMSEG = prove
321 (`!f m n. (!i. m <= i /\ i <= n ==> (f(i) = &1)) ==> (product(m..n) f = &1)`,
322 SIMP_TAC[PRODUCT_EQ_1; IN_NUMSEG]);;
324 let PRODUCT_MUL = prove
325 (`!f g s. FINITE s ==> product s (\x. f x * g x) = product s f * product s g`,
326 GEN_TAC THEN GEN_TAC THEN MATCH_MP_TAC FINITE_INDUCT_STRONG THEN
327 SIMP_TAC[PRODUCT_CLAUSES; REAL_MUL_AC; REAL_MUL_LID]);;
329 let PRODUCT_MUL_NUMSEG = prove
331 product(m..n) (\x. f x * g x) = product(m..n) f * product(m..n) g`,
332 SIMP_TAC[PRODUCT_MUL; FINITE_NUMSEG]);;
334 let PRODUCT_CONST = prove
335 (`!c s. FINITE s ==> product s (\x. c) = c pow (CARD s)`,
336 GEN_TAC THEN MATCH_MP_TAC FINITE_INDUCT_STRONG THEN
337 SIMP_TAC[PRODUCT_CLAUSES; CARD_CLAUSES; real_pow]);;
339 let PRODUCT_CONST_NUMSEG = prove
340 (`!c m n. product (m..n) (\x. c) = c pow ((n + 1) - m)`,
341 SIMP_TAC[PRODUCT_CONST; CARD_NUMSEG; FINITE_NUMSEG]);;
343 let PRODUCT_CONST_NUMSEG_1 = prove
344 (`!c n. product(1..n) (\x. c) = c pow n`,
345 SIMP_TAC[PRODUCT_CONST; CARD_NUMSEG_1; FINITE_NUMSEG]);;
347 let PRODUCT_NEG = prove
349 FINITE s ==> product s (\i. --(f i)) = --(&1) pow (CARD s) * product s f`,
350 SIMP_TAC[GSYM PRODUCT_CONST; GSYM PRODUCT_MUL] THEN
351 REWRITE_TAC[REAL_MUL_LNEG; REAL_MUL_LID]);;
353 let PRODUCT_NEG_NUMSEG = prove
354 (`!f m n. product(m..n) (\i. --(f i)) =
355 --(&1) pow ((n + 1) - m) * product(m..n) f`,
356 SIMP_TAC[PRODUCT_NEG; CARD_NUMSEG; FINITE_NUMSEG]);;
358 let PRODUCT_NEG_NUMSEG_1 = prove
359 (`!f n. product(1..n) (\i. --(f i)) = --(&1) pow n * product(1..n) f`,
360 REWRITE_TAC[PRODUCT_NEG_NUMSEG; ADD_SUB]);;
362 let PRODUCT_INV = prove
363 (`!f s. FINITE s ==> product s (\x. inv(f x)) = inv(product s f)`,
364 GEN_TAC THEN MATCH_MP_TAC FINITE_INDUCT_STRONG THEN
365 SIMP_TAC[PRODUCT_CLAUSES; REAL_INV_1; REAL_INV_MUL]);;
367 let PRODUCT_DIV = prove
368 (`!f g s. FINITE s ==> product s (\x. f x / g x) = product s f / product s g`,
369 SIMP_TAC[real_div; PRODUCT_MUL; PRODUCT_INV]);;
371 let PRODUCT_DIV_NUMSEG = prove
373 product(m..n) (\x. f x / g x) = product(m..n) f / product(m..n) g`,
374 SIMP_TAC[PRODUCT_DIV; FINITE_NUMSEG]);;
376 let PRODUCT_ONE = prove
377 (`!s. product s (\n. &1) = &1`,
378 SIMP_TAC[PRODUCT_EQ_1]);;
380 let PRODUCT_LE_1 = prove
381 (`!f s. FINITE s /\ (!x. x IN s ==> &0 <= f x /\ f x <= &1)
382 ==> product s f <= &1`,
383 GEN_TAC THEN REWRITE_TAC[IMP_CONJ] THEN
384 MATCH_MP_TAC FINITE_INDUCT_STRONG THEN
385 SIMP_TAC[PRODUCT_CLAUSES; REAL_LE_REFL; IN_INSERT] THEN
386 REPEAT STRIP_TAC THEN GEN_REWRITE_TAC RAND_CONV [GSYM REAL_MUL_LID] THEN
387 MATCH_MP_TAC REAL_LE_MUL2 THEN ASM_SIMP_TAC[PRODUCT_POS_LE]);;
389 let PRODUCT_ABS = prove
390 (`!f s. FINITE s ==> product s (\x. abs(f x)) = abs(product s f)`,
391 GEN_TAC THEN MATCH_MP_TAC FINITE_INDUCT_STRONG THEN
392 SIMP_TAC[PRODUCT_CLAUSES; REAL_ABS_MUL; REAL_ABS_NUM]);;
394 let PRODUCT_CLOSED = prove
396 P(&1) /\ (!x y. P x /\ P y ==> P(x * y)) /\ (!a. a IN s ==> P(f a))
398 REPEAT STRIP_TAC THEN MP_TAC(MATCH_MP ITERATE_CLOSED MONOIDAL_REAL_MUL) THEN
399 DISCH_THEN(MP_TAC o SPEC `P:real->bool`) THEN
400 ASM_SIMP_TAC[NEUTRAL_REAL_MUL; GSYM product]);;
402 let PRODUCT_CLAUSES_LEFT = prove
403 (`!f m n. m <= n ==> product(m..n) f = f(m) * product(m+1..n) f`,
404 SIMP_TAC[GSYM NUMSEG_LREC; PRODUCT_CLAUSES; FINITE_NUMSEG; IN_NUMSEG] THEN
407 let PRODUCT_CLAUSES_RIGHT = prove
408 (`!f m n. 0 < n /\ m <= n ==> product(m..n) f = product(m..n-1) f * f(n)`,
409 GEN_TAC THEN GEN_TAC THEN INDUCT_TAC THEN
410 SIMP_TAC[LT_REFL; PRODUCT_CLAUSES_NUMSEG; SUC_SUB1]);;
412 let REAL_OF_NUM_NPRODUCT = prove
413 (`!f:A->num s. FINITE s ==> &(nproduct s f) = product s (\x. &(f x))`,
414 GEN_TAC THEN MATCH_MP_TAC FINITE_INDUCT_STRONG THEN
415 SIMP_TAC[PRODUCT_CLAUSES; NPRODUCT_CLAUSES; GSYM REAL_OF_NUM_MUL]);;
417 let PRODUCT_SUPERSET = prove
419 u SUBSET v /\ (!x. x IN v /\ ~(x IN u) ==> f(x) = &1)
420 ==> product v f = product u f`,
421 SIMP_TAC[product; GSYM NEUTRAL_REAL_MUL;
422 ITERATE_SUPERSET; MONOIDAL_REAL_MUL]);;
424 let PRODUCT_PAIR = prove
425 (`!f m n. product(2*m..2*n+1) f = product(m..n) (\i. f(2*i) * f(2*i+1))`,
426 MP_TAC(MATCH_MP ITERATE_PAIR MONOIDAL_REAL_MUL) THEN
427 REWRITE_TAC[product; NEUTRAL_REAL_MUL]);;
429 let PRODUCT_DELETE = prove
430 (`!f s a. FINITE s /\ a IN s ==> f(a) * product(s DELETE a) f = product s f`,
431 SIMP_TAC[product; ITERATE_DELETE; MONOIDAL_REAL_MUL]);;
433 (* ------------------------------------------------------------------------- *)
434 (* Extend congruences. *)
435 (* ------------------------------------------------------------------------- *)
438 (`(!f g s. (!x. x IN s ==> f(x) = g(x))
439 ==> product s (\i. f(i)) = product s g) /\
440 (!f g a b. (!i. a <= i /\ i <= b ==> f(i) = g(i))
441 ==> product(a..b) (\i. f(i)) = product(a..b) g) /\
442 (!f g p. (!x. p x ==> f x = g x)
443 ==> product {y | p y} (\i. f(i)) = product {y | p y} g)`,
444 REPEAT STRIP_TAC THEN MATCH_MP_TAC PRODUCT_EQ THEN
445 ASM_SIMP_TAC[IN_ELIM_THM; IN_NUMSEG]) in
446 extend_basic_congs (map SPEC_ALL (CONJUNCTS th));;