(* ========================================================================== *)
(* FLYSPECK - BOOK FORMALIZATION *)
(* *)
(* Chapter: Trigonometry *)
(* Author: Jason Rute, Thomas C. Hales *)
(* Date: 2010-02-09 *)
(* ========================================================================== *)
module type Trigonometry1_type = sig
(* ADD *)
end;;
(*
Formal Proofs Blueprint Chapter on Trigonometry
some proofs copied from John Harrison.
*)
flyspeck_needs "general/sphere.hl";;
module Trigonometry1 (* : Trigonometry1_type *) = struct
let atn2 = Sphere.atn2;;
let arclength = Sphere.arclength;;
let ups_x = Sphere.ups_x;;
prioritize_real();;
(* This is close to CIRCLE_SINCOS *)
let atn2_spec_t = `!x y. ?r. ((-- pi < atn2(x, y)) /\ (atn2(x,y) <= pi) /\
(x = r* (cos(atn2(x,y)))) /\ (y = r* (sin (atn2( x, y)))) /\
(&0 <= r))`;;
let acs_atn2_t = `!y. (-- &1 <= y /\ y <= &1) ==> (acs y = pi/(&2) - atn2(sqrt(&1 - y pow 2),y))`;;
let arcVarc_t = `!u v w:real^3. ~(u=v) /\ ~(u=w) ==> arcV u v w = arclength (dist( u, v)) (dist( u, w)) (dist( v, w))`;;
let law_of_cosines_t = `!a b c. (&0 < a) /\ (&0 < b) /\ (&0 <= c) /\ (c <= a + b) /\ (a <= b + c) /\ (b <= c + a) ==>
((c pow 2) = (a pow 2) + (b pow 2) - &2 * a * b * (cos(arclength a b c)))`;;
let law_of_sines_t = `!a b c. (&0 < a) /\ (&0 < b) /\ (&0 <= c) /\ (c <= a + b) /\ (a <= b + c) /\ (b <= c + a) ==>
(&2 * a * b * sin (arclength a b c) = sqrt(ups_x (a pow 2) (b pow 2) (c pow 2)))`;;
let cross_mag_t = `!u v. norm (u cross v) = (norm u) * (norm v) * sin(arcV (vec 0) u v)`;;
let cross_skew_t = `!u v. (u cross v) = -- (v cross u)`;;
let cross_triple_t = `!u v w. (u cross v) dot w = (v cross w) dot u`;;
(* law of cosines *)
let spherical_loc_t = `!v0 va vb vc:real^3.
~(collinear {v0,va,vc}) /\ ~(collinear {v0,vb,vc}) ==>
(
let gamma = dihV v0 vc va vb in
let a = arcV v0 vb vc in
let b = arcV v0 va vc in
let c = arcV v0 va vb in
(cos(gamma) = (cos(c) - cos(a)*cos(b))/(sin(a)*sin(b))))`;;
let spherical_loc2_t = `!v0 va vb vc:real^3.
~(collinear {v0,va,vc}) /\ ~(collinear {v0,vb,vc}) ==>
(
let alpha = dihV v0 va vb vc in
let beta = dihV v0 vb va vc in
let gamma = dihV v0 vc vb va in
let c = arcV v0 va vb in
(cos(c) = (cos(gamma) + cos(alpha)*cos(beta))/(sin(alpha)*sin(beta))))`;;
let dih_formula_t = `!v0 v1 v2 v3:real^3.
~(collinear {v0,v1,v2}) /\ ~(collinear {v0,v1,v3}) ==>
(
let (x1,x2,x3,x4,x5,x6) = xlist v0 v1 v2 v3 in
(dihV v0 v1 v2 v3 = dih_x x1 x2 x3 x4 x5 x6)
)`;;
let dih_x_acs_t = `!x1 x2 x3 x4 x5 x6.
(&0 < ups_x x1 x2 x6) /\ (&0 < ups_x x1 x3 x5) /\ (&0 <= delta_x x1 x2 x3 x4 x5 x6) /\ (&0 <= x1) ==>
dih_x x1 x2 x3 x4 x5 x6 = acs ((delta_x4 x1 x2 x3 x4 x5 x6)/
((sqrt (ups_x x1 x2 x6)) * (sqrt (ups_x x1 x3 x5))))`;;
let beta_cone_t = `!v0 v1 v2 v3:real^3.
~(collinear {v0,v1,v2}) /\ ~(collinear {v0,v1,v3}) /\
(dihV v0 v3 v1 v2 = pi/(&2)) ==>
(dihV v0 v1 v2 v3 = beta (arcV v0 v1 v3) (arcV v0 v1 v2))`;;
let euler_triangle_t = `!v0 v1 v2 v3:real^3.
let p = euler_p v0 v1 v2 v3 in
let (x1,x2,x3,x4,x5,x6) = xlist v0 v1 v2 v3 in
let alpha1 = dihV v0 v1 v2 v3 in
let alpha2 = dihV v0 v2 v3 v1 in
let alpha3 = dihV v0 v3 v1 v2 in
let d = delta_x x1 x2 x3 x4 x5 x6 in
((&0 < d) ==>
(alpha1 + alpha2 + alpha3 - pi = pi - &2 * atn2(sqrt(d), (&2 * p))))`;;
let polar_cycle_rotate_t = `!V psi u f.
(!x y. f (x,y) = (x*cos psi + y*sin psi, -- x*sin psi + y*cos psi)) /\
FINITE V /\ V u ==>
(polar_cycle (IMAGE f V) (f u) = f (polar_cycle V u))`;;
let thetaij_t = `!theta1 theta2 k12 k21 theta12 theta21.
(&0 <= theta1) /\ (theta1 < &2 * pi) /\ (&0 <= theta2) /\ (theta2 < &2 * pi) /\
(theta12 = theta2 - theta1 + &2 * pi * (&k12)) /\
(theta21 = theta1 - theta2 + &2 * pi * (&k21)) /\
(&0 <= theta12) /\ (theta12 < &2 * pi) /\
(&0 <= theta21) /\ (theta21 < &2 * pi) ==>
((theta12+theta21) = (if (theta1=theta2) then (&0) else (&2 * pi)))`;;
(* JMR: Changed `polar_angle (FST u) (SND u)` to `Arg(complex u)` *)
let thetapq_wind_t = `!W n thetapq kpq.
(!x y. (W (x,y) ==> (~(x= &0) /\ ~(y = &0)))) /\
(W HAS_SIZE n) /\
(!u v. W u /\ W v ==>
((thetapq u v = Arg(complex v) - Arg(complex u) + &2 * pi * kpq u v) /\ (&0 <= thetapq u v) /\ (thetapq u v < &2 * pi)))
==>
((!u i j. (W u /\ (0 <= i) /\ (i <= j) /\ (j < n)) ==>
thetapq u (ITER i (polar_cycle W) u) + thetapq (ITER i (polar_cycle W) u) (ITER j (polar_cycle W) u) = thetapq u (ITER j (polar_cycle W) u)) /\
((!u v. (W u /\ W v) ==> (Arg(complex u) = Arg(complex v))) \/
(!u. (W u) ==> (sum(0 .. n-1) (\i. thetapq (ITER i (polar_cycle W) u) (ITER (SUC i) (polar_cycle W) u)) = &2 * pi)) ))`;;
let zenith_t = `!u v w:real^3. ~(u=v) /\ ~(w = v) ==>
(?u' r phi e3.
(phi = arcV v u w) /\ (r = dist( u, v)) /\ ((dist( w, v)) % e3 = (w-v)) /\
( u' dot e3 = &0) /\ (u = v + u' + (r*cos(phi)) % e3))`;;
(* spherical_coord_t deprecated, replaced with Harrison's SPHERICAL_COORDINATES theorem,
which is worded slightly differently.
*)
let polar_coord_zenith_t = `!u v w u' n.
~(collinear {u,v,w}) /\ (aff {u,v,w} u') /\ ~(u' = v) /\
(n = (w - v) cross (u - v)) ==>
(arcV v (v + n) u' = pi/ (&2))`;;
let azim_pair_t = `!v w w1 w2.
let a1 = azim v w w1 w2 in
let a2 = azim v w w2 w1 in
(cyclic_set {w1,w2} v w) ==>
(a1 + a2 = (if (a1 = &0) then (&0) else (&2 * pi)))`;;
let azim_cycle_sum_t = `!W v w n.
(cyclic_set W v w) /\
(W HAS_SIZE n) ==>
(!p i j. (W p /\ (0 <= i) /\ (i <= j) /\ (j < n)) ==>
((!q. W q ==> (azim v w p q = &0) ) \/
(sum(0 .. n-1) (\i. azim v w (ITER i (azim_cycle W v w) p) (ITER (SUC i) (azim_cycle W v w) p)) = &2 * pi )))`;;
let dih_azim_t = `!v w v1 v2.
~(collinear {v,w,v1}) /\ ~(collinear {v,w,v2}) ==>
(cos(azim v w v1 v2) = cos(dihV v w v1 v2))`;;
let sph_triangle_ineq_t = `!p u v w:real^3.
~(collinear {p,u,w}) /\ ~(collinear {p,u,v}) /\ ~(collinear {p,v,w}) ==>
(arcV p u w <= arcV p u v + arcV p v w)`;;
let sph_triangle_ineq_sum_t = `!p:real^3 u r.
(!i. (i < r) ==> ~(collinear {p,u i, u (SUC i)})) /\
~(collinear {p,u 0, u r}) ==>
(arcV p (u 0) (u r) <= sum(0 .. r-1) (\i. arcV p (u i) (u (SUC i))))`;;
let azim_t = `!v w w1 w2 e1 e2 e3.
?psi h1 h2 r1 r2.
~collinear {v, w, w1} /\
~collinear {v, w, w2} /\
orthonormal e1 e2 e3 /\
(dist( w, v) % e3 = w - v)
==> &0 <= azim v w w1 w2 /\
azim v w w1 w2 < &2 * pi /\
&0 < r1 /\
&0 < r2 /\
w1 =
(r1 * cos psi) % e1 + (r1 * sin psi) % e2 + h1 % (w - v) /\
(w2 =
(r2 * cos (psi + azim v w w1 w2)) % e1 +
(r2 * sin (psi + azim v w w1 w2)) % e2 +
h2 % (w - v))`;;
(* signature for trig theorems.
This is the list of theorems that should be provided by
an implementation of the blueprint on trig.
The signature can be extended, but care needs to made
in removing anything, because it may create incompatibilities
with other pieces of code. *)
(* In every case, there is a term giving the precise theorem to
be proved *)
module type Trigsig = sig
val atn2_spec : thm (* atn2_spec_t *)
val acs_atn2: thm (* acs_atn2_t *)
val arcVarc : thm (* arcVarc_t *)
val law_of_cosines : thm (* law_of_cosines_t *)
val law_of_sines : thm (* law_of_sines_t *)
val cross_mag : thm (* cross_mag_t *)
val cross_skew : thm (* cross_skew_t *)
val cross_triple : thm (* cross_triple_t *)
val spherical_loc : thm (* spherical_loc_t *)
val spherical_loc2 : thm (* spherical_loc2_t *)
val dih_formula : thm (* dih_formula_t *)
val dih_x_acs : thm (* dih_x_acs_t *)
val beta_cone : thm (* beta_cone_t *)
val euler_triangle : thm (* euler_triangle_t *)
(* val polar_coords : thm (* polar_coords_t *) *)
val polar_cycle_rotate : thm (* polar_cycle_rotate_t *)
val thetaij : thm (* thetaij_t *)
val thetapq_wind : thm (* thetapq_wind_t *)
val zenith : thm (* zenith_t *)
(* val spherical_coord : thm (* spherical_coord_t *) *)
val polar_coord_zenith : thm (* polar_coord_zenith_t *)
val azim_pair : thm (* azim_pair_t *)
val azim_cycle_sum : thm (* azim_cycle_sum_t *)
val dih_azim : thm (* dih_azim_t *)
val sph_triangle_ineq : thm (* sph_triangle_ineq_t *)
val sph_triangle_ineq_sum : thm (* sph_triangle_ineq_sum_t *)
val azim : thm (* azim_t *)
end;;
(* Here is a single axiom that permits a quick implementation of the
module with the given signature.
The axiom can be used so that the proofs in different chapters can
proceed independently. *)
(*
let trig_term_list = new_definition (mk_eq (`trig_term:bool`, (list_mk_conj
[
atn2_spec_t ;
acs_atn2_t ;
arcVarc_t ;
law_of_cosines_t ;
law_of_sines_t ;
cross_mag_t ;
cross_skew_t ;
cross_triple_t ;
spherical_loc_t ;
spherical_loc2_t ;
dih_formula_t ;
dih_x_acs_t ;
beta_cone_t ;
euler_triangle_t ;
polar_cycle_rotate_t ;
thetaij_t ;
thetapq_wind_t ;
zenith_t ;
polar_coord_zenith_t ;
azim_pair_t ;
azim_cycle_sum_t ;
dih_azim_t ;
sph_triangle_ineq_t ;
sph_triangle_ineq_sum_t ;
azim_t;
])));;
*)
(* ---------------------------------------------------------------------- *)
(* These are theorems proved in HOL Light, but not in the *)
(* Multivariate files. Unless noted, all proofs by John Harrison. *)
(* ---------------------------------------------------------------------- *)
(* REAL_LE_POW_2 is in HOL-Light Examples/transc.ml. *)
(* Also called REAL_LE_SQUARE_POW in Examples/analysis.ml. *)
(* REAL_DIV_MUL2 is in HOL-Light Examples/analysis.ml. *)
(* Proof in now trivial *)
let REAL_DIV_MUL2 = REAL_FIELD
`!x z. ~(x = &0) /\ ~(z = &0) ==> !y. y / z = (x * y) / (x * z)`;;
(* ---------------------------------------------------------------------- *)
(* Useful theorems about real numbers. *)
(* ---------------------------------------------------------------------- *)
(* ---------------------------------------------------------------------- *)
(* Basic trig results not included in Examples/transc.ml *)
(* ---------------------------------------------------------------------- *)
(* Next two proofs similar to TAN_PERIODIC_NPI in *)
(* Examples/transc.ml by John Harrison *)
(* They are no longer needed, but may be useful later. *)
let SIN_NEGPOS_PI = prove
(`!x. (--pi < x /\ x <=
pi) ==>
(
sin x < &0 <=> --pi < x /\ x < &0) /\
(
sin x = &0 <=> (x = &0 \/ x =
pi)) /\
(&0 <
sin x <=> &0 < x /\ x <
pi)`,
STRIP_TAC THEN STRIP_TAC THEN SUBGOAL_THEN
`if (
sin x < &0) then (
sin x < &0 <=> --pi < x /\ x < &0) else
if (
sin x = &0) then (
sin x = &0 <=> (x = &0 \/ x =
pi)) else
(&0 <
sin x <=> &0 < x /\ x <
pi)` MP_TAC THENL
[ SUBGOAL_TAC "a" `--pi < x /\ x < &0 ==>
sin x < &0`
[ MP_TAC (REWRITE_RULE [
SIN_NEG] (SPEC `--x:real`
SIN_POS_PI)) THEN
REAL_ARITH_TAC ] THEN
SUBGOAL_TAC "b" `x = &0 ==>
sin x = &0`
[ STRIP_TAC THEN ASM_REWRITE_TAC [
SIN_0] ] THEN
SUBGOAL_TAC "c" `x =
pi ==>
sin x = &0`
[ STRIP_TAC THEN ASM_REWRITE_TAC [
SIN_PI] ] THEN
LABEL_TAC "d" (SPEC `x:real`
SIN_POS_PI) THEN
REPEAT (POP_ASSUM MP_TAC) THEN REAL_ARITH_TAC;
REPEAT (POP_ASSUM MP_TAC) THEN REAL_ARITH_TAC ]);;
let COS_NEGPOS_PI = prove
(`!x. (--pi < x /\ x <=
pi) ==>
(
cos x < &0 <=> (--pi < x /\ x < --(
pi / &2)) \/
(
pi / &2 < x /\ x <=
pi)) /\
(
cos x = &0 <=> (x = --(
pi / &2) \/ x =
pi / &2)) /\
(&0 <
cos x <=> --(
pi / &2) < x /\ x <
pi / &2)`,
STRIP_TAC THEN STRIP_TAC THEN SUBGOAL_THEN
`if (
cos x < &0) then (
cos x < &0 <=> (--pi < x /\ x < --(
pi / &2)) \/
(
pi / &2 < x /\ x <=
pi)) else
if (
cos x = &0) then
(
cos x = &0 <=> (x = --(
pi / &2) \/ x =
pi / &2)) else
(&0 <
cos x <=> --(
pi / &2) < x /\ x <
pi / &2)` MP_TAC THENL
[ SUBGOAL_TAC "a" `--pi < x /\ x < --(
pi / &2) ==>
cos x < &0`
[ MP_TAC (REWRITE_RULE [
COS_PERIODIC_PI]
(SPEC `x + pi:real`
COS_POS_PI2)) THEN
REAL_ARITH_TAC ] THEN
SUBGOAL_TAC "b" `
pi / &2 < x /\ x <=
pi ==>
cos x < &0`
[ MP_TAC (REWRITE_RULE [
SIN_NEG; GSYM
COS_SIN]
(SPEC `--(
pi / &2 - x)`
SIN_POS_PI2)) THEN
SUBGOAL_TAC "b1" `x =
pi ==>
cos x < &0`
[ STRIP_TAC THEN ASM_REWRITE_TAC [
COS_PI; REAL_ARITH `&0 < &1`] THEN
REAL_ARITH_TAC ] THEN
POP_ASSUM MP_TAC THEN REAL_ARITH_TAC ] THEN
SUBGOAL_TAC "c" `x = --(
pi / &2) ==>
cos x = &0`
[ STRIP_TAC THEN ASM_REWRITE_TAC [
COS_NEG;
COS_PI2] ] THEN
SUBGOAL_TAC "d" `x =
pi / &2 ==>
cos x = &0`
[ STRIP_TAC THEN ASM_REWRITE_TAC [
COS_PI2] ] THEN
LABEL_TAC "e" (SPEC `x:real`
COS_POS_PI) THEN
REPEAT (POP_ASSUM MP_TAC) THEN REAL_ARITH_TAC;
REPEAT (POP_ASSUM MP_TAC) THEN REAL_ARITH_TAC ]);;
(* ----------------------------------------------------------------------- *)
(* Theory of atan_2 function. See sphere.hl for the definiton. *)
(* ----------------------------------------------------------------------- *)
(* lemma:atn2_spec *)
let dist_lemma = prove
(`!x y. ~(x = &0) \/ ~(y = &0) ==>
(x /
sqrt(x pow 2 + y pow 2)) pow 2 +
(y /
sqrt(x pow 2 + y pow 2)) pow 2 = &1 /\
&0 <
sqrt(x pow 2 + y pow 2)`,
STRIP_TAC THEN STRIP_TAC THEN STRIP_TAC THEN
SUBGOAL_TAC "sum_pos" `&0 < x pow 2 + y pow 2 /\ &0 <= x pow 2 + y pow 2`
[ MP_TAC (SPEC `x:real`
REAL_LE_POW_2) THEN
MP_TAC (SPEC `y:real`
REAL_LE_POW_2) THEN
IMP_RES_THEN MP_TAC (SPECL [`x:real`; `2`]
REAL_POW_NZ) THEN
IMP_RES_THEN MP_TAC (SPECL [`y:real`; `2`]
REAL_POW_NZ) THEN
REAL_ARITH_TAC ] THEN
POP_ASSUM MP_TAC THEN STRIP_TAC THEN
ASM_SIMP_TAC [
REAL_POW_DIV;
SQRT_POW_2;
SQRT_POS_LT] THEN
POP_ASSUM MP_TAC THEN POP_ASSUM MP_TAC THEN
CONV_TAC REAL_FIELD);;
let ATAN2_EXISTS = prove
(`!x y. ?t. (--pi < t /\ t <=
pi) /\
x =
sqrt(x pow 2 + y pow 2) *
cos t /\
y =
sqrt(x pow 2 + y pow 2) *
sin t`,
REPEAT STRIP_TAC THEN ASM_CASES_TAC `(x = &0) /\ (y = &0)` THENL
[ ASM_REWRITE_TAC [(SPEC `2`
REAL_POW_ZERO)] THEN
NUM_REDUCE_TAC THEN CONV_TAC REAL_RAT_REDUCE_CONV THEN
REWRITE_TAC [
SQRT_0] THEN EXISTS_TAC `
pi` THEN MP_TAC
PI_POS THEN
REAL_ARITH_TAC ;
IMP_RES_THEN STRIP_ASSUME_TAC
(REWRITE_RULE [TAUT `(~A \/ ~B) <=> ~(A /\ B)`]
dist_lemma) THEN
IMP_RES_THEN STRIP_ASSUME_TAC
CIRCLE_SINCOS_PI THEN
POP_ASSUM (MP_TAC o GSYM) THEN POP_ASSUM (MP_TAC o GSYM) THEN
STRIP_TAC THEN STRIP_TAC THEN EXISTS_TAC `t:real` THEN
ASM_REWRITE_TAC [] THEN
POP_ASSUM (K ALL_TAC) THEN POP_ASSUM (K ALL_TAC) THEN
POP_ASSUM (K ALL_TAC) THEN POP_ASSUM (K ALL_TAC) THEN
POP_ASSUM MP_TAC THEN CONV_TAC REAL_FIELD ]);;
(* The official Kepler definition (atn2) is different, but it was easier *)
(* to start with this one and prove it is equivalent. *)
let ATAN2_TEMP_DEF = new_definition
`atan2_temp (x,y) = if (x = &0 /\ y = &0)
then pi
else @t. (--pi < t /\ t <= pi) /\
x = sqrt(x pow 2 + y pow 2) * cos t /\
y = sqrt(x pow 2 + y pow 2) * sin t`;;
let ATAN2_TEMP = prove
(`!x y. (--pi < atan2_temp (x,y) /\ atan2_temp (x,y) <=
pi) /\
x =
sqrt(x pow 2 + y pow 2) *
cos (atan2_temp (x,y)) /\
y =
sqrt(x pow 2 + y pow 2) *
sin (atan2_temp (x,y))`,
STRIP_TAC THEN STRIP_TAC THEN REWRITE_TAC [
ATAN2_TEMP_DEF] THEN
COND_CASES_TAC THENL
[ ASM_REWRITE_TAC [(SPEC `2`
REAL_POW_ZERO)] THEN
NUM_REDUCE_TAC THEN CONV_TAC REAL_RAT_REDUCE_CONV THEN
REWRITE_TAC [
SQRT_0] THEN MP_TAC
PI_POS THEN
REAL_ARITH_TAC ;
REWRITE_TAC [(SELECT_RULE (SPECL [`x:real`;`y:real`]
ATAN2_EXISTS))]]);;
let ATAN2_TEMP_SPEC = prove
(`!x y. ?r. ((--
pi < atan2_temp(x, y)) /\ (atan2_temp(x,y) <=
pi) /\
(x = r* (
cos(atan2_temp(x,y)))) /\ (y = r* (
sin (atan2_temp( x, y)))) /\
(&0 <= r))`,
STRIP_TAC THEN STRIP_TAC THEN EXISTS_TAC `
sqrt(x pow 2 + y pow 2)` THEN
REWRITE_TAC [
ATAN2_TEMP] THEN SUBGOAL_TAC "sum_pos" `&0 <= x pow 2 + y pow 2`
[ MP_TAC (SPEC `x:real`
REAL_LE_POW_2) THEN
MP_TAC (SPEC `y:real`
REAL_LE_POW_2) THEN
REAL_ARITH_TAC ] THEN
MP_TAC (SPEC `x pow 2 + y pow 2`
SQRT_POS_LE) THEN POP_ASSUM MP_TAC THEN
REAL_ARITH_TAC);;
let ATAN2_TEMP_BREAKDOWN = prove
(`!x y. (&0 < x ==> atan2_temp(x,y) =
atn(y / x)) /\
(&0 < y ==> atan2_temp(x,y) =
pi / &2 -
atn(x / y)) /\
(y < &0 ==> atan2_temp(x,y) = --(
pi / &2) -
atn(x / y)) /\
(y = &0 /\ x <= &0 ==> atan2_temp(x,y) =
pi)`,
REPEAT GEN_TAC THEN REPEAT CONJ_TAC THENL
[ STRIP_ASSUME_TAC (SPECL [`x:real`;`y:real`]
ATAN2_TEMP) THEN
ABBREV_TAC `t = atan2_temp (x,y)` THEN
ABBREV_TAC `r =
sqrt (x pow 2 + y pow 2)` THEN STRIP_TAC THEN
SUBGOAL_TAC "r_pos" `&0 < r`
[ EXPAND_TAC "r" THEN MP_TAC (SPECL [`x:real`;`y:real`]
dist_lemma) THEN
POP_ASSUM MP_TAC THEN REAL_ARITH_TAC] THEN
SUBGOAL_TAC "tan" `(r *
sin t) / (r *
cos t) =
tan t`
[ REWRITE_TAC [
tan] THEN POP_ASSUM MP_TAC THEN CONV_TAC REAL_FIELD ] THEN
ASM_REWRITE_TAC [] THEN MATCH_MP_TAC (GSYM
TAN_ATN) THEN
POP_ASSUM (K ALL_TAC) THEN
POP_ASSUM (fun
th -> POP_ASSUM MP_TAC THEN ASSUME_TAC
th) THEN
ASM_SIMP_TAC [GSYM
COS_NEGPOS_PI;
REAL_LT_MUL_EQ] THEN REAL_ARITH_TAC ;
STRIP_ASSUME_TAC (SPECL [`x:real`;`y:real`]
ATAN2_TEMP) THEN
ABBREV_TAC `t = atan2_temp (x,y)` THEN
ABBREV_TAC `r =
sqrt (x pow 2 + y pow 2)` THEN STRIP_TAC THEN
SUBGOAL_TAC "r_pos" `&0 < r`
[ EXPAND_TAC "r" THEN MP_TAC (SPECL [`x:real`;`y:real`]
dist_lemma) THEN
POP_ASSUM MP_TAC THEN REAL_ARITH_TAC] THEN
SUBGOAL_TAC "tan" `(r *
cos t) / (r *
sin t) = inv (
tan t)`
[ REWRITE_TAC [
tan] THEN POP_ASSUM MP_TAC THEN
CONV_TAC REAL_FIELD ] THEN
ASM_REWRITE_TAC [GSYM
TAN_COT] THEN
SUBGOAL_THEN `
pi / &2 - t =
atn (
tan (
pi / &2 - t))`
(fun
th -> REWRITE_TAC [GSYM
th] THEN REAL_ARITH_TAC) THEN
MATCH_MP_TAC (GSYM
TAN_ATN) THEN
SUBGOAL_THEN `&0 < t /\ t <
pi`
(fun
th -> MP_TAC
th THEN REAL_ARITH_TAC) THEN
POP_ASSUM (K ALL_TAC) THEN
POP_ASSUM (fun
th -> POP_ASSUM MP_TAC THEN ASSUME_TAC
th) THEN
ASM_SIMP_TAC [GSYM
SIN_NEGPOS_PI;
REAL_LT_MUL_EQ] THEN REAL_ARITH_TAC ;
STRIP_ASSUME_TAC (SPECL [`x:real`;`y:real`]
ATAN2_TEMP) THEN
ABBREV_TAC `t = atan2_temp (x,y)` THEN
ABBREV_TAC `r =
sqrt (x pow 2 + y pow 2)` THEN STRIP_TAC THEN
SUBGOAL_TAC "r_pos" `&0 < r`
[ EXPAND_TAC "r" THEN MP_TAC (SPECL [`x:real`;`y:real`]
dist_lemma) THEN
POP_ASSUM MP_TAC THEN REAL_ARITH_TAC] THEN
SUBGOAL_TAC "tan" `(r *
cos t) / (r *
sin t) = --inv (
tan (--t))`
[ REWRITE_TAC [
TAN_NEG;
REAL_INV_NEG] THEN
REWRITE_TAC [
tan;
REAL_NEG_NEG] THEN
POP_ASSUM MP_TAC THEN CONV_TAC REAL_FIELD ] THEN
ASM_REWRITE_TAC [GSYM
TAN_COT;
ATN_NEG] THEN
SUBGOAL_THEN `
pi / &2 + t =
atn (
tan (
pi / &2 + t))`
(fun
th -> REWRITE_TAC [REAL_ARITH `
pi / &2 - --t =
pi / &2 + t`;GSYM
th]
THEN REAL_ARITH_TAC) THEN
MATCH_MP_TAC (GSYM
TAN_ATN) THEN
SUBGOAL_THEN `--pi < t /\ t < &0`
(fun
th -> MP_TAC
th THEN REAL_ARITH_TAC) THEN
POP_ASSUM (K ALL_TAC) THEN
POP_ASSUM (fun
th -> POP_ASSUM (MP_TAC o (REWRITE_RULE [GSYM
REAL_NEG_GT0]))
THEN ASSUME_TAC
th) THEN
ASM_SIMP_TAC [GSYM
SIN_NEGPOS_PI;
REAL_LT_MUL_EQ;
REAL_NEG_RMUL] THEN
REAL_ARITH_TAC ;
ASM_CASES_TAC `x = &0` THENL
[ STRIP_TAC THEN ASM_REWRITE_TAC [
ATAN2_TEMP_DEF];
ALL_TAC] THEN
STRIP_ASSUME_TAC (SPECL [`x:real`;`y:real`]
ATAN2_TEMP) THEN
ABBREV_TAC `t = atan2_temp (x,y)` THEN
ABBREV_TAC `r =
sqrt (x pow 2 + y pow 2)` THEN STRIP_TAC THEN
SUBGOAL_TAC "r_pos" `&0 < r`
[ EXPAND_TAC "r" THEN MP_TAC (SPECL [`x:real`;`y:real`]
dist_lemma) THEN
POP_ASSUM MP_TAC THEN FIND_ASSUM MP_TAC `~(x = &0)` THEN
REAL_ARITH_TAC ] THEN
SUBGOAL_TAC "sin_cos" `
sin t = &0 /\
cos t < &0 ==> t =
pi`
[ ASM_SIMP_TAC [
SIN_NEGPOS_PI;
COS_NEGPOS_PI] THEN MP_TAC
PI_POS THEN
REAL_ARITH_TAC ] THEN
POP_ASSUM MATCH_MP_TAC THEN
SUBGOAL_TAC "x_pos" `&0 < --x`
[ FIND_ASSUM MP_TAC `x <= &0` THEN FIND_ASSUM MP_TAC `~(x = &0)` THEN
REAL_ARITH_TAC ] THEN
POP_ASSUM MP_TAC THEN
POP_ASSUM (fun
th -> POP_ASSUM (K ALL_TAC) THEN POP_ASSUM MP_TAC THEN
ASSUME_TAC
th) THEN
ASM_SIMP_TAC [
REAL_LT_MUL_EQ;
REAL_NEG_RMUL] THEN POP_ASSUM MP_TAC THEN
CONV_TAC REAL_FIELD]);;
let ATAN2_TEMP_ALT = prove
(`!x y. atan2_temp (x,y) =
if ( abs y < x ) then
atn(y / x) else
(if (&0 < y) then ((
pi / &2) -
atn(x / y)) else
(if (y < &0) then (-- (pi/ &2) -
atn (x / y)) else (
pi )))`,
STRIP_TAC THEN STRIP_TAC THEN COND_CASES_TAC THENL
[ SUBGOAL_THEN `&0 < x`
(fun
th -> SIMP_TAC [
th;
ATAN2_TEMP_BREAKDOWN]) THEN
POP_ASSUM MP_TAC THEN REAL_ARITH_TAC;
COND_CASES_TAC THENL
[ SUBGOAL_THEN `&0 < y`
(fun
th -> SIMP_TAC [
th;
ATAN2_TEMP_BREAKDOWN]) THEN
POP_ASSUM MP_TAC THEN REAL_ARITH_TAC;
COND_CASES_TAC THENL
[ SUBGOAL_THEN `y < &0`
(fun
th -> SIMP_TAC [
th;
ATAN2_TEMP_BREAKDOWN]) THEN
POP_ASSUM MP_TAC THEN REAL_ARITH_TAC;
SUBGOAL_THEN `y = &0`
(fun
th -> POP_ASSUM (K ALL_TAC) THEN POP_ASSUM (K ALL_TAC) THEN
ASSUME_TAC
th) THENL
[ POP_ASSUM MP_TAC THEN POP_ASSUM MP_TAC THEN REAL_ARITH_TAC ;
SUBGOAL_THEN `x <= &0`
(fun
th -> ASM_SIMP_TAC [
th;
ATAN2_TEMP_BREAKDOWN]) THEN
POP_ASSUM MP_TAC THEN POP_ASSUM MP_TAC THEN REAL_ARITH_TAC ]]]]);;
(* Show that the working def and the official def are equivalent. *)
(* These three and the definition should suffice as the basic *)
(* specifications for atn2. No more need for atan2_temp.*)
let ATN2_BREAKDOWN = prove
(`!x y. (&0 < x ==> atn2 (x,y) =
atn(y / x)) /\
(&0 < y ==> atn2 (x,y) =
pi / &2 -
atn(x / y)) /\
(y < &0 ==> atn2 (x,y) = --(
pi / &2) -
atn(x / y)) /\
(y = &0 /\ x <= &0 ==> atn2(x,y) =
pi)`,
let ATN2_CIRCLE = prove
(`!x y. (--pi < atan2_temp (x,y) /\ atan2_temp (x,y) <=
pi) /\
x =
sqrt(x pow 2 + y pow 2) *
cos (atan2_temp (x,y)) /\
y =
sqrt(x pow 2 + y pow 2) *
sin (atan2_temp (x,y))`,
(* Useful properties of atn2. *)
let ATN2_0_1 = prove
(`atn2 (&0, &1) =
pi / &2`,
ASSUME_TAC (REAL_ARITH `&0 < &1`) THEN
ASM_SIMP_TAC [
ATN2_BREAKDOWN] THEN CONV_TAC REAL_RAT_REDUCE_CONV THEN
REWRITE_TAC [
ATN_0] THEN REAL_ARITH_TAC);;
let ATN2_0_NEG_1 = prove
(`atn2 (&0, --(&1)) = --(
pi / &2)`,
ASSUME_TAC (REAL_ARITH `--(&1) < &0`) THEN
ASM_SIMP_TAC [
ATN2_BREAKDOWN] THEN CONV_TAC REAL_RAT_REDUCE_CONV THEN
REWRITE_TAC [
ATN_0] THEN REAL_ARITH_TAC);;
let ATN2_RNEG = prove
(`!x y. (~(y = &0) \/ &0 < x) ==> atn2(x,--y) = --(atn2(x,y))`,
STRIP_TAC THEN STRIP_TAC THEN STRIP_ASSUME_TAC
(REAL_ARITH `&0 < x \/ &0 < y \/ y < &0 \/ (y = &0 /\ x <= &0)`) THENL
[ ASM_REWRITE_TAC [] ;
ASM_SIMP_TAC [
REAL_LT_IMP_NE] THEN SUBGOAL_TAC "neg" `--y < &0`
[ ASM_REWRITE_TAC [
REAL_NEG_LT0] ] ;
ASM_SIMP_TAC [
REAL_LT_IMP_NE] THEN SUBGOAL_TAC "pos" `&0 < --y`
[ ASM_REWRITE_TAC [
REAL_NEG_GT0] ] ;
ASM_REWRITE_TAC [
real_lt] ] THEN
let
th1 = SPECL [`x:real`;`y:real`]
ATN2_BREAKDOWN in
let
th2 = SPECL [`x:real`;`--y:real`]
ATN2_BREAKDOWN in
let
th3 = REAL_ARITH `(--x)/y = --(x/y)` in
let th4 = REAL_FIELD `(y < &0 \/ &0 < y) ==> x / (--y) = --(x/y)` in
ASM_SIMP_TAC [
th1;
th2;
th3; th4;
ATN_NEG] THEN REAL_ARITH_TAC);;
(* lemma:acs_atn2 *)
let acs_atn2 = prove
(acs_atn2_t,
STRIP_TAC THEN ASM_CASES_TAC `y = &1 \/ y = --(&1)` THENL
[ POP_ASSUM DISJ_CASES_TAC THENL
[ ASM_REWRITE_TAC [] THEN CONV_TAC REAL_RAT_REDUCE_CONV THEN
REWRITE_TAC [ACS_1; SQRT_0; ATN2_0_1] THEN REAL_ARITH_TAC ;
ASM_REWRITE_TAC [] THEN CONV_TAC REAL_RAT_REDUCE_CONV THEN
REWRITE_TAC [ACS_NEG_1; SQRT_0; ATN2_0_NEG_1] THEN REAL_ARITH_TAC ] ;
STRIP_TAC THEN
SUBGOAL_TAC "sqrt" `&0 < sqrt (&1 - y pow 2)`
[ MATCH_MP_TAC SQRT_POS_LT THEN
SUBGOAL_THEN `&0 <= y pow 2 /\ y pow 2 < &1`
(fun th -> MP_TAC th THEN REAL_ARITH_TAC) THEN
REWRITE_TAC [REAL_LE_POW_2; REAL_ARITH `a < &1 <=> a < &1 pow 2`;
GSYM REAL_LT_SQUARE_ABS ] THEN
REPEAT (POP_ASSUM MP_TAC) THEN REAL_ARITH_TAC ] THEN
ASM_SIMP_TAC [ATN2_BREAKDOWN] THEN MATCH_MP_TAC ACS_ATN THEN
REPEAT (POP_ASSUM MP_TAC) THEN REAL_ARITH_TAC ]);;
(* ----------------------------------------------------------------------- *)
(* Theory of triangles (without vectors). Includes laws of cosines/sines. *)
(* ----------------------------------------------------------------------- *)
let UPS_X_SQUARES = prove
(`!a b c.
ups_x (a * a) (b * b) (c * c) =
&16 * ((a + b + c) / &2) *
(((a + b + c) / &2) - a) *
(((a + b + c) / &2) - b) *
(((a + b + c) / &2) - c)`,
REPEAT STRIP_TAC THEN REWRITE_TAC [
ups_x] THEN REAL_ARITH_TAC);;
(* Theorems assuming a, b, c are lengths of a triangle (c not 0). *)
let TRI_UPS_X_POS = prove
(`!a b c. (&0 < a) /\ (&0 < b) /\ (&0 <= c) /\ (c <= a + b) /\ (a <= b + c) /\ (b <= c + a) ==>
&0 <=
ups_x (a * a) (b * b) (c * c)`,
REPEAT STRIP_TAC THEN REWRITE_TAC [
UPS_X_SQUARES] THEN
REPEAT (MATCH_MP_TAC
REAL_LE_MUL THEN STRIP_TAC) THENL
[ REAL_ARITH_TAC ;
REPEAT (POP_ASSUM MP_TAC) THEN REAL_ARITH_TAC ;
SUBGOAL_THEN `&2 * a <= a + b + c`
(fun
th -> MP_TAC
th THEN REAL_ARITH_TAC) THEN
REPEAT (POP_ASSUM MP_TAC) THEN REAL_ARITH_TAC ;
SUBGOAL_THEN `&2 * b <= a + b + c`
(fun
th -> MP_TAC
th THEN REAL_ARITH_TAC) THEN
REPEAT (POP_ASSUM MP_TAC) THEN REAL_ARITH_TAC ;
SUBGOAL_THEN `&2 * c <= a + b + c`
(fun
th -> MP_TAC
th THEN REAL_ARITH_TAC) THEN
REPEAT (POP_ASSUM MP_TAC) THEN REAL_ARITH_TAC ]);;
let TRI_SQUARES_BOUNDS = prove
(`!a b c. (&0 < a) /\ (&0 < b) /\ (&0 <= c) /\ (c <= a + b) /\ (a <= b + c) /\ (b <= c + a) ==>
--(&1) <= ((a * a) + (b * b) - (c * c)) / (&2 * a * b) /\
((a * a) + (b * b) - (c * c)) / (&2 * a * b) <= &1`,
REPEAT STRIP_TAC THEN
SUBGOAL_TAC "2ab_pos" `&0 < &2 * a * b`
[ ASM_SIMP_TAC [
REAL_LT_MUL_3; REAL_ARITH `&0 < &2`] ] THENL
[ SUBGOAL_TAC "abc_square" `c*c <= (a + b) * (a + b)`
[ MATCH_MP_TAC (REWRITE_RULE [IMP_IMP]
REAL_LE_MUL2) THEN
REPEAT (POP_ASSUM MP_TAC) THEN REAL_ARITH_TAC ] THEN
ASM_SIMP_TAC [
REAL_LE_RDIV_EQ] THEN REMOVE_THEN "abc_square" MP_TAC THEN
REAL_ARITH_TAC ;
SUBGOAL_TAC "abc_square" `(a - b) * (a - b) <= c*c`
[ DISJ_CASES_TAC (REAL_ARITH `a <= b \/ b <= a`) THENL
[ SUBST1_TAC (REAL_ARITH `(a-b)*(a-b)=(b-a)*(b-a)`); ALL_TAC ] THEN
MATCH_MP_TAC (REWRITE_RULE [IMP_IMP]
REAL_LE_MUL2) THEN
REPEAT (POP_ASSUM MP_TAC) THEN REAL_ARITH_TAC ] THEN
ASM_SIMP_TAC [
REAL_LE_LDIV_EQ] THEN REMOVE_THEN "abc_square" MP_TAC THEN
REAL_ARITH_TAC ]);;
let ATN2_ARCLENGTH = prove
(`!a b c. (&0 < a) /\ (&0 < b) /\ (&0 <= c) /\ (c <= a + b) /\ (a <= b + c) /\ (b <= c + a) ==>
arclength a b c =
pi / &2 - atn2(
sqrt(
ups_x (a*a) (b*b) (c*c)), (a*a) + (b*b) - (c*c))`,
REPEAT STRIP_TAC THEN
let
th = REAL_ARITH `c * c - a * a - b * b = --(a * a + b * b - c * c)` in
REWRITE_TAC [arclength;
th;
ATN2_RNEG] THEN
SUBGOAL_THEN `~(a * a + b * b - c * c = &0) \/
&0 <
sqrt(
ups_x (a*a) (b*b) (c*c))`
(fun
th -> ASM_SIMP_TAC [
th;
ATN2_RNEG] THEN
REAL_ARITH_TAC) THEN
REWRITE_TAC [TAUT `(~A \/ B) <=> (A ==> B)`] THEN STRIP_TAC THEN
SUBGOAL_TAC "c_ab" `c*c = a*a + b*b`
[ POP_ASSUM MP_TAC THEN REAL_ARITH_TAC ] THEN
REMOVE_THEN "c_ab" (fun
th -> REWRITE_TAC [
ups_x;
th]) THEN
MATCH_MP_TAC
SQRT_POS_LT THEN
CONV_TAC (DEPTH_BINOP_CONV `(<)` REAL_POLY_CONV) THEN
MATCH_MP_TAC
REAL_LT_MUL_3 THEN STRIP_TAC THENL
[ REAL_ARITH_TAC ;
ASM_SIMP_TAC [
REAL_POW_LT] ]);;
let TRI_LEMMA = prove
(`!a b c. (&0 < a) /\ (&0 < b) /\ (&0 <= c) /\ (c <= a + b) /\ (a <= b + c) /\ (b <= c + a) ==>
(&2 * a * b) * (a * a + b * b - c * c) / (&2 * a * b) =
a * a + b * b - c * c`,
REPEAT STRIP_TAC THEN
SUBGOAL_TAC "2ab_pos" `&0 < &2 * a * b`
[ ASM_SIMP_TAC [
REAL_LT_MUL_3; REAL_ARITH `&0 < &2`] ] THEN
SUBGOAL_TAC "2ab_not0" `~(&2 * a * b = &0)`
[ POP_ASSUM MP_TAC THEN REAL_ARITH_TAC ] THEN
ASM_SIMP_TAC [
REAL_DIV_LMUL]);;
let TRI_UPS_X_SQUARES = prove
(`!a b c. (&0 < a) /\ (&0 < b) /\ (&0 <= c) /\ (c <= a + b) /\ (a <= b + c) /\ (b <= c + a) ==>
ups_x (a * a) (b * b) (c * c) =
(&2 * a * b) pow 2 * (&1 - ((a * a + b * b - c * c) / (&2 * a * b)) pow 2)`,
let TRI_UPS_X_SQRT = prove
(`!a b c. (&0 < a) /\ (&0 < b) /\ (&0 <= c) /\ (c <= a + b) /\ (a <= b + c) /\ (b <= c + a) ==>
sqrt(
ups_x (a * a) (b * b) (c * c)) =
(&2 * a * b) *
sqrt(&1 - ((a * a + b * b - c * c) / (&2 * a * b)) pow 2)`,
let ACS_ARCLENGTH = prove
(`!a b c. (&0 < a) /\ (&0 < b) /\ (&0 <= c) /\ (c <= a + b) /\ (a <= b + c) /\ (b <= c + a) ==>
arclength a b c =
acs (((a * a) + (b * b) - (c * c)) / (&2 * a * b))`,
(* ----------------------------------------------------------------------- *)
(* Cross product properties. *)
(* ----------------------------------------------------------------------- *)
let DIST_TRIANGLE_DETAILS = prove
(`~(u = v) /\ ~(u = w) <=>
&0 <
dist(u,v) /\ &0 <
dist(u,w) /\
&0 <=
dist(v,w) /\
dist(v,w) <=
dist(u,v) +
dist(u,w) /\
dist(u,v) <=
dist(u,w) +
dist(v,w) /\
dist(u,w) <=
dist(v,w) +
dist(u,v)`,
NORM_ARITH_TAC);;
(* I would like to change this to real^N but that means changing arcV to real^N *)
(* DIMINDEX_3, FORALL_3, SUM_3, DOT_3, VECTOR_3, FORALL_VECTOR_3 *)
(* are all very useful. Any time you see a theorem you need with *)
(* 1 <= i /\ i <= dimindex(:3), first use INST_TYPE and then rewrite *)
(* with DIMINDEX_3 and FORALL_3 or see if it's in the list below. *)
(* COND_COMPONENT_3 - no need, COND_COMPONENT works fine. *)
end;;