(* ========================================================================= *)
(* Various convenient background stuff. *)
(* *)
(* (c) Copyright, John Harrison 1998-2008 *)
(* ========================================================================= *)
prioritize_real();;
(* ------------------------------------------------------------------------- *)
(* A couple of extra tactics used in some proofs below. *)
(* ------------------------------------------------------------------------- *)
let ASSERT_TAC tm =
SUBGOAL_THEN tm STRIP_ASSUME_TAC;;
let EQ_TRANS_TAC tm =
MATCH_MP_TAC EQ_TRANS THEN EXISTS_TAC tm THEN CONJ_TAC;;
(* ------------------------------------------------------------------------- *)
(* Miscellaneous lemmas. *)
(* ------------------------------------------------------------------------- *)
let SEQ_MONO_LEMMA = prove
(`!d e. (!n. n >= m ==> d(n) < e(n)) /\ (!n. n >= m ==> e(n) <= e(m))
==> !n:num. n >= m ==> d(n) < e(m)`,
let REAL_HALF = prove
(`(!e. &0 < e / &2 <=> &0 < e) /\
(!e. e / &2 + e / &2 = e) /\
(!e. &2 * (e / &2) = e)`,
REAL_ARITH_TAC);;
let TRIANGLE_LEMMA = prove
(`!x y z. &0 <= x /\ &0 <= y /\ &0 <= z /\ x pow 2 <= y pow 2 + z pow 2
==> x <= y + z`,
REPEAT GEN_TAC THEN
REPEAT(DISCH_THEN(CONJUNCTS_THEN2 ASSUME_TAC MP_TAC)) THEN
ONCE_REWRITE_TAC[GSYM CONTRAPOS_THM] THEN
REWRITE_TAC[
REAL_NOT_LE] THEN DISCH_TAC THEN
MATCH_MP_TAC
REAL_LET_TRANS THEN EXISTS_TAC `(y + z) pow 2` THEN
ASM_SIMP_TAC[
REAL_POW_LT2;
REAL_LE_ADD;
ARITH_EQ] THEN
ASM_SIMP_TAC[
REAL_LE_MUL; REAL_POW_2; REAL_ARITH
`x * x + y * y <= (x + y) * (x + y) <=> &0 <= x * y`]);;
let LAMBDA_SKOLEM = prove
(`(!i. 1 <= i /\ i <= dimindex(:N) ==> ?x. P i x) =
(?x:A^N. !i. 1 <= i /\ i <= dimindex(:N) ==> P i (x$i))`,
REWRITE_TAC[
RIGHT_IMP_EXISTS_THM;
SKOLEM_THM] THEN EQ_TAC THENL
[DISCH_THEN(X_CHOOSE_TAC `x:num->A`) THEN
EXISTS_TAC `(lambda i. x i):A^N` THEN ASM_SIMP_TAC[
LAMBDA_BETA];
DISCH_THEN(X_CHOOSE_TAC `x:A^N`) THEN
EXISTS_TAC `\i. (x:A^N)$i` THEN ASM_REWRITE_TAC[]]);;
let EPSILON_DELTA_MINIMAL = prove
(`!P:real->A->bool Q.
FINITE {x | Q x} /\
(!d e x. Q x /\ &0 < e /\ e < d ==> P d x ==> P e x) /\
(!x. Q x ==> ?d. &0 < d /\ P d x)
==> ?d. &0 < d /\ !x. Q x ==> P d x`,
(* ------------------------------------------------------------------------- *)
(* A generic notion of "hull" (convex, affine, conic hull and closure). *)
(* ------------------------------------------------------------------------- *)
parse_as_infix("hull",(21,"left"));;
let HULL_IMAGE = prove
(`!P f s. (!s. P(P hull s)) /\ (!s. P(
IMAGE f s) <=> P s) /\
(!x y:A. f x = f y ==> x = y) /\ (!y. ?x. f x = y)
==> P hull (
IMAGE f s) =
IMAGE f (P hull s)`,
REPEAT GEN_TAC THEN
REPLICATE_TAC 2 (DISCH_THEN(CONJUNCTS_THEN2 ASSUME_TAC MP_TAC)) THEN
REWRITE_TAC[
BIJECTIVE_LEFT_RIGHT_INVERSE] THEN
DISCH_THEN(X_CHOOSE_THEN `g:A->A` STRIP_ASSUME_TAC) THEN
MATCH_MP_TAC
HULL_IMAGE_GALOIS THEN EXISTS_TAC `g:A->A` THEN
ASM_REWRITE_TAC[] THEN CONJ_TAC THENL [ALL_TAC; ASM SET_TAC[]] THEN
X_GEN_TAC `s:A->bool` THEN
FIRST_X_ASSUM(fun th -> GEN_REWRITE_TAC RAND_CONV [GSYM th]) THEN
MATCH_MP_TAC EQ_IMP THEN AP_TERM_TAC THEN ASM SET_TAC[]);;
let HULL_P_AND_Q = prove
(`!P Q. (!f. (!s. s
IN f ==> P s) ==> P(
INTERS f)) /\
(!f. (!s. s
IN f ==> Q s) ==> Q(
INTERS f)) /\
(!s. Q s ==> Q(P hull s))
==> (\x. P x /\ Q x) hull s = P hull (Q hull s)`,
(* ------------------------------------------------------------------------- *)
(* More variants of the Archimedian property and useful consequences. *)
(* ------------------------------------------------------------------------- *)
let REAL_ARCH_POW = prove
(`!x y. &1 < x ==> ?n. y < x pow n`,
REPEAT STRIP_TAC THEN
MP_TAC(SPEC `x - &1`
REAL_ARCH) THEN ASM_REWRITE_TAC[
REAL_SUB_LT] THEN
DISCH_THEN(MP_TAC o SPEC `y:real`) THEN MATCH_MP_TAC
MONO_EXISTS THEN
X_GEN_TAC `n:num` THEN DISCH_TAC THEN MATCH_MP_TAC
REAL_LTE_TRANS THEN
EXISTS_TAC `&1 + &n * (x - &1)` THEN
ASM_SIMP_TAC[REAL_ARITH `x < y ==> x < &1 + y`] THEN
ASM_MESON_TAC[
REAL_POW_LBOUND;
REAL_SUB_ADD2; REAL_ARITH
`&1 < x ==> &0 <= x - &1`]);;
let FORALL_POS_MONO = prove
(`!P. (!d e. d < e /\ P d ==> P e) /\ (!n. ~(n = 0) ==> P(inv(&n)))
==> !e. &0 < e ==> P e`,
(* ------------------------------------------------------------------------- *)
(* Relate max and min to sup and inf. *)
(* ------------------------------------------------------------------------- *)
(* ------------------------------------------------------------------------- *)
(* Define square root here to decouple it from the existing analysis theory. *)
(* We totalize by making sqrt(-x) = -sqrt(x), which looks rather unnatural *)
(* but allows many convenient properties to be used without sideconditions. *)
(* ------------------------------------------------------------------------- *)
let SQRT_UNIQUE = prove
(`!x y. &0 <= y /\ y pow 2 = x ==> sqrt(x) = y`,
REPEAT STRIP_TAC THEN REWRITE_TAC[sqrt] THEN MATCH_MP_TAC
SELECT_UNIQUE THEN
FIRST_X_ASSUM(SUBST1_TAC o SYM) THEN
REWRITE_TAC[
REAL_SGN_POW_2;
REAL_ABS_POW] THEN
X_GEN_TAC `z:real` THEN ASM_REWRITE_TAC[
real_abs] THEN
REWRITE_TAC[REAL_RING `x pow 2 = y pow 2 <=> x:real = y \/ x = --y`] THEN
REWRITE_TAC[
real_sgn] THEN ASM_REAL_ARITH_TAC);;
(* ------------------------------------------------------------------------- *)
(* Geometric progression. *)
(* ------------------------------------------------------------------------- *)
let SUM_GP = prove
(`!x m n.
sum(m..n) (\i. x pow i) =
if n < m then &0
else if x = &1 then &((n + 1) - m)
else (x pow m - x pow (SUC n)) / (&1 - x)`,
let SUM_GP_OFFSET = prove
(`!x m n. sum(m..m+n) (\i. x pow i) =
if x = &1 then &n + &1
else x pow m * (&1 - x pow (SUC n)) / (&1 - x)`,
REPEAT GEN_TAC THEN REWRITE_TAC[
SUM_GP; ARITH_RULE `~(m + n < m:num)`] THEN
COND_CASES_TAC THEN ASM_REWRITE_TAC[] THENL
[REWRITE_TAC[REAL_OF_NUM_ADD] THEN AP_TERM_TAC THEN ARITH_TAC;
REWRITE_TAC[
real_div;
real_pow;
REAL_POW_ADD] THEN REAL_ARITH_TAC]);;
(* ------------------------------------------------------------------------- *)
(* Segment of natural numbers starting at a specific number. *)
(* ------------------------------------------------------------------------- *)
(* ------------------------------------------------------------------------- *)
(* Make a Horner-style evaluation of sum(m..n) (\k. a(k) * x pow k). *)
(* ------------------------------------------------------------------------- *)
let HORNER_SUM_CONV =
let horner_0,horner_s = (CONJ_PAIR o prove)
(`(sum(0..0) (\i. c(i) * x pow i) = c 0) /\
(sum(0..SUC n) (\i. c(i) * x pow i) =
c(0) + x * sum(0..n) (\i. c(i+1) * x pow i))`,
REWRITE_TAC[CONJUNCT1 SUM_CLAUSES_NUMSEG] THEN
REWRITE_TAC[GSYM SUM_LMUL] THEN
ONCE_REWRITE_TAC[REAL_ARITH `x * c * y:real = c * x * y`] THEN
REWRITE_TAC[GSYM(CONJUNCT2 real_pow); ADD1] THEN
REWRITE_TAC[GSYM(SPEC `1` SUM_OFFSET)] THEN
SIMP_TAC[SUM_CLAUSES_LEFT; LE_0; real_pow; REAL_MUL_RID]) in
let conv_0 = GEN_REWRITE_CONV I [horner_0] THENC NUM_REDUCE_CONV
and conv_s = LAND_CONV(RAND_CONV(num_CONV)) THENC
GEN_REWRITE_CONV I [horner_s] THENC
GEN_REWRITE_CONV ONCE_DEPTH_CONV [LEFT_ADD_DISTRIB] THENC
GEN_REWRITE_CONV TOP_DEPTH_CONV [GSYM ADD_ASSOC] THENC
NUM_REDUCE_CONV in
let rec conv tm =
try (conv_0 THENC REAL_RAT_REDUCE_CONV) tm with Failure _ ->
(conv_s THENC RAND_CONV(RAND_CONV conv) THENC REAL_RAT_REDUCE_CONV) tm in
conv;;