(* ========================================================================= *)
(* Define integer sums, with most theorems derived automatically. *)
(* ========================================================================= *)
let int_isum = prove
(`!f:A->int s. real_of_int(isum s f) = sum s (\x. real_of_int(f x))`,
(* ------------------------------------------------------------------------- *)
(* Generalize INT_OF_REAL_THM for most common sum patterns. *)
(* ------------------------------------------------------------------------- *)
let INT_OF_REAL_THM =
let dest = `real_of_int`
and real_ty = `:real`
and int_ty = `:int`
and cond_th = prove
(`real_of_int(if b then x else y) =
if b then real_of_int x else real_of_int y`,
COND_CASES_TAC THEN REWRITE_TAC[])
and compose_th = prove
(`(\x. real_of_int((f o g) x)) = (\x. real_of_int(f x)) o g`,
REWRITE_TAC[o_DEF]) in
let thlist = map GSYM
[int_eq; int_le; int_lt; int_ge; int_gt;
int_of_num_th; int_neg_th; int_add_th; int_mul_th;
int_sub_th; int_abs_th; int_max_th; int_min_th; int_pow_th;
int_isum; GSYM BETA_THM; GSYM ETA_AX; compose_th; cond_th] in
let REW_RULE = GEN_REWRITE_RULE REDEPTH_CONV thlist in
let is_fun_into_real ty =
try match dest_type ty with
"fun",[s;t] when t = real_ty -> mk_fun_ty s int_ty
| "real",[] -> int_ty
| _ -> failwith ""
with Failure _ -> ty in
let int_of_real_ty ty =
try match dest_type ty with
"real",[] -> int_ty
| "fun",[s;t] when t = real_ty -> mk_fun_ty s int_ty
| _ -> ty
with Failure _ -> ty in
let int_tm_of_real_var v =
let s,ty = dest_var v in
let tys,rty = splitlist dest_fun_ty ty in
if rty <> real_ty then v else
let ity = itlist mk_fun_ty tys int_ty in
let vs = map genvar tys in
list_mk_abs(vs,mk_comb(dest,list_mk_comb(mk_var(s,ity),vs))) in
let int_of_real_var v =
let s,ty = dest_var v in
let tys,rty = splitlist dest_fun_ty ty in
if rty <> real_ty then v else
let ity = itlist mk_fun_ty tys int_ty in
mk_var(s,ity) in
let INT_OF_REAL_THM1 th =
let newavs = subtract (frees (concl th)) (freesl (hyp th)) in
let avs,bod = strip_forall(concl th) in
let allavs = newavs@avs in
let avs' = map int_tm_of_real_var allavs in
let avs'' = map int_of_real_var avs in
GENL avs'' (REW_RULE(SPECL avs' (GENL newavs th))) in
let rec INT_OF_REAL_THM th =
if is_conj(concl th) then CONJ (INT_OF_REAL_THM1 (CONJUNCT1 th))
(INT_OF_REAL_THM1 (CONJUNCT2 th))
else INT_OF_REAL_THM1 th in
INT_OF_REAL_THM;;
(* ------------------------------------------------------------------------- *)
(* Apply it in all the cases where it works. *)
(* ------------------------------------------------------------------------- *)
(* ------------------------------------------------------------------------- *)
(* Manually derive the few cases where it doesn't. *)
(* *)
(* Note that SUM_BOUND_GEN and SUM_BOUND_LT_GEN don't seem to have immediate *)
(* analogs over the integers since they involve division. *)
(* *)
(* Should really roll ADMISSIBLE_ISUM into "define" as well. *)
(* ------------------------------------------------------------------------- *)
let ADMISSIBLE_ISUM = prove
(`!(<<) p:(B->C)->P->bool s:P->A h a b.
admissible(<<) (\f (k,x). a(x) <= k /\ k <= b(x) /\ p f x)
(\(k,x). s x) (\f (k,x). h f x k)
==> admissible(<<) p s (\f x. isum(a(x)..b(x)) (h f x))`,
(* ------------------------------------------------------------------------- *)
(* Extend the congruences. *)
(* ------------------------------------------------------------------------- *)
let th = prove
(`(!f g s. (!x. x
IN s ==> f(x) = g(x))
==> isum s (\i. f(i)) = isum s g) /\
(!f g a b. (!i. a <= i /\ i <= b ==> f(i) = g(i))
==> isum(a..b) (\i. f(i)) = isum(a..b) g) /\
(!f g p. (!x. p x ==> f x = g x)
==> isum {y | p y} (\i. f(i)) = isum {y | p y} g)`,
REPEAT STRIP_TAC THEN MATCH_MP_TAC
ISUM_EQ THEN
ASM_SIMP_TAC[
IN_ELIM_THM;
IN_NUMSEG]) in
extend_basic_congs (map SPEC_ALL (CONJUNCTS th));;