(* ========================================================================== *)
(* FLYSPECK - BOOK FORMALIZATION *)
(* *)
(* Chapter: Jordan *)
(* Copied from HOL Light jordan directory *)
(* Author: Thomas C. Hales *)
(* Date: 2010-07-08 *)
(* ========================================================================== *)
(*
A handheld calculator, implemented in HOL light.
It implements + - / * sqrt, ssqrt, abs, atn, acs, pi,
The user can supply additional conversons to extend the calculator to other functions.
There is an example file float_example.hl.
*)
(* based on float.ml in hol/jordan/float.ml *)
(*
To do. Allow the user to supply theorems that carry domain constraints,
(such as ACS_ATN).
*)
flyspeck_needs "jordan/taylor_atn.hl";;
module Float = struct
open Lib_ext;;
open Num_ext_nabs;;
open Real_ext;;
open Refinement;;
open Tactics_jordan;;
open Taylor_atn;;
Parse_ext_override_interface.unambiguous_interface();;
Parse_ext_override_interface.prioritize_real();;
(* Three types of error:
Insufficient precision: the inequality might be true but there is not enough
precision to decide. Divide by zero generally lands here, because there is
no testing for exact equality.
Internal failure: a bug in this code.
User input failure: sqrt of negative numbers, false inequalities.
*)
exception Insufficient_precision;;
(*
exception Mk_comb of (term*hol_type)*(term*hol_type);;
let mk_comb(a,b) = try mk_comb(a,b) with
Failure _ -> raise (Mk_comb((a,type_of a),(b,type_of b)));;
*)
let add_test,test = new_test_suite();;
(*--------------------------------------------------------------------*)
let mk_interval a b ex =
mk_comb(mk_comb (mk_comb (`interval_eps`,a),b),ex);;
add_test("mk_interval",
mk_interval `#3` `#4` `#1` = `interval_eps #3 #4 #1`);;
let dest_interval intv =
let (h1,ex) = dest_comb intv in
let (h2,f) = dest_comb h1 in
let (h3,a) = dest_comb h2 in
let _ = (h3 = `interval_eps`) or (print_term h3; failwith "dest_interval:interval_eps") in
(a,f,ex);;
let _ = add_test("dest_interval",
let a = `#3` and b = `#4` and c = `#1` in
dest_interval (mk_interval a b c) = (a,b,c));;
(*--------------------------------------------------------------------*)
let (dest_int:term-> Num.num) =
fun b ->
let dest_pos_int a =
let (op,nat) = dest_comb a in
if (fst (dest_const op) = "int_of_num") then (dest_numeral nat)
else fail() in
let (op',u) = (dest_comb b) in
try (if (fst (dest_const op') = "int_neg") then
minus_num (dest_pos_int u) else
dest_pos_int b) with
Failure _ -> failwith "dest_int ";;
let (mk_int:Num.num -> term) =
fun a ->
let sgn = Num.sign_num a in
let abv = Num.abs_num a in
let r = mk_comb(`int_of_num`,mk_numeral abv) in
try (if (sgn<0) then mk_comb (`int_neg`,r) else r) with
Failure _ -> failwith ("dest_int "^(string_of_num a));;
add_test("mk_int",
(mk_int (Int (-1443)) = `int_neg (int_of_num 1443)`) &&
(mk_int (Int 37) = `(int_of_num 37)`));;
(* ------------------------------------------------------------------ *)
let (split_ratio:Num.num -> Num.num*Num.num) =
function
(Ratio r) -> (Big_int (Ratio.numerator_ratio r)),
(Big_int (Ratio.denominator_ratio r))|
u -> (u,(Int 1));;
add_test("split_ratio",
let (a,b) = split_ratio ((Int 4)//(Int 20)) in
(a =/ (Int 1)) && (b =/ (Int 5)));;
(* ------------------------------------------------------------------ *)
(* break nonzero int r into a*(C**b) with a prime to C . *)
let (factor_C:int -> Num.num -> Num.num*Num.num) =
function c ->
let intC = (Int c) in
let rec divC (a,b) =
if ((Int 0) =/ mod_num a intC) then (divC (a//intC,b+/(Int 1)))
else (a,b) in
function r->
if ((Num.is_integer_num r)&& not((Num.sign_num r) = 0)) then
divC (r,(Int 0)) else failwith "factor_C";;
add_test("factor_C",
(factor_C 2 (Int (4096+32)) = (Int 129,Int 5)) &&
(factor_C 10 (Int (5000)) = (Int 5,Int 3)) &&
(cannot (factor_C 2) ((Int 50)//(Int 3))));;
(*--------------------------------------------------------------------*)
let (dest_float:term -> Num.num) =
fun f ->
let (a,b) = dest_binop `float` f in
(dest_int a)*/ ((Int 2) **/ (dest_int b));;
add_test("dest_float",
dest_float `float (int_of_num 3) (int_of_num 17)` = (Int 393216));;
add_test("dest_float2", (* must express as numeral first *)
cannot dest_float `float ((int_of_num 3)+:(int_of_num 1)) (int_of_num 17)`);;
(* ------------------------------------------------------------------ *)
(* creates float of the form `float a b` with a odd *)
let (mk_float:Num.num -> term) =
function r ->
let (a,b) = split_ratio r in
let (a',exp_a) = if (a=/(Int 0)) then ((Int 0),(Int 0)) else factor_C 2 a in
let (b',exp_b) = factor_C 2 b in
let c = a'//b' in
if (Num.is_integer_num c) then
mk_binop `float` (mk_int c) (mk_int (exp_a -/ exp_b))
else failwith "mk_float";;
add_test("mk_float",
mk_float (Int (4096+32)) = `float (int_of_num 129) (int_of_num 5)` &&
(mk_float (Int 0) = `float (int_of_num 0) (int_of_num 0)`));;
add_test("mk_float2", (* throws exception exactly when denom != 2^k *)
let rtest = fun t -> (t =/ dest_float (mk_float t)) in
rtest ((Int 3)//(Int 1024)) &&
(cannot rtest ((Int 1)//(Int 3))));;
add_test("mk_float dest_float", (* constructs canonical form of float *)
mk_float (dest_float `float (int_of_num 4) (int_of_num 3)`) = `float (int_of_num 1) (int_of_num 5)`);;
(* ------------------------------------------------------------------ *)
(* creates decimal of the form `DECIMAL a b` with a prime to 10 *)
let (mk_pos_decimal:Num.num -> term) =
let zero = `#0` in
function r ->
let _ = assert (r >=/ (Int 0)) in
let (a,b) = split_ratio r in
if (a=/(Int 0)) then zero else
let (a1,exp_a5) = factor_C 5 a in
let (a2,exp_a2) = factor_C 2 a1 in
let (b1,exp_b5) = factor_C 5 b in
let (b2,exp_b2) = factor_C 2 b1 in
let _ = assert(b2 =/ (Int 1)) in
let c = end_itlist Num.max_num [exp_b5-/exp_a5;exp_b2-/exp_a2;(Int 0)] in
let a' = a2*/((Int 2)**/ (c +/ exp_a2 -/ exp_b2))*/
((Int 5)**/(c +/ exp_a5 -/ exp_b5)) in
let b' = (Int 10) **/ c in
mk_binop `DECIMAL` (mk_numeral a') (mk_numeral b');;
add_test("mk_pos_decimal",
mk_pos_decimal (Int (5000)) = `#5000` &&
(mk_pos_decimal ((Int 30)//(Int 40)) = `#0.75`) &&
(mk_pos_decimal (Int 0) = `#0`) &&
(mk_pos_decimal ((Int 15)//(Int 25)) = `#0.6`) &&
(mk_pos_decimal ((Int 25)//(Int 4)) = `#6.25`) &&
(mk_pos_decimal ((Int 2)//(Int 25)) = `#0.08`));;
let (mk_decimal:Num.num->term) =
function r ->
let a = Num.sign_num r in
let b = mk_pos_decimal (Num.abs_num r) in
if (a < 0) then (mk_comb (`real_neg`, b)) else b;;
add_test("mk_decimal",
(mk_decimal (Int 3) = `#3`) &&
(mk_decimal (Int (-3)) = `real_neg (#3)`));;
(*--------------------------------------------------------------------*)
let (dest_decimal:term -> Num.num) =
fun f ->
let (a,b) = dest_binop `DECIMAL` f in
let a1 = dest_numeral a in
let b1 = dest_numeral b in
a1//b1;;
add_test("dest_decimal",
dest_decimal `#3.4` =/ ((Int 34)//(Int 10)));;
add_test("dest_decimal2",
cannot dest_decimal `real_neg (#3.4)`);;
(*--------------------------------------------------------------------*)
(* Properties of integer powers of 2. *)
(* ------------------------------------------------------------------ *)
let TWOPOW_POS = prove(`!n. (
twopow (
int_of_num n) = (&2) pow n)`,
(REWRITE_TAC[
twopow])
THEN GEN_TAC
THEN COND_CASES_TAC
THENL [AP_TERM_TAC;ALL_TAC]
THEN (REWRITE_TAC[
NABS_POS])
THEN (UNDISCH_EL_TAC 0)
THEN (TAUT_TAC (` ( A ) ==> (~ A ==> B)`))
THEN (MESON_TAC[]));;
let TWOPOW_NEG = prove(`!n. (
twopow (--(
int_of_num n)) = inv((&2) pow n))`,
GEN_TAC
THEN (REWRITE_TAC[
twopow])
THEN (COND_CASES_TAC THENL [ALL_TAC;REWRITE_TAC[
NABS_NEG]])
THEN (POP_ASSUM CHOOSE_TAC)
THEN (REWRITE_TAC[
NABS_NEG])
THEN (UNDISCH_EL_TAC 0)
THEN (REWRITE_TAC[
int_eq;
int_neg_th;
INT_NUM_REAL])
THEN (REWRITE_TAC[prove (`! u y.((--(real_of_num u) = (real_of_num y))=
((real_of_num u) +(real_of_num y) = (&0)))`,REAL_ARITH_TAC)])
THEN (REWRITE_TAC[REAL_OF_NUM_ADD;REAL_OF_NUM_EQ;
ADD_EQ_0])
THEN (DISCH_TAC)
THEN (ASM_REWRITE_TAC[
real_pow;
REAL_INV_1]));;
let INT_REP3 = prove(`!a .(?n.( (a =
int_of_num n) \/ (a = --: (
int_of_num (n+1)))))`,
(GEN_TAC)
THEN ((ASSUME_TAC (SPEC `a:int`
INT_REP2)))
THEN ((POP_ASSUM CHOOSE_TAC))
THEN ((DISJ_CASES_TAC (prove (`((a:int) = (
int_of_num 0)) \/ ~((a:int) =(
int_of_num 0))`, MESON_TAC[]))))
(* cases *)
THENL[ ((EXISTS_TAC `0`)) THEN ((ASM_REWRITE_TAC[]));ALL_TAC]
THEN ((UNDISCH_EL_TAC 0))
THEN ((POP_ASSUM DISJ_CASES_TAC))
THENL [DISCH_TAC THEN ((ASM MESON_TAC)[]);ALL_TAC]
THEN (DISCH_TAC)
THEN ((EXISTS_TAC `
PRE n`))
THEN ((DISJ2_TAC))
THEN ((ASM_REWRITE_TAC[
INT_EQ_NEG2]))
(*** Changed by JRH, 2006/03/28 to avoid PRE_ELIM_TAC ***)
THEN (FIRST_X_ASSUM(MP_TAC o check(is_neg o concl)))
THEN (ASM_REWRITE_TAC[
INT_NEG_EQ_0;
INT_OF_NUM_EQ])
THEN (ARITH_TAC));;
let REAL_EQ_INV = prove(`!x y. ((x:real = y) <=> (inv(x) = inv (y)))`,
((REPEAT GEN_TAC))
THEN (EQ_TAC)
THENL [((DISCH_TAC THEN (ASM_REWRITE_TAC[])));
(* branch 2*) ((DISCH_TAC))
THEN ((ONCE_REWRITE_TAC [(GSYM
REAL_INV_INV)]))
THEN ((ASM_REWRITE_TAC[]))]);;
(* ------------------------------------------------------------------ *)
(* Arithmetic operations on float *)
(* ------------------------------------------------------------------ *)
let pow = real_pow;;
let POW_2 = prove(
`!x. x pow 2 = x * x`,
GEN_TAC THEN REWRITE_TAC[num_CONV `2`] THEN
REWRITE_TAC[pow;
POW_1]);;
(* subtraction of integers *)
(* assumes a term of the form int_of_num a +: (--: (int_of_num b)) *)
let INT_SUB_CONV t =
let a,b = dest_binop `int_add` t in
let (_,a) = dest_comb a in
let (_,b) = dest_comb b in
let (_,b) = dest_comb b in
let a = dest_numeral a in
let b = dest_numeral b in
let thm = if (b <=/ a) then
INT_ADD_NEGv2
else INT_ADD_NEG in
(ARITH_SIMP_CONV[thm]) t;; (* (SIMP_CONV[thm;ARITH]) t;; *)
(* ------------------------------------------------------------------ *)
(* Simplifies an arithmetic expression in floats *)
(* A workhorse *)
(* ------------------------------------------------------------------ *)
let FLOAT_CONV =
(ARITH_SIMP_CONV[FLOAT_LT;FLOAT_LE;FLOAT_MUL;FLOAT_SUB;FLOAT_ABS;FLOAT_POW;
FLOAT_ADD_NN;FLOAT_ADD_NNv2;FLOAT_ADD_PP;FLOAT_ADD_PPv2;
FLOAT_ADD_NP;FLOAT_ADD_PN;FLOAT_NEG;
INT_NEG_NEG;INT_SUB;
INT_ABS_NUM;INT_ABS_NEG_NUM;
INT_MUL_LNEG;INT_MUL_RNEG;INT_NEG_MUL2;INT_OF_NUM_MUL;
INT_OF_NUM_ADD;GSYM INT_NEG_ADD;INT_ADD_NEG_NUM;
INT_OF_NUM_POW;INT_POW_ODD_NEG1;INT_POW_EVEN_NEG1;
INT_ADD_NEG;INT_ADD_NEGv2 (* ; ARITH *)
]) ;;
add_test("FLOAT_CONV1",
let f z =
let (x,y) = dest_eq z in
let (u,v) = dest_thm (FLOAT_CONV x) in
(u=[]) && (z = v) in
f `float (int_of_num 3) (int_of_num 0) = float (int_of_num 3) (int_of_num 0)` &&
f `float (int_of_num 3) (int_of_num 3) = float (int_of_num 3) (int_of_num 3)` &&
f `float (int_of_num 3) (int_of_num 0) +. (float (int_of_num 4) (int_of_num 0)) = (float (int_of_num 7) (int_of_num 0))` &&
f `float (int_of_num 1 + (int_of_num 3)) (int_of_num 4) = float (int_of_num 4) (int_of_num 4)` &&
f `float (int_of_num 3 - (int_of_num 7)) (int_of_num 0) = float (--:(int_of_num 4)) (int_of_num 0)` &&
f `float (int_of_num 3) (int_of_num 4) *. (float (--: (int_of_num 2)) (int_of_num 3)) = float (--: (int_of_num 6))
(int_of_num 7)` &&
f `real_neg (float (--: (int_of_num 3)) (int_of_num 0)) = float (int_of_num 3) (int_of_num 0)`
);;
(* ------------------------------------------------------------------ *)
(* Operations on interval_eps. Preliminary stuff to deal with *)
(* chains of inequalities. *)
(* ------------------------------------------------------------------ *)
let REAL_ADD_LE_SUBST_RHS = prove(
`!a b c P. ((a <=. ((P b)) /\ (!x. (P x) = x + (P (&. 0))) /\ (b <=. c)) ==> (a <=. (P c)))`,
(((REPEAT GEN_TAC)))
THEN (((REPEAT (TAUT_TAC `(b ==> a==> c) ==> (a /\ b ==> c)`))))
THEN (((REPEAT DISCH_TAC)))
THEN ((((H_RULER(ONCE_REWRITE_RULE))[HYP_INT 1] (HYP_INT 0))))
THEN ((((ASM ONCE_REWRITE_TAC)[])))
THEN ((((ASM MESON_TAC)[
REAL_LE_RADD;
REAL_LE_TRANS]))));;
let REAL_ADD_LE_SUBST_LHS = prove(
`!a b c P. (((P(a) <=. b /\ (!x. (P x) = x + (P (&. 0))) /\ (c <=. a)))
==> ((P c) <=. b))`,
(REP_GEN_TAC)
THEN (DISCH_ALL_TAC)
THEN (((H_RULER(ONCE_REWRITE_RULE)) [HYP_INT 1] (HYP_INT 0)))
THEN (((ASM ONCE_REWRITE_TAC)[]))
THEN (((ASM MESON_TAC)[
REAL_LE_RADD;
REAL_LE_TRANS])));;
(*
let rec SPECL =
function [] -> I |
(a::b) -> fun thm ->(SPECL b (SPEC a thm));;
*)
(*
input:
rel: b <=. c
thm: a <=. P(b).
output: a <=. P(c).
condition: REAL_ARITH must be able to prove !x. P(x) = x+. P(&.0).
condition: the term `a` must appear exactly once the lhs of the thm.
*)
let IWRITE_REAL_LE_RHS rel thm =
let bvar = genvar `:real` in
let (bt,_) = dest_binop `real_le` (concl rel) in
let sub = SUBS_CONV[ASSUME (mk_eq(bt,bvar))] in
let rule = (fun th -> EQ_MP (sub (concl th)) th) in
let (subrel,subthm) = (rule rel,rule thm) in
let (a,p) = dest_binop `real_le` (concl subthm) in
let (_,c) = dest_binop `real_le` (concl subrel) in
let pfn = mk_abs (bvar,p) in
let imp_th = BETA_RULE (SPECL [a;bvar;c;pfn] REAL_ADD_LE_SUBST_RHS) in
let ppart = REAL_ARITH
(fst(dest_conj(snd(dest_conj(fst(dest_imp(concl imp_th))))))) in
let prethm = MATCH_MP imp_th (CONJ subthm (CONJ ppart subrel)) in
let prethm2 = SPEC bt (GEN bvar (DISCH
(find (fun x -> try(bvar = rhs x) with Failure _ -> false) (hyp prethm)) prethm)) in
MATCH_MP prethm2 (REFL bt);;
(*
input:
rel: c <=. a
thm: P a <=. b
output: P c <=. b
condition: REAL_ARITH must be able to prove !x. P(x) = x+. P(&.0).
condition: the term `a` must appear exactly once the lhs of the thm.
*)
let IWRITE_REAL_LE_LHS rel thm =
let avar = genvar `:real` in
let (_,at) = dest_binop `real_le` (concl rel) in
let sub = SUBS_CONV[ASSUME (mk_eq(at,avar))] in
let rule = (fun th -> EQ_MP (sub (concl th)) th) in
let (subrel,subthm) = (rule rel,rule thm) in
let (p,b) = dest_binop `real_le` (concl subthm) in
let (c,_) = dest_binop `real_le` (concl subrel) in
let pfn = mk_abs (avar,p) in
let imp_th = BETA_RULE (SPECL [avar;b;c;pfn] REAL_ADD_LE_SUBST_LHS) in
let ppart = REAL_ARITH
(fst(dest_conj(snd(dest_conj(fst(dest_imp(concl imp_th))))))) in
let prethm = MATCH_MP imp_th (CONJ subthm (CONJ ppart subrel)) in
let prethm2 = SPEC at (GEN avar (DISCH
(find (fun x -> try(avar = rhs x) with Failure _ -> false) (hyp prethm)) prethm)) in
MATCH_MP prethm2 (REFL at);;
(* ------------------------------------------------------------------ *)
(* INTERVAL ADD, NEG, SUBTRACT *)
(* ------------------------------------------------------------------ *)
let INTERVAL_ADD = prove(
`!x f ex y g ey.
interval_eps x f ex /\
interval_eps y g ey ==>
interval_eps (x +. y) (f +. g) (ex +. ey)`,
EVERY[
REPEAT GEN_TAC;
TAUT_TAC `(A==>B==>C)==>(A/\ B ==> C)`;
REWRITE_TAC[
interval_eps];
REWRITE_TAC[prove(`(x+.y) -. (f+.g) = (x-.f) +. (y-.g)`,REAL_ARITH_TAC)];
ABBREV_TAC `a = x-.f`;
ABBREV_TAC `b = y-.g`;
ASSUME_TAC (SPEC `b:real` (SPEC `a:real`
ABS_TRIANGLE));
UNDISCH_EL_TAC 0;
ABBREV_TAC `a':real = abs a`;
ABBREV_TAC `b':real = abs b`;
REPEAT DISCH_TAC;
(H_VAL2(IWRITE_REAL_LE_RHS)) (HYP_INT 0) (HYP_INT 2);
(H_VAL2(IWRITE_REAL_LE_RHS)) (HYP_INT 2) (HYP_INT 0);
ASM_REWRITE_TAC[]]);;
(* ------------------------------------------------------------------ *)
(* INTERVAL MULTIPLICATION *)
(* ------------------------------------------------------------------ *)
(* renamed from REAL_LE_ABS_RMUL *)
let REAL_LE_ABS_MUL = prove(
`!x y z w. (( x <=. y) /\ (abs z <=. w)) ==> (x*.w <=. y*.w) `,
(DISCH_ALL_TAC)
THEN ((ASSUME_TAC (REAL_ARITH `abs z <=. w ==> (&.0) <=. w`)))
THEN (((ASM MESON_TAC)[
REAL_LE_RMUL_IMP])));;
let ABS_MUL = REAL_ABS_MUL;;
let INTERVAL_ABS = REAL_ARITH
`!(x:real) z d. (x - d) <= z /\ z <= (x + d) <=> abs(z - x) <= d`;;
let INTERVAL_MUL = prove(
`!x f ex y g ey. (
interval_eps x f ex) /\ (
interval_eps y g ey) ==>
(
interval_eps (x *. y) (f *. g) (abs(f)*.ey +. ex*. abs(g) +. ex*.ey))`,
(REP_GEN_TAC)
THEN ((REWRITE_TAC[
interval_eps]))
THEN ((REWRITE_TAC[REAL_ARITH `(x*. y -. f*. g) = (f *.(y -. g) +. (x -. f)*.g +. (x-.f)*.(y-. g))`]))
THEN (DISCH_ALL_TAC)
THEN ((ASSUME_TAC (SPECL [`f*.(y-g)`;`(x-f)*g +. (x-f)*.(y-g)`]
ABS_TRIANGLE)))
THEN ((ASSUME_TAC (SPECL [`(x-f)*.g`;`(x-f)*.(y-g)`]
ABS_TRIANGLE)))
THEN (((H_VAL2(IWRITE_REAL_LE_RHS)) (HYP_INT 0) (HYP_INT 1)))
THEN ((H_REWRITE_RULE [THM
ABS_MUL] (HYP_INT 0)))
THEN ((H_MATCH_MP (THM (SPECL [`g:real`; `abs (x -. f)`; `ex:real`]
REAL_PROP_LE_RABS)) (HYP_INT 4)))
THEN (((H_VAL2(IWRITE_REAL_LE_RHS)) (HYP_INT 0) (HYP_INT 1)))
THEN ((H_MATCH_MP (THM (SPECL [`f:real`; `abs (y -. g)`; `ey:real`]
REAL_PROP_LE_LABS)) (HYP_INT 7)))
THEN (((H_VAL2 (IWRITE_REAL_LE_RHS)) (HYP_INT 0) (HYP_INT 1)))
THEN ((H_MATCH_MP (THM (SPECL [`x-.f`; `abs (y -. g)`; `ey:real`]
REAL_PROP_LE_LABS)) (HYP_INT 9)))
THEN (((H_VAL2(IWRITE_REAL_LE_RHS)) (HYP_INT 0) (HYP_INT 1)))
THEN ((ASSUME_TAC (SPECL [`abs(x-.f)`;`ex:real`;`y-.g`;`ey:real`]
REAL_LE_ABS_MUL)))
THEN ((H_CONJ (HYP_INT 11) (HYP_INT 12)))
THEN ((H_MATCH_MP (HYP_INT 1) (HYP_INT 0)))
THEN (((H_VAL2(IWRITE_REAL_LE_RHS)) (HYP_INT 0) (HYP_INT 3)))
THEN ((POP_ASSUM ACCEPT_TAC)));;
(* ------------------------------------------------------------------ *)
(* INTERVAL BASIC OPERATIONS *)
(* ------------------------------------------------------------------ *)
let INTERVAL_CENTER = prove(
`!x f ex g. (
interval_eps x f ex) ==> (
interval_eps x g (abs(f-g)+.ex))`,
((REWRITE_TAC[
interval_eps]))
THEN (DISCH_ALL_TAC)
THEN ((ASSUME_TAC (REAL_ARITH `abs(x -. g) <=. abs(f-.g) +. abs(x -. f)`)))
THEN ((H_VAL2 IWRITE_REAL_LE_RHS (HYP_INT 1) (HYP_INT 0)))
THEN ((ASM_REWRITE_TAC[])));;
(* renamed from REAL_ABS_POS *)
(* ------------------------------------------------------------------ *)
(* INTERVAL DIVIDE *)
(* ------------------------------------------------------------------ *)
let INTERVAL_DIV = prove(`!x f ex y g ey h ez.
(((
interval_eps x f ex) /\ (
interval_eps y g ey) /\ (ey <. (abs g)) /\
((ex +. (abs (f -. (h*.g))) +. (abs h)*. ey) <=. (ez*.((abs g) -. ey))))
==> (
interval_eps (x / y) h ez))`,
let lemma1 = prove( `&.0 < u /\ real_abs z <=. e*. u ==> (&.0) <=. e`,
EVERY[
DISCH_ALL_TAC;
ASSUME_TAC (SPEC `z:real` REAL_MK_NN_ABS);
H_MATCH_MP (THM REAL_LE_TRANS) (H_RULE2 CONJ (HYP_INT 0) (HYP_INT 2));
H_MATCH_MP (THM REAL_PROP_NN_RCANCEL) (H_RULE2 CONJ (HYP_INT 2) (HYP_INT 0));
ASM_REWRITE_TAC[]
]) in
EVERY[
DISCH_ALL_TAC;
SUBGOAL_MP_TAC `~(y= (&.0))`
THENL[
EVERY[
UNDISCH_LIST[1;2];
REWRITE_TAC[interval_eps];
REAL_ARITH_TAC
];
EVERY[
REWRITE_TAC[interval_eps];
DISCH_TAC THEN (H I (HYP_INT 0)) THEN (UNDISCH_EL_TAC 0);
DISCH_THEN (fun th -> (MP_TAC(MATCH_MP REAL_MK_POS_ABS_' th)));
MATCH_MP_TAC REAL_MUL_RTIMES_LE;
REWRITE_TAC[GSYM ABS_MUL;REAL_SUB_RDISTRIB;real_div;GSYM REAL_MUL_ASSOC];
ASM_SIMP_TAC[REAL_MUL_LINV;REAL_MUL_RID];
H (REWRITE_RULE[interval_eps]) (HYP_INT 1);
H (REWRITE_RULE[interval_eps]) (HYP_INT 3);
H (MATCH_MP INTERVAL_ABS_MIN) (HYP_INT 4);
POPL_TAC[3;4;5];
H_VAL2 (IWRITE_REAL_LE_LHS) (HYP_INT 2) (HYP_INT 4);
H (REWRITE_RULE[ REAL_ADD_ASSOC]) (HYP_INT 0);
H_VAL2 (IWRITE_REAL_LE_LHS) (THM (SPEC `f-. h*g` (SPEC `x-.f` ABS_TRIANGLE))) (HYP_INT 0);
H (ONCE_REWRITE_RULE[REAL_ABS_SUB]) (HYP_INT 4);
H (MATCH_MP (SPEC `h:real` REAL_PROP_LE_LABS)) (HYP_INT 0);
H (REWRITE_RULE[GSYM ABS_MUL]) (HYP_INT 0);
H_VAL2 (IWRITE_REAL_LE_LHS) (HYP_INT 0) (HYP_INT 3);
H_VAL2 (IWRITE_REAL_LE_LHS) (THM (SPEC `h*.(g-.y)` (SPEC`(x-.f)+(f-. h*g)` ABS_TRIANGLE))) (HYP_INT 0);
POPL_TAC[1;2;3;4;5;6;7;9;10;12];
H (ONCE_REWRITE_RULE[REAL_ARITH `((x-.f) +. (f -. h*. g)) +. h*.(g-. y) = x -. h*. y `]) (HYP_INT 0);
ABBREV_TAC `z = x -. h*.y`;
H (ONCE_REWRITE_RULE[GSYM REAL_SUB_LT]) (HYP_INT 4);
ABBREV_TAC `u = abs(g) -. ey`;
POPL_TAC[0;2;4;6];
H (MATCH_MP lemma1 ) (H_RULE2 CONJ (HYP_INT 0) (HYP_INT 1));
H (MATCH_MP REAL_PROP_LE_LMUL) (H_RULE2 CONJ (HYP_INT 0) (HYP_INT 3));
H (MATCH_MP REAL_LE_TRANS) (H_RULE2 CONJ (HYP_INT 3) (HYP_INT 0));
ASM_REWRITE_TAC[]
];
]]);;
(* ------------------------------------------------------------------ *)
(* INTERVAL ABS VALUE *)
(* ------------------------------------------------------------------ *)
(* 7 minutes *)
(* ------------------------------------------------------------------ *)
(* INTERVAL ATN VALUE *)
(* ------------------------------------------------------------------ *)
(* }}} *)
(* }}} *)
(* ------------------------------------------------------------------ *)
(* INTERVAL SQRT *)
(* This requires some preliminaries. Extend sqrt by 0 on negatives *)
(* ------------------------------------------------------------------ *)
(*2m*)
(* }}} *)
let LET_TAC = REWRITE_TAC[LET_DEF;LET_END_DEF];;
let REAL_SSQRT_NEG = prove(`!x. (x <. (&.0)) ==> (
ssqrt x = (&.0))`,
EVERY[
DISCH_ALL_TAC;
REWRITE_TAC[
ssqrt];
COND_CASES_TAC
THENL[
ACCEPT_TAC (REFL `&.0`);
ASM_MESON_TAC[]
]
]);;
(* 5 min*)
(* 12 min, mostly spent loading *index-shell* *)
(*17 minutes*)
(* 6 minutes *)
(* 15 minutes *)
(* 5 minutes *)
(* 13 minutes *)
(* 7min *)
(*20min*)
(* an alternate proof appears in RCS *)
let INTERVAL_SSQRT = prove(`!x f ex u ey ez v. (
interval_eps x f ex) /\ (
interval_eps (u*.u) f ey) /\
(ex +.ey <=. ez*.(v+.u)) /\ (v*.v <=. f-.ex) /\ (&.0 <. u) /\ (&.0 <=. v) ==>
(
interval_eps (
ssqrt x) u ez)`,
EVERY[
DISCH_ALL_TAC;
H (MATCH_MP
REAL_LE_TRANS) (H_RULE2 CONJ (THM (SPEC `v:real` REAL_MK_NN_SQUARE)) (HYP_INT 3));
H (MATCH_MP (
INTERVAL_MIN)) (HYP_INT 1);
H (MATCH_MP
REAL_LE_TRANS) (H_RULE2 CONJ (HYP_INT 1) (HYP_INT 0));
H (MATCH_MP
INTERVAL_EPS_POS) (HYP_INT 3);
H (MATCH_MP
INTERVAL_EPS_POS) (HYP_INT 5);
H (MATCH_MP REAL_PROP_NN_ADD2) (H_RULE2 CONJ (HYP_INT 1) (HYP_INT 0));
H (MATCH_MP REAL_PROP_POS_LADD) (H_RULE2 CONJ (HYP_INT 11) (HYP_INT 10));
H (MATCH_MP REAL_PROP_POS_LADD) (H_RULE2 CONJ (THM (SPEC `x:real`
REAL_MK_NN_SSQRT)) (HYP_INT 11));
H (MATCH_MP REAL_PROP_POS_INV) (HYP_INT 0);
ASSUME_TAC (REAL_ARITH `(
ssqrt x -. u) = (
ssqrt x -. u)*.(&.1)`);
H (MATCH_MP REAL_MK_NZ_POS) (HYP_INT 2);
H (MATCH_MP
REAL_MUL_RINV) (HYP_INT 0);
H_REWRITE_RULE[(H_RULE GSYM) (HYP_INT 0)] (HYP_INT 2);
POPL_TAC[1;2;3];
H (REWRITE_RULE[REAL_MUL_ASSOC]) (HYP_INT 0);
H (REWRITE_RULE[ONCE_REWRITE_RULE[REAL_MUL_SYM]
REAL_DIFFSQ]) (HYP_INT 0);
POPL_TAC[1;2];
H_SIMP_RULE[HYP_INT 7;THM
REAL_SSQRT_SQUARE] (HYP_INT 0);
ASSUME_TAC (REAL_ARITH `abs(x -. u*.u) <=. abs(x -. f) + abs(f-. u*.u)`);
H (REWRITE_RULE[
interval_eps]) (HYP_INT 12);
H (ONCE_REWRITE_RULE[
interval_eps]) (HYP_INT 14);
H (ONCE_REWRITE_RULE[
REAL_ABS_SUB]) (HYP_INT 0);
POPL_TAC[1;5;15;16];
H (MATCH_MP
REAL_LE_ADD2) (H_RULE2 CONJ (HYP_INT 1) (HYP_INT 0));
H (MATCH_MP
REAL_LE_TRANS) (H_RULE2 CONJ (HYP_INT 3) (HYP_INT 0));
POPL_TAC[1;2;3;4];
H (AP_TERM `
real_abs `) (HYP_INT 1);
H (REWRITE_RULE[
ABS_MUL]) (HYP_INT 0);
H (MATCH_MP
REAL_LT_IMP_LE) (HYP_INT 4);
H (REWRITE_RULE[GSYM
REAL_ABS_REFL]) (HYP_INT 0);
H_REWRITE_RULE [HYP_INT 0] (HYP_INT 2);
H (MATCH_MP
REAL_LE_RMUL) (H_RULE2 CONJ (HYP_INT 5) (HYP_INT 2));
H_REWRITE_RULE [H_RULE GSYM (HYP_INT 1)] (HYP_INT 0);
POPL_TAC[1;2;3;5;6;7;8];
H (MATCH_MP
REAL_LE_TRANS) (H_RULE2 CONJ (HYP_INT 12) (HYP_INT 9));
H (MATCH_MP
REAL_SSQRT_MONO) (HYP_INT 0);
H (MATCH_MP REAL_SSQRT_SQUARE') (HYP_INT 16);
H_REWRITE_RULE [HYP_INT 0] (HYP_INT 1);
H (ONCE_REWRITE_RULE[GSYM (SPECL[`v:real`;`
ssqrt x`;`u:real`]
REAL_LE_RADD)]) (HYP_INT 0);
H (MATCH_MP
REAL_LE_INV2) (H_RULE2 CONJ (HYP_INT 9) (HYP_INT 0));
POPL_TAC[1;2;3;4;5;7;8;9;12;13];
H (MATCH_MP
REAL_LE_LMUL) (H_RULE2 CONJ (HYP_INT 3) (HYP_INT 0));
H (MATCH_MP
REAL_LE_TRANS) (H_RULE2 CONJ (HYP_INT 2) (HYP_INT 0));
H (MATCH_MP REAL_PROP_POS_INV) (HYP_INT 4);
H (MATCH_MP
REAL_LT_IMP_LE) (HYP_INT 0);
H (MATCH_MP
REAL_LE_RMUL) (H_RULE2 CONJ (HYP_INT 11) (HYP_INT 0));
H (REWRITE_RULE[GSYM REAL_MUL_ASSOC]) (HYP_INT 0);
H (MATCH_MP REAL_MK_NZ_POS) (HYP_INT 8);
H (MATCH_MP
REAL_MUL_RINV) (HYP_INT 0);
H_REWRITE_RULE[HYP_INT 0; THM
REAL_MUL_RID] (HYP_INT 2);
H (MATCH_MP
REAL_LE_TRANS) (H_RULE2 CONJ (HYP_INT 7) (HYP_INT 0));
ASM_REWRITE_TAC[
interval_eps]
]);;
test();;
(* conversion for interval_eps *)
(* ------------------------------------------------------------------ *)
(* Take a term x of type real. Convert to a thm of the form *)
(* interval_eps x f eps *)
(* *)
(* ------------------------------------------------------------------ *)
let add_test,test = new_test_suite();;
(* ------------------------------------------------------------------ *)
(* num_exponent
Take the absolute value of input.
Write it as a*2^k, where 1 <= a < 2, return k.
Except:
num_exponent (Int 0) is -1.
*)
let (num_exponent:Num.num -> Num.num) =
fun a ->
let afloat = float_of_num (abs_num a) in
Int ((snd (frexp afloat)) - 1);;
(*test*)let f (u,v) = ((num_exponent u) =(Int v)) in
add_test("num_exponenwt",
forall f
[Int 1,0; Int 65,6; Int (-65),6;
Int 0,-1; (Int 3)//(Int 4),-1]);;
(* ------------------------------------------------------------------ *)
let dest_unary op tm =
try let xop,r = dest_comb tm in
if xop = op then r else fail()
with Failure _ -> failwith "dest_unary";;
(* ------------------------------------------------------------------ *)
(* finds a nearby (outward-rounded) Int with only prec_b significant bits *)
let (round_outward: int -> Num.num -> Num.num) =
fun prec_b a ->
let b = abs_num a in
let sign = if (a =/ b) then I else minus_num in
let throw_bits = Num.max_num (Int 0) ((num_exponent b)-/ (Int prec_b)) in
let twoexp = power_num (Int 2) throw_bits in
(sign (ceiling_num (b // twoexp)))*/twoexp;;
let (round_inward: int-> Num.num -> Num.num) =
fun prec_b a ->
let b = abs_num a in
let sign = if (a=/b) then I else minus_num in
let throw_bits = Num.max_num (Int 0) ((num_exponent b)-/ (Int prec_b)) in
let twoexp = power_num (Int 2) throw_bits in
(sign (floor_num (b // twoexp)))*/twoexp;;
let round_rat bprec n =
let b = abs_num n in
let sign = if (b =/ n) then I else minus_num in
let powt = ((Int 2) **/ (Int bprec)) in
sign ((round_outward bprec (Num.ceiling_num (b */ powt)))//powt);;
let round_inward_rat bprec n =
let b = abs_num n in
let sign = if (b =/ n) then I else minus_num in
let powt = ((Int 2) **/ (Int bprec)) in
sign ((round_inward bprec (Num.floor_num (b */ powt)))//powt);;
let (round_outward_float: int -> float -> Num.num) =
fun bprec f ->
if (f=0.0) then (Int 0) else
begin
let b = abs_float f in
let sign = if (f >= 0.0) then I else minus_num in
let (x,n) = frexp b in
let u = int_of_float( ceil (ldexp x bprec)) in
sign ((Int u)*/ ((Int 2) **/ (Int (n - bprec))))
end;;
let (round_inward_float: int -> float -> Num.num) =
fun bprec f ->
if (f=0.0) then (Int 0) else
begin
(* avoid overflow on 30 bit integers *)
let bprec = if (bprec > 25) then 25 else bprec in
let b = abs_float f in
let sign = if (f >= 0.0) then I else minus_num in
let (x,n) = frexp b in
let u = int_of_float( floor (ldexp x bprec)) in
sign ((Int u)*/ ((Int 2) **/ (Int (n - bprec))))
end;;
(* ------------------------------------------------------------------ *)
(* This doesn't belong here. A general term substitution function *)
let SUBST_TERM sublist tm =
rhs (concl ((SPECL (map fst sublist)) (GENL (map snd sublist)
(REFL tm))));;
add_test("SUBST_TERM",
SUBST_TERM [(`#1`,`a:real`);(`#2`,`b:real`)] (`a +. b +. c`) =
`#1 + #2 + c`);;
(* ------------------------------------------------------------------ *)
(* take a term of the form `interval_eps x f ex` and clean up the f and ex *)
let INTERVAL_CLEAN_CONV:conv =
fun interv ->
let (ixf,ex) = dest_comb interv in
let (ix,f) = dest_comb ixf in
let fthm = FLOAT_CONV f in
let exthm = FLOAT_CONV ex in
let ixfthm = AP_TERM ix fthm in
MK_COMB (ixfthm, exthm);;
(*test*) add_test("INTERVAL_CLEAN_CONV",
let testval = INTERVAL_CLEAN_CONV `interval_eps ((&.1) +. (&.1))
(float (int_of_num 3) (int_of_num 4) +. (float (int_of_num 2) (--: (int_of_num 3))))
(float (int_of_num 1) (int_of_num 2) *. (float (int_of_num 3) (--: (int_of_num 2))))` in
let hypval = hyp testval in
let concval = concl testval in
(length hypval = 0) &&
concval =
`interval_eps (&1 + &1) (float (int_of_num 3) (int_of_num 4) + float (int_of_num 2) (--: (int_of_num 3)))
(float (int_of_num 1) (int_of_num 2) * float (int_of_num 3) (--: (int_of_num 2))) =
interval_eps (&1 + &1) (float (int_of_num 386) (--: (int_of_num 3))) (float (int_of_num 3) (int_of_num 0))`
);;
(* ------------------------------------------------------------------ *)
(* GENERAL lemmas *)
(* ------------------------------------------------------------------ *)
(* verifies statement of the form `float a b = float a' b'` *)
let REAL_INV_POS = REAL_LT_INV;;
let FLOAT_NN = Prove_by_refinement.prove_by_refinement(
`!a b. ((&.0) <=. (float a b)) <=> (int_of_num 0 <=: a)`,
[
REWRITE_TAC[float;INT_OF_NUM_DEST];
REP_GEN_TAC;
REWRITE_TAC[int_of_num_th;int_le];
MESON_TAC[REAL_PROP_NN_RCANCEL;TWOPOW_MK_POS;REAL_PROP_NN_POS;REAL_PROP_NN_MUL2];
]);;
let INT_NN = INT_POS;;
let RAT_LEMMA1_SUB = prove(`~(y1 = &0) /\ ~(y2 = &0) ==>
((x1 / y1) - (x2 / y2) = (x1 * y2 - x2 * y1) * inv(y1) * inv(y2))`,
let ABS_NUM_P = prove_by_refinement(
`!m n. (m <= n) ==> (abs (&. n -. (&. m)) = &.((m-|n) + (n-|m)))`,
[
REPEAT STRIP_TAC;
ASM_SIMP_TAC[(ARITH_RULE `(m <= n ==> (m - n = 0) )/\ ( 0 + x = x)`)];
ASM_SIMP_TAC[GSYM
REAL_OF_NUM_SUB;
REAL_ABS_REFL;];
FIRST_X_ASSUM MP_TAC;
REWRITE_TAC[GSYM REAL_OF_NUM_LE];
REAL_ARITH_TAC;
])
;;
let ABS_NUM = prove_by_refinement (
`!m n. abs (&. n -. (&. m)) = &.((m-|n) + (n-|m))`,
[
REPEAT GEN_TAC ;
DISJ_CASES_TAC (SPECL [`m:num`;`n:num`]
LTE_CASES) ; (* THENL[ *)
(* first case *)
MATCH_MP_TAC
ABS_NUM_P;
FIRST_X_ASSUM MP_TAC;
ARITH_TAC;
(* second case *)
ONCE_REWRITE_TAC[REAL_ARITH `abs(x - y) = abs(y - x)`];
ONCE_REWRITE_TAC[ARITH_RULE `(a:num) + b = b + a`];
MATCH_MP_TAC
ABS_NUM_P;
ASM_REWRITE_TAC[];
]);;
let ABS_TO_INTERVAL = prove(
`!c u k. (abs (c - u) <=. k) ==> (!f g ex ey.((
interval_eps u f ex) /\ (
interval_eps k g ey) ==> (
interval_eps c f (g+.ey+.ex))))`,
EVERY[
REWRITE_TAC[
interval_eps];
DISCH_ALL_TAC;
REPEAT GEN_TAC;
DISCH_ALL_TAC;
ONCE_REWRITE_TAC [REAL_ARITH `c -. f = (c-. u) + (u-. f)`];
ONCE_REWRITE_TAC [REAL_ADD_ASSOC];
ASSUME_TAC (SPECL [`c-.u`;`u-.f`]
ABS_TRIANGLE);
IMP_RES_THEN ASSUME_TAC (REAL_ARITH `
real_abs (k-.g) <=. ey ==> (k <=. (g +. ey))`);
MATCH_MP_TAC (REAL_ARITH `(?a b.((x <=. (a+.b)) /\ (a <=. u) /\ (b <=. v))) ==> (x <=. (u +. v))`);
EXISTS_TAC `abs (c-.u)`;
EXISTS_TAC `abs(u-.f)`;
ASM_REWRITE_TAC[];
ASM_MESON_TAC[
REAL_LE_TRANS];
]);;
(* end of general lemmas *)
(* ------------------------------------------------------------------ *)
(* ------------------------------------------------------------------ *)
(* Cache of computed constants (abs (r - u) <= k)
or interval r u eps *)
(* ------------------------------------------------------------------ *)
let cache_entry_of_ineq bprec ineq =
try(
let (abst,_) = dest_binop `real_le` (concl ineq) in
let (_,cmu) = dest_comb abst in
let (r,_) = dest_binop `real_sub` cmu in
(r,bprec,ineq))
with Failure _ ->
(try(
let (r,_,_) = dest_interval (concl ineq) in (r,bprec,ineq))
with Failure _ -> (print_term (concl ineq); failwith "calculated_constants format : abs(r - u) <= k"));;
let get_real_constant cache bprec tm =
(fun (_,_,r) -> r) (find (fun (t,p,th) -> (t = tm) & (p>= bprec)) cache);;
let remove_entry t = filter (fun x -> not(x = t));;
(* ------------------------------------------------------------------ *)
(* take |- interval_eps r u e to interval_eps r' u e, where th_r gives r <=> r' *)
let interval_rule th_r th_int =
let (iru,e) = dest_comb (concl th_int) in
let (ir,u) = dest_comb iru in
let (i,r) = dest_comb ir in
let ir_t = AP_TERM i th_r in
let iru_t = AP_THM ir_t u in
let irue_t = AP_THM iru_t e in
let a = try EQ_MP irue_t th_int
with Failure m -> (print_thm irue_t; print_thm th_int; failwith m) in
a;;
(* term of the form '&.n'. Assume error checking done already. *)
let INTERVAL_OF_NUM:conv =
fun tm ->
let n = snd (dest_comb tm) in
let th_r = (ARITH_REWRITE_CONV[] n) in
let th_int = SPEC (rhs (concl th_r)) INTERVAL_NUM in
interval_rule (SYM (AP_TERM `real_of_num` th_r)) th_int;;
add_test("INTERVAL_OF_NUM",
dest_thm (INTERVAL_OF_NUM `&.3`) = ([],
`interval_eps (&3) (float (int_of_num 3) (int_of_num 0)) (float (int_of_num 0) (int_of_num 0))`));;
(* ------------------------------------------------------------------ *)
(* conversion for float inequalities *)
(* ------------------------------------------------------------------ *)
let FLOAT_LESS_CONV = FLOAT_CONV THENC ARITH_SIMP_CONV[FLOAT_POS;
INT_POS';INT_POS_NEG;FLOAT_NN;INT_NN;INT_NN_NEG;];;
let FLOAT_INEQ_CONV t =
let th =FLOAT_LESS_CONV t in
let (_,rhs) = dest_eq (concl th) in
let _ = (rhs = `T`) or raise Insufficient_precision in
EQ_MP (SYM th) TRUTH;;
add_test("FLOAT_INEQ_CONV",
let f c x =
dest_thm (c x) = ([],x) in
let t1 =
`(float (int_of_num 3) (int_of_num 0)) +. (float (int_of_num 4) (int_of_num 0)) <. (float (int_of_num 8) (int_of_num 1))` in
((f FLOAT_INEQ_CONV t1)));;
let INTERVAL_TO_LESS_CONV =
let rthm = ASSUME `!f g ex ey. (&.0 <. (g -. (ey +. ex +. f)))` in
fun thm1 thm2 ->
let (a,f,ex) = dest_interval (concl thm1) in
let (b,g,ey) = dest_interval (concl thm2) in
let rspec = concl (SPECL [f;g;ex;ey] rthm) in
let rspec_th = FLOAT_INEQ_CONV rspec in
let fthm = CONJ thm1 (CONJ thm2 rspec_th) in
MATCH_MP INTERVAL_TO_LESS fthm;;
add_test("INTERVAL_TO_LESS_CONV",
let thm1 = ASSUME
`interval_eps (#0.1) (float (int_of_num 1) (--: (int_of_num 1))) (float (int_of_num 1) (--: (int_of_num 2)))` in
let thm2 = ASSUME `interval_eps (#7) (float (int_of_num 4) (int_of_num 1)) (float (int_of_num 1) (int_of_num 0))` in
let thm3 = INTERVAL_TO_LESS_CONV thm1 thm2 in
concl thm3 = `#0.1 <. (#7)`);;
add_test("INTERVAL_TO_LESS_CONV2",
let (h,c) = dest_thm (INTERVAL_TO_LESS_CONV
(INTERVAL_OF_NUM `&.3`) (INTERVAL_OF_NUM `&.8`)) in
(h=[]) && (c = `&.3 <. (&.8)`));;
(* ------------------------------------------------------------------ *)
(* conversion for DEC <= posfloat and posfloat <= DEC *)
let lemma1 = prove(
`!n m p. ((&.p/(&.m)) <= (&.n)) <=> ((&.p/(&.m)) <= (&.n)/(&.1))`,
let lemma2 = prove(
`!n m p. ((&.p) <= ((&.n)/(&.m))) <=> ((&.p/(&.1)) <= (&.n)/(&.m))`,
let REAL_LT = REAL_OF_NUM_LT;;
let REAL_LE = REAL_OF_NUM_LE;;
let lemma3 = prove(`!a b c d. (
((0<b) /\ (0<d) /\ (a*d <=| c*b))
==> (&.a/(&.b) <=. ((&.c)/(&.d))))`,
let DEC_FLOAT = EQT_ELIM o
ARITH_SIMP_CONV[DECIMAL;float;TWOPOW_POS;TWOPOW_NEG;GSYM real_div;
REAL_OF_NUM_POW;INT_NUM_REAL;REAL_OF_NUM_MUL;
lemma1;lemma2;lemma3];;
add_test("DEC_FLOAT",
let f c x =
dest_thm (c x) = ([],x) in
((f DEC_FLOAT `#10.0 <= (float (int_of_num 3) (int_of_num 2))`) &&
(f DEC_FLOAT `#10 <= (float (int_of_num 3) (int_of_num 2))`) &&
(f DEC_FLOAT `#0.1 <= (float (int_of_num 1) (--: (int_of_num 2)))`) &&
(f DEC_FLOAT `float (int_of_num 3) (int_of_num 2) <= (#13.0)`) &&
(f DEC_FLOAT `float (int_of_num 3) (int_of_num 2) <= (#13)`) &&
(f DEC_FLOAT `float (int_of_num 1) (--: (int_of_num 2)) <= (#0.3)`)));;
(* Conversion for powers *)
let pow_conv = PURE_ONCE_REWRITE_CONV[CONJUNCT1 real_pow;REAL_POW_1;pow_parity];;
(* conversion for negation *)
let neg_conv =
let th = REAL_ARITH `--x = &0 - x` in
PURE_ONCE_REWRITE_CONV[th];;
(* conversion for sums *)
let dest_sum =
let sum = `sum:(num->bool)->(num->real)->real` in
let rg = `(..)` in
fun tm ->
let (x,f) = dest_binop sum tm in
let (i,j) = dest_binop rg x in
(i,j,f);;
let mk_sum =
let sum = `sum:(num->bool)->(num->real)->real` in
let rg = `(..)` in
fun (i,j,f) ->
let x = mk_binop rg i j in
mk_binop sum x f;;
(*
mk_sum (dest_sum `sum (3..4) f`);;
*)
let sum_conv =
fun tm ->
let (i,j,f) = dest_sum tm in
let i',j' = dest_numeral i,dest_numeral j in
if (i'=j') then (ONCE_REWRITE_CONV[SUM_SING_NUMSEG]) tm
else if (i' >/ j') then
let th = ARITH_RULE(mk_binop `(<):num->num->bool` j i) in
let th2 = MATCH_MP SUM_TRIV_NUMSEG th in
(PURE_ONCE_REWRITE_CONV[th2]) tm
else
let j_pred = mk_numeral (j'-/ Int 1) in
let j_new = mk_comb (`SUC`, j_pred) in
let th = (ISPECL [i;j_pred] (CONJUNCT2 SUM_CLAUSES_NUMSEG)) in
let rr = ARITH_RULE (mk_eq (j_new,j)) in
let th' = REWRITE_RULE[rr;ARITH_RULE (mk_binop `(<=):num->num->bool` i j)] th in
PURE_ONCE_REWRITE_CONV[th'] tm;;
(* ------------------------------------------------------------------ *)
(* converts a DECIMAL TO A THEOREM *)
let ABS_BOUNDS = REAL_ABS_BOUNDS;; (* new *)
let INTERVAL_OF_DECIMAL bprec dec =
let a_num = dest_decimal dec in
let f_num = round_rat bprec a_num in
let ex_num = round_rat bprec (Num.abs_num (f_num -/ a_num)) in
let _ = assert (ex_num <=/ f_num) in
let f = mk_float f_num in
let ex= mk_float ex_num in
let fplus_ex = FLOAT_CONV (mk_binop `real_add` f ex) in
let fminus_ex= FLOAT_CONV (mk_binop `real_sub` f ex) in
let fplus_term = rhs (concl fplus_ex) in
let fminus_term = rhs (concl fminus_ex) in
let th1 = DEC_FLOAT (mk_binop `real_le` fminus_term dec) in
let th2 = DEC_FLOAT (mk_binop `real_le` dec fplus_term) in
let intv = mk_interval dec f ex in
EQT_ELIM (SIMP_CONV[INTERVAL_MINMAX;fplus_ex;fminus_ex;th1;th2] intv);;
add_test("INTERVAL_OF_DECIMAL",
let (h,c) = dest_thm (INTERVAL_OF_DECIMAL 4 `#36.1`) in
let (x,f,ex) = dest_interval c in
(h=[]) && (x = `#36.1`));;
add_test("INTERVAL_OF_DECIMAL2",
can (fun() -> INTERVAL_TO_LESS_CONV (INTERVAL_OF_DECIMAL 4 `#33.33`)
(INTERVAL_OF_DECIMAL 4 `#36.1`)) ());;
(* }}} *)
let INTERVAL_FLOAT_CONV flt =
let (a,b) = dest_binop `float` flt in
(ISPECL [a;b] INTERVAL_FLOAT);;
(*--------------------------------------------------------------------*)
(* functions to check format. *)
(* There are various implicit rules: *)
(* NUMERAL is followed by bits and no other kind of num, etc. *)
(* FLOAT a b, both a and b are int_of_num NUMERAL or --:int_of_num NUMERAL, etc. *)
(*--------------------------------------------------------------------*)
(* converts exceptions to false *)
let falsify_ex f x = try (f x) with Failure _ -> false;;
let is_bits_format =
let zero = `_0` in
let rec format x =
if (x = zero) then true
else let (h,t) = dest_comb x in
(((h = `BIT1`) or (h = `BIT0`)) && (format t))
in falsify_ex format;;
let is_numeral_format =
let fn x =
let (h,t) = dest_comb x in
((h = `NUMERAL`) && (is_bits_format t)) in
falsify_ex fn;;
let is_decimal_format =
let fn x =
let (t1,t2) = dest_binop `DECIMAL` x in
((is_numeral_format t1) && (is_numeral_format t2)) in
falsify_ex fn;;
let is_pos_int_format =
let fn x =
let (h,t) = dest_comb x in
(h = `int_of_num`) && (is_numeral_format t) in
falsify_ex fn;;
let is_neg_int_format =
let fn x =
let (h,t) = dest_comb x in
(h = `real_neg`) && (is_pos_int_format t) in
falsify_ex fn;;
let is_int_format x =
(is_neg_int_format x) or (is_pos_int_format x);;
let is_float_format =
let fn x =
let (t1,t2) = dest_binop `float` x in
(is_int_format t1) && (is_int_format t2) in
falsify_ex fn;;
let is_interval_format =
let fn x =
let (a,b,c) = dest_interval x in
(is_float_format b) && (is_float_format c) in
falsify_ex fn;;
let is_neg_real =
let fn x =
let (h,t) = dest_comb x in
(h= `real_neg `) in
falsify_ex fn;;
let is_real_num_format =
let fn x =
let (h,t) = dest_comb x in
(h=`real_of_num`) && (is_numeral_format t) in
falsify_ex fn;;
let is_comb_of t u =
let fn t u =
t = (fst (dest_comb u)) in
try (fn t u) with Failure _ -> false;;
(* ------------------------------------------------------------------ *)
(* Heron's formula for the square root of A
Return a value x that is always at most the actual square root
and such that abs (x - A/x ) < epsilon *)
let rec heron_sqrt depth A x eps =
let half = (Int 1)//(Int 2) in
if (depth <= 0)
then raise (Failure "heron_sqrt:internal error:sqrt recursion depth exceeded")
else
if (Num.abs_num (x -/ (A//x) ) </ eps) & (x*/ x >=/ A) then (A//x) else
let x' = half */ (x +/ (A//x)) in
heron_sqrt (depth -1) A x' eps;;
(* compute ez parameter for division *)
let division_ez bprec (f,ex,g,ey) =
let f_num = dest_float f in
let ex_num = dest_float ex in
let g_num = dest_float g in
let ey_num = dest_float ey in
let _ = (ey_num </ abs_num g_num) or raise Insufficient_precision in
let h_num = round_rat bprec (f_num//g_num) in
let h = mk_float h_num in
let ez_rat = (ex_num +/ abs_num (f_num -/ (h_num*/ g_num))
+/ (abs_num h_num */ ey_num))//((abs_num g_num) -/ (ey_num)) in
let ez_num = round_rat bprec (ez_rat) in
let _ = assert((ez_num >=/ (Int 0))) in
let ez = mk_float ez_num
in (h,ez);;
let pureconv (s,t) = (s,PURE_ONCE_REWRITE_CONV[t]);;
(* ------------------------------------------------------------------ *)
(*
bprec gives the bits of precision.
*)
let rec (INTERVAL_OF_TERM:(string*conv)list -> (term *int*thm)list ->int -> term -> (term*int*thm) list * thm) =
fun convl cache bprec tm ->
let mk c th = (cache_entry_of_ineq bprec th :: c, th) in
(* treat user conversions *)
let interval_of_conv cache bprec conv tm =
let th_r = conv tm in
let (lhs,rhs) = dest_eq (concl th_r) in
let _ = (not (aconv lhs rhs)) or (print_term lhs; failwith "interval_of_conv: no change" )in
let (cache,th_rhs) = INTERVAL_OF_TERM convl cache bprec rhs in
let th_lhs = interval_rule (SYM th_r) th_rhs in
mk cache th_lhs in
let interval_of_binop op opname match_thm =
begin
let (a,b) = dest_binop op tm in
let (cache,a_int) = INTERVAL_OF_TERM convl cache bprec a in
let (cache,b_int) = INTERVAL_OF_TERM convl cache bprec b in
try(
let c_int = MATCH_MP match_thm (CONJ a_int b_int) in
let th = EQ_MP (INTERVAL_CLEAN_CONV (concl c_int)) c_int in
mk cache th)
with Failure _ -> failwith ("INTERVAL_OF_TERM: "^opname)
end in
(* treat cached values first *)
if (can (get_real_constant cache bprec) tm) then
begin
try(
let int_thm = get_real_constant cache bprec tm in
if (can dest_interval (concl int_thm)) then (cache,int_thm)
else (
let absthm = int_thm in
let (abst,k) = dest_binop `real_le` (concl absthm) in
let (absh,cmu) = dest_comb abst in
let (c,u) = dest_binop `real_sub` cmu in
let (cache,intk) = INTERVAL_OF_TERM convl cache bprec k in
let (cache,intu) = INTERVAL_OF_TERM convl cache bprec u in
let thm1 = MATCH_MP ABS_TO_INTERVAL absthm in
let thm2 = MATCH_MP thm1 (CONJ intu intk) in
let (_,f,ex)= dest_interval (concl thm2) in
let fthm = FLOAT_CONV f in
let exthm = FLOAT_CONV ex in
let thm3 = REWRITE_RULE[fthm;exthm] thm2 in
(cache_entry_of_ineq bprec thm3 :: (remove_entry (tm,bprec,int_thm) cache), thm3)
))
with Failure _ -> failwith "INTERVAL_OF_TERM : CONSTANT"
end
else if (is_real_num_format tm) then
let th = INTERVAL_OF_NUM tm in (cache,th)
else if (is_decimal_format tm) then
let th = (INTERVAL_OF_DECIMAL bprec tm)
in mk cache th
(* treat abs value *)
else if (is_comb_of `real_abs` tm) then
begin
let (_,b) = dest_comb tm in
let (cache,i1) = (INTERVAL_OF_TERM convl cache bprec b) in
try(
let b_int = MATCH_MP INTERVAL_ABSV i1 in
let th = EQ_MP (INTERVAL_CLEAN_CONV (concl b_int)) b_int in
mk cache th)
with Failure _ -> failwith "INTERVAL_OF_TERM : ABS"
end
(* treat twopow *)
else if (is_comb_of `twopow` tm) then
begin
try(
let (_,b) = dest_comb tm in
let th = SPEC b INTERVAL_OF_TWOPOW
in mk cache th
)
with Failure _ -> failwith "INTERVAL_OF_TERM : TWOPOW"
end
(* treat addition *)
else if (can (dest_binop `real_add`) tm) then
interval_of_binop `real_add` "ADD" INTERVAL_ADD
(* treat subtraction *)
else if (can (dest_binop `real_sub`) tm) then
interval_of_binop `real_sub` "SUB" INTERVAL_SUB
(* treat multiplication *)
else if (can (dest_binop `real_mul`) tm) then
interval_of_binop `real_mul` "MUL" INTERVAL_MUL
(* treat division : instantiate INTERVAL_DIV *)
else if (can (dest_binop `( / )`) tm) then
begin
let (a,b) = dest_binop `( / )` tm in
let (cache,a_int) = INTERVAL_OF_TERM convl cache bprec a in
let (cache,b_int) = INTERVAL_OF_TERM convl cache bprec b in
try(
let (_,f,ex) = dest_interval (concl a_int) in
let (_,g,ey) = dest_interval (concl b_int) in
let (h,ez) = division_ez bprec (f,ex,g,ey) in
let hyp1 = a_int in
let hyp2 = b_int in
let hyp3 = try (FLOAT_INEQ_CONV (mk_binop `real_lt` ey (mk_comb (`real_abs`,g))))
with Failure _ -> raise Insufficient_precision in
let thm = SPECL [a;f;ex;b;g;ey;h;ez] INTERVAL_DIV in
let conj2 x = snd (dest_conj x) in
let hyp4t = (conj2 (conj2 (conj2 (fst(dest_imp (concl thm)))))) in
let hyp4 = FLOAT_INEQ_CONV hyp4t in
let hyp_all = end_itlist CONJ [hyp1;hyp2;hyp3;hyp4] in
let th = MATCH_MP thm hyp_all in
mk cache th)
with Failure _ -> failwith "INTERVAL_OF_TERM :DIV"
end
(* treat pow *)
else if (can (dest_binary "real_pow") tm) then
interval_of_conv cache bprec pow_conv tm
(* treat negative terms *)
else if (is_neg_real tm) then
interval_of_conv cache bprec neg_conv tm
(* treat beta *)
else if can (fun t-> let (f,x) = dest_comb t in dest_abs f ) tm then
interval_of_conv cache bprec BETA_CONV tm
(* treat sum *)
else if can dest_sum tm then
interval_of_conv cache bprec sum_conv tm
(* treat float *)
else if can (dest_binop `float`) tm then
(cache,INTERVAL_FLOAT_CONV tm)
(* treat ssqrt : instantiate INTERVAL_SSQRT *)
else if (can (dest_unary `ssqrt`) tm) then
begin
try(
let x = dest_unary `ssqrt` tm in
let (cache,x_int) = INTERVAL_OF_TERM convl cache bprec x in
let (_,f,ex) = dest_interval (concl x_int) in
let f_num = dest_float f in
let ex_num = dest_float ex in
let fd_num = f_num -/ ex_num in
let fe_f = Num.float_of_num fd_num in
let apprx_sqrt = Pervasives.sqrt fe_f in
(* put in heron's formula *)
let v_num1 = round_inward_float 25 (apprx_sqrt) in
let v_num = round_inward_rat bprec
(heron_sqrt 10 fd_num v_num1 ((Int 2) **/ (Int (-bprec-4)))) in
let u_num1 = round_inward_float 25
(Pervasives.sqrt (float_of_num f_num)) in
let u_num = round_inward_rat bprec
(heron_sqrt 10 f_num u_num1 ((Int 2) **/ (Int (-bprec-4)))) in
let ey_num = round_rat bprec (abs_num (f_num -/ (u_num */ u_num))) in
let ez_num = round_rat bprec ((ex_num +/ ey_num)//(u_num +/ v_num)) in
let (v,u) = (mk_float v_num,mk_float u_num) in
let (ey,ez) = (mk_float ey_num,mk_float ez_num) in
let thm = SPECL [x;f;ex;u;ey;ez;v] INTERVAL_SSQRT in
let conjhyp = fst (dest_imp (concl thm)) in
let [hyp6;hyp5;hyp4;hyp3;hyp2;hyp1] =
let rec break_conj c acc =
if (not(is_conj c)) then (c::acc) else
let (u,v) = dest_conj c in break_conj v (u::acc) in
(break_conj conjhyp []) in
INT_POS_NEG] THEN ARITH_TAC in
let thm5 = prove( hyp5,float_tac) in
let thm6 = prove( hyp6,float_tac) in
let ant = end_itlist CONJ[x_int;thm2;thm3;thm4;thm5;thm6] in
let th = MATCH_MP thm ant
in mk cache th
)
with Failure _ -> failwith "INTERVAL_OF_TERM : SSQRT"
end
else if (can (dest_unary `sqrt`) tm) then
begin
try(
let x = dest_unary `sqrt` tm in
let stm = mk_comb (`ssqrt`, x) in
let (cache,ssqrt_thm) = INTERVAL_OF_TERM convl cache bprec stm in
let (cache,int1) = INTERVAL_OF_TERM convl cache bprec`real_of_num 0` in
let (cache,int2) =INTERVAL_OF_TERM convl cache bprec x in
let ant = CONJ (INTERVAL_TO_LESS_CONV int1 int2) ssqrt_thm in
let th = MATCH_MP ssqrt_sqrt ant
in mk cache th)
with Failure _ -> failwith "INTERVAL_OF_TERM : SQRT"
end
(* treat atn *)
else if can (dest_unary `atn`) tm then
begin
let half_co = ("halfatn4_co",ARITH_SIMP_CONV[Taylor_atn.halfatn4_co]) in
let half4 = ("halfatn4",PURE_REWRITE_CONV[Taylor_atn.halfatn4;o_THM]) in
let halfatnconv = pureconv("halfatn",Taylor_atn.halfatn) in
let aconvl = (halfatnconv::half4::half_co::convl) in
let n = mk_numeral (Int (1 + (bprec - 5) / 6)) in
let x = dest_unary `atn` tm in
let sum_tm = instantiate ([],[(n,`n:num`);(x,`u:real`)],[]) `&16 * sum (0..n) (halfatn4_co u)` in
let (cache,hyp_1) = INTERVAL_OF_TERM (aconvl) cache bprec sum_tm in
let (_,_,eps2) = dest_interval (concl hyp_1) in
let eps_tm = instantiate([],[(n,`n:num`);(eps2,`eps2:real`)],[]) `float (int_of_num 1) ( -- int_of_num (6 * n + 5)) + eps2` in
let eps_thm = FLOAT_CONV eps_tm in
let eps = snd(dest_eq (concl eps_thm)) in
let hyp_2 = FLOAT_INEQ_CONV (mk_binop `(<=):real->real->bool` eps_tm eps) in (cache, MATCH_MP taylor_atn (CONJ hyp_1 hyp_2) )
end
(* treat acs *)
else if can (dest_unary `acs`) tm then
begin
let x = dest_unary `acs` tm in
let (_,int_m1) = INTERVAL_OF_TERM convl cache bprec`-- real_of_num 1` in
let (_,int_p1) = INTERVAL_OF_TERM convl cache bprec`real_of_num 1` in
let (cache,int_x) =INTERVAL_OF_TERM convl cache bprec x in
let ant1 = INTERVAL_TO_LESS_CONV int_m1 int_x in
let ant2 = INTERVAL_TO_LESS_CONV int_x int_p1 in
let th = MATCH_MP ACS_ATN (CONJ ant1 ant2) in
interval_of_conv cache bprec (PURE_ONCE_REWRITE_CONV[th]) tm
end
(* treat pi *)
else if (tm = `pi`) then
begin
interval_of_conv cache bprec (PURE_ONCE_REWRITE_CONV[pi_atn]) tm
end
(* user supplied conversions *)
else
begin
let (c,b) = strip_comb tm in
let _ = is_const c or failwith "INTERVAL_OF_TERM: case not installed" in
let (s,_) = dest_const c in
let conv = try (assoc s convl)
with Failure _ -> failwith ("INTERVAL_OF_TERM: function not found "^s) in
interval_of_conv cache bprec conv tm
end;;
let real_ineq convl cache bprec tm =
let (t1,t2) = try (dest_binop `real_lt` tm)
with Failure _ -> failwith "real_ineq: inequality of the form `x < y` expected" in
let (cache,int1) = INTERVAL_OF_TERM convl cache bprec t1 in
let (cache,int2) = INTERVAL_OF_TERM convl cache bprec t2 in
(cache,INTERVAL_TO_LESS_CONV int1 int2);;
let rec rec_real_ineq convl cache bprec bprec_max tm =
try (bprec,real_ineq convl cache bprec tm) with
Insufficient_precision ->
let bprec = (16 * bprec) / 10 in
let _ = (bprec < bprec_max) or failwith ("insufficient precision "^ (string_of_int bprec_max)) in
let _ = Format.print_string ("increasing precision to "^(string_of_int bprec)^" bits");
Format.print_newline() in
rec_real_ineq convl cache bprec bprec_max tm;;
(* Give it a conjunction of strict inequalities *)
let REAL_INEQUALITY_CALCULATOR_PREC (bprec_init,bprec_max) convl tm =
let tml = striplist dest_conj tm in
let (b,c,th) = List.fold_left (fun (b,c,thl) tm1 ->
let (bprec,(cache,th1)) = rec_real_ineq convl c b bprec_max tm1
in (bprec,cache, th1 ::thl)) (bprec_init,[], []) (tml) in
(b, EQ_MP (SYM(REWRITE_CONV th tm)) TRUTH);;
let REAL_INEQUALITY_CALCULATOR convl tm =
REAL_INEQUALITY_CALCULATOR_PREC (10,70) convl tm;;
(*
let REAL_INEQUALITY_CALCULATOR convl tm =
let tml = striplist dest_conj tm in
let bprec_max = 70 in
let (b,c,th) = List.fold_left (fun (b,c,thl) tm1 ->
let (bprec,(cache,th1)) = rec_real_ineq convl c b bprec_max tm1
in (bprec,cache, th1 ::thl)) (10,[], []) (tml) in
(b, EQ_MP (SYM(REWRITE_CONV th tm)) TRUTH);;
*)
(*
let tmint = map (rec_real_ineq [] 10) tml in
List.fold_left CONJ (hd tmint) (tl tmint);;
*)
end;;