(* ========================================================================= *)
(* The integer/rational-valued reals, and the "floor" and "frac" functions. *)
(* ========================================================================= *)
prioritize_real();;
(* ------------------------------------------------------------------------- *)
(* Closure theorems and other lemmas for the integer-valued reals. *)
(* ------------------------------------------------------------------------- *)
let REAL_ABS_INTEGER_LEMMA = prove
(`!x. integer(x) /\ ~(x = &0) ==> &1 <= abs(x)`,
GEN_TAC THEN REWRITE_TAC[integer] THEN
DISCH_THEN(CONJUNCTS_THEN2 ASSUME_TAC MP_TAC) THEN
ONCE_REWRITE_TAC[REAL_ARITH `(x = &0) <=> (abs(x) = &0)`] THEN
POP_ASSUM(CHOOSE_THEN SUBST1_TAC) THEN
REWRITE_TAC[REAL_OF_NUM_EQ; REAL_OF_NUM_LE] THEN ARITH_TAC);;
let INTEGER_CLOSED = prove
(`(!n. integer(&n)) /\
(!x y. integer(x) /\ integer(y) ==> integer(x + y)) /\
(!x y. integer(x) /\ integer(y) ==> integer(x - y)) /\
(!x y. integer(x) /\ integer(y) ==> integer(x * y)) /\
(!x r. integer(x) ==> integer(x pow r)) /\
(!x. integer(x) ==> integer(--x)) /\
(!x. integer(x) ==> integer(abs x))`,
REWRITE_TAC[integer] THEN
MATCH_MP_TAC(TAUT
`x /\ c /\ d /\ e /\ f /\ (a /\ e ==> b) /\ a
==> x /\ a /\ b /\ c /\ d /\ e /\ f`) THEN
REPEAT CONJ_TAC THENL
[REWRITE_TAC[
REAL_ABS_NUM] THEN MESON_TAC[];
REWRITE_TAC[
REAL_ABS_MUL] THEN MESON_TAC[REAL_OF_NUM_MUL];
REWRITE_TAC[
REAL_ABS_POW] THEN MESON_TAC[
REAL_OF_NUM_POW];
REWRITE_TAC[
REAL_ABS_NEG]; REWRITE_TAC[
REAL_ABS_ABS];
REWRITE_TAC[
real_sub] THEN MESON_TAC[]; ALL_TAC] THEN
SIMP_TAC[REAL_ARITH `&0 <= a ==> ((abs(x) = a) <=> (x = a) \/ (x = --a))`;
REAL_POS] THEN
REPEAT STRIP_TAC THEN
ASM_REWRITE_TAC[GSYM
REAL_NEG_ADD; REAL_OF_NUM_ADD] THENL
[MESON_TAC[]; ALL_TAC; ALL_TAC; MESON_TAC[]] THEN
REWRITE_TAC[REAL_ARITH `(--a + b = c) <=> (a + c = b)`;
REAL_ARITH `(a + --b = c) <=> (b + c = a)`] THEN
REWRITE_TAC[REAL_OF_NUM_ADD; REAL_OF_NUM_EQ] THEN
MESON_TAC[
LE_EXISTS;
ADD_SYM;
LE_CASES]);;
let REAL_EQ_INTEGERS = prove
(`!x y. integer x /\ integer y ==> (x = y <=> abs(x - y) < &1)`,
REWRITE_TAC[REAL_ARITH `x = y <=> ~(x < y \/ y < x)`] THEN
SIMP_TAC[
REAL_LT_INTEGERS] THEN REAL_ARITH_TAC);;
let INTEGER_ADD_EQ = prove
(`(!x y. integer(x) ==> (integer(x + y) <=> integer(y))) /\
(!x y. integer(y) ==> (integer(x + y) <=> integer(x)))`,
let INTEGER_SUB_EQ = prove
(`(!x y. integer(x) ==> (integer(x - y) <=> integer(y))) /\
(!x y. integer(y) ==> (integer(x - y) <=> integer(x)))`,
let INTEGER_ABS_MUL_EQ_1 = prove
(`!x y. integer x /\ integer y
==> (abs(x * y) = &1 <=> abs x = &1 /\ abs y = &1)`,
REWRITE_TAC[integer] THEN
REPEAT STRIP_TAC THEN ASM_REWRITE_TAC[
REAL_ABS_MUL] THEN
REWRITE_TAC[REAL_OF_NUM_EQ; REAL_OF_NUM_MUL;
MULT_EQ_1]);;
(* ------------------------------------------------------------------------- *)
(* Similar theorems for rational-valued reals. *)
(* ------------------------------------------------------------------------- *)
let RATIONAL_INTEGER = prove
(`!x. integer x ==> rational x`,
GEN_TAC THEN DISCH_TAC THEN REWRITE_TAC[rational] THEN
MAP_EVERY EXISTS_TAC [`x:real`; `&1`] THEN
ASM_SIMP_TAC[
INTEGER_CLOSED] THEN CONV_TAC REAL_FIELD);;
let RATIONAL_NEG = prove
(`!x. rational(x) ==> rational(--x)`,
REWRITE_TAC[rational;
LEFT_IMP_EXISTS_THM] THEN
MAP_EVERY X_GEN_TAC [`x:real`; `m:real`; `n:real`] THEN
STRIP_TAC THEN
MAP_EVERY EXISTS_TAC [`--m:real`; `n:real`] THEN
ASM_SIMP_TAC[
INTEGER_CLOSED] THEN CONV_TAC REAL_FIELD);;
let RATIONAL_INV = prove
(`!x. rational(x) ==> rational(inv x)`,
GEN_TAC THEN ASM_CASES_TAC `x = &0` THEN
ASM_SIMP_TAC[REAL_INV_0;
RATIONAL_NUM] THEN
REWRITE_TAC[rational;
LEFT_IMP_EXISTS_THM] THEN
MAP_EVERY X_GEN_TAC [`m:real`; `n:real`] THEN STRIP_TAC THEN
MAP_EVERY EXISTS_TAC [`n:real`; `m:real`] THEN
ASM_SIMP_TAC[
INTEGER_CLOSED] THEN
REPEAT(POP_ASSUM MP_TAC) THEN CONV_TAC REAL_FIELD);;
let RATIONAL_CLOSED = prove
(`(!n. rational(&n)) /\
(!x. integer x ==> rational x) /\
(!x y. rational(x) /\ rational(y) ==> rational(x + y)) /\
(!x y. rational(x) /\ rational(y) ==> rational(x - y)) /\
(!x y. rational(x) /\ rational(y) ==> rational(x * y)) /\
(!x y. rational(x) /\ rational(y) ==> rational(x / y)) /\
(!x r. rational(x) ==> rational(x pow r)) /\
(!x. rational(x) ==> rational(--x)) /\
(!x. rational(x) ==> rational(inv x)) /\
(!x. rational(x) ==> rational(abs x))`,
let RATIONAL_ALT = prove
(`!x. rational(x) <=> ?p q. ~(q = 0) /\ abs x = &p / &q`,
GEN_TAC THEN REWRITE_TAC[rational] THEN EQ_TAC THENL
[REWRITE_TAC[integer] THEN STRIP_TAC THEN ASM_REWRITE_TAC[
REAL_ABS_DIV] THEN
ASM_MESON_TAC[REAL_OF_NUM_EQ;
REAL_ABS_ZERO];
STRIP_TAC THEN FIRST_X_ASSUM(DISJ_CASES_THEN SUBST1_TAC o MATCH_MP
(REAL_ARITH `abs(x:real) = a ==> x = a \/ x = --a`)) THEN
ASM_REWRITE_TAC[
real_div; GSYM
REAL_MUL_LNEG] THEN
REWRITE_TAC[GSYM
real_div] THEN
ASM_MESON_TAC[
INTEGER_CLOSED; REAL_OF_NUM_EQ]]);;
(* ------------------------------------------------------------------------- *)
(* The floor and frac functions. *)
(* ------------------------------------------------------------------------- *)
let REAL_TRUNCATE_POS = prove
(`!x. &0 <= x ==> ?n r. &0 <= r /\ r < &1 /\ (x = &n + r)`,
REPEAT STRIP_TAC THEN MP_TAC(SPEC `x:real`
REAL_ARCH_SIMPLE) THEN
GEN_REWRITE_TAC LAND_CONV [
num_WOP] THEN
REWRITE_TAC[
LEFT_IMP_EXISTS_THM] THEN
INDUCT_TAC THEN REWRITE_TAC[
LT_SUC_LE; CONJUNCT1
LT] THENL
[DISCH_TAC THEN MAP_EVERY EXISTS_TAC [`0`; `&0`] THEN ASM_REAL_ARITH_TAC;
POP_ASSUM_LIST(K ALL_TAC)] THEN
REWRITE_TAC[GSYM
REAL_OF_NUM_SUC] THEN
DISCH_THEN(CONJUNCTS_THEN2 ASSUME_TAC (MP_TAC o SPEC `n:num`)) THEN
REWRITE_TAC[
LE_REFL;
REAL_NOT_LE] THEN DISCH_TAC THEN
FIRST_X_ASSUM(DISJ_CASES_THEN STRIP_ASSUME_TAC o REWRITE_RULE[
REAL_LE_LT])
THENL
[MAP_EVERY EXISTS_TAC [`n:num`; `x - &n`] THEN ASM_REAL_ARITH_TAC;
MAP_EVERY EXISTS_TAC [`SUC n`; `x - &(SUC n)`] THEN
REWRITE_TAC[
REAL_ADD_SUB; GSYM
REAL_OF_NUM_SUC] THEN ASM_REAL_ARITH_TAC]);;
"frac"]
(REWRITE_RULE[SKOLEM_THM] REAL_TRUNCATE);;
(* ------------------------------------------------------------------------- *)
(* Useful lemmas about floor and frac. *)
(* ------------------------------------------------------------------------- *)
let FLOOR_UNIQUE = prove
(`!x a. integer(a) /\ a <= x /\ x < a + &1 <=> (floor x = a)`,
REPEAT GEN_TAC THEN EQ_TAC THENL
[STRIP_TAC THEN STRIP_ASSUME_TAC(SPEC `x:real`
FLOOR_FRAC) THEN
SUBGOAL_THEN `abs(floor x - a) < &1` MP_TAC THENL
[ASM_REAL_ARITH_TAC; ALL_TAC] THEN
ONCE_REWRITE_TAC[GSYM CONTRAPOS_THM] THEN
DISCH_TAC THEN REWRITE_TAC[
REAL_NOT_LT] THEN
MATCH_MP_TAC
REAL_ABS_INTEGER_LEMMA THEN CONJ_TAC THENL
[ASM_MESON_TAC[
INTEGER_CLOSED]; ASM_REAL_ARITH_TAC];
DISCH_THEN(SUBST1_TAC o SYM) THEN
MP_TAC(SPEC `x:real`
FLOOR_FRAC) THEN
SIMP_TAC[] THEN REAL_ARITH_TAC]);;
let FLOOR = prove
(`!x. integer(floor x) /\ floor(x) <= x /\ x < floor(x) + &1`,
GEN_TAC THEN MP_TAC(SPEC `x:real`
FLOOR_FRAC) THEN
DISCH_THEN(CONJUNCTS_THEN2 ASSUME_TAC MP_TAC) THEN
ASM_REWRITE_TAC[] THEN REAL_ARITH_TAC);;
let FLOOR_DOUBLE = prove
(`!u. &2 * floor(u) <= floor(&2 * u) /\ floor(&2 * u) <= &2 * floor(u) + &1`,
let REAL_FLOOR_ADD = prove
(`!x y. floor(x + y) = if frac x + frac y < &1 then floor(x) + floor(y)
else (floor(x) + floor(y)) + &1`,
REPEAT GEN_TAC THEN REWRITE_TAC[GSYM
FLOOR_UNIQUE] THEN
CONJ_TAC THENL [ASM_MESON_TAC[
INTEGER_CLOSED;
FLOOR]; ALL_TAC] THEN
MAP_EVERY (MP_TAC o C SPEC
FLOOR_FRAC)[`x:real`; `y:real`; `x + y:real`] THEN
REAL_ARITH_TAC);;
let REAL_FRAC_ADD = prove
(`!x y. frac(x + y) = if frac x + frac y < &1 then frac(x) + frac(y)
else (frac(x) + frac(y)) - &1`,
let FRAC_UNIQUE = prove
(`!x a. integer(x - a) /\ &0 <= a /\ a < &1 <=> frac x = a`,
REWRITE_TAC[
FRAC_FLOOR; REAL_ARITH `x - f:real = a <=> f = x - a`] THEN
REPEAT GEN_TAC THEN REWRITE_TAC[GSYM
FLOOR_UNIQUE] THEN
AP_TERM_TAC THEN REAL_ARITH_TAC);;
let INTEGER_ROUND = prove
(`!x. ?n. integer n /\ abs(x - n) <= &1 / &2`,
GEN_TAC THEN MATCH_MP_TAC(MESON[] `!a. P a \/ P(a + &1) ==> ?x. P x`) THEN
EXISTS_TAC `floor x` THEN MP_TAC(ISPEC `x:real`
FLOOR) THEN
SIMP_TAC[
INTEGER_CLOSED] THEN REAL_ARITH_TAC);;
(* ------------------------------------------------------------------------- *)
(* Assertions that there are integers between well-spaced reals. *)
(* ------------------------------------------------------------------------- *)
let INTEGER_EXISTS_BETWEEN_ALT = prove
(`!x y. x + &1 <= y ==> ?n. integer n /\ x < n /\ n <= y`,
REPEAT STRIP_TAC THEN EXISTS_TAC `floor y` THEN
MP_TAC(SPEC `y:real`
FLOOR) THEN SIMP_TAC[] THEN ASM_REAL_ARITH_TAC);;
(* ------------------------------------------------------------------------- *)
(* A couple more theorems about real_of_int. *)
(* ------------------------------------------------------------------------- *)
(* ------------------------------------------------------------------------- *)
(* Finiteness of bounded set of integers. *)
(* ------------------------------------------------------------------------- *)
(* ------------------------------------------------------------------------- *)
(* Yet set of all integers or rationals is infinite. *)
(* ------------------------------------------------------------------------- *)
(* ------------------------------------------------------------------------- *)
(* Arbitrarily good rational approximations. *)
(* ------------------------------------------------------------------------- *)