(* ========================================================================= *)
(* The five Platonic solids exist and there are no others. *)
(* ========================================================================= *)
needs "100/polyhedron.ml";;
needs "Multivariate/cross.ml";;
prioritize_real();;
(* ------------------------------------------------------------------------- *)
(* Some standard regular polyhedra (vertex coordinates from Wikipedia). *)
(* ------------------------------------------------------------------------- *)
let std_tetrahedron = new_definition
`std_tetrahedron =
convex hull
{vector[&1;&1;&1],vector[-- &1;-- &1;&1],
vector[-- &1;&1;-- &1],vector[&1;-- &1;-- &1]}:real^3->bool`;;
let std_cube = new_definition
`std_cube =
convex hull
{vector[&1;&1;&1],vector[&1;&1;-- &1],
vector[&1;-- &1;&1],vector[&1;-- &1;-- &1],
vector[-- &1;&1;&1],vector[-- &1;&1;-- &1],
vector[-- &1;-- &1;&1],vector[-- &1;-- &1;-- &1]}:real^3->bool`;;
let std_octahedron = new_definition
`std_octahedron =
convex hull
{vector[&1;&0;&0],vector[-- &1;&0;&0],
vector[&0;&0;&1],vector[&0;&0;-- &1],
vector[&0;&1;&0],vector[&0;-- &1;&0]}:real^3->bool`;;
let std_dodecahedron = new_definition
`std_dodecahedron =
let p = (&1 + sqrt(&5)) / &2 in
convex hull
{vector[&1;&1;&1],vector[&1;&1;-- &1],
vector[&1;-- &1;&1],vector[&1;-- &1;-- &1],
vector[-- &1;&1;&1],vector[-- &1;&1;-- &1],
vector[-- &1;-- &1;&1],vector[-- &1;-- &1;-- &1],
vector[&0;inv p;p],vector[&0;inv p;--p],
vector[&0;--inv p;p],vector[&0;--inv p;--p],
vector[inv p;p;&0],vector[inv p;--p;&0],
vector[--inv p;p;&0],vector[--inv p;--p;&0],
vector[p;&0;inv p],vector[--p;&0;inv p],
vector[p;&0;--inv p],vector[--p;&0;--inv p]}:real^3->bool`;;
let std_icosahedron = new_definition
`std_icosahedron =
let p = (&1 + sqrt(&5)) / &2 in
convex hull
{vector[&0; &1; p],vector[&0; &1; --p],
vector[&0; -- &1; p],vector[&0; -- &1; --p],
vector[&1; p; &0],vector[&1; --p; &0],
vector[-- &1; p; &0],vector[-- &1; --p; &0],
vector[p; &0; &1],vector[--p; &0; &1],
vector[p; &0; -- &1],vector[--p; &0; -- &1]}:real^3->bool`;;
(* ------------------------------------------------------------------------- *)
(* Slightly ad hoc conversions for computation in Q[sqrt(5)]. *)
(* Numbers are canonically represented as either a rational constant r or an *)
(* expression r1 + r2 * sqrt(5) where r2 is nonzero but r1 may be zero and *)
(* must be present. *)
(* ------------------------------------------------------------------------- *)
let REAL_RAT5_OF_RAT_CONV =
let pth = prove
(`p = p + &0 * sqrt(&5)`,
REAL_ARITH_TAC) in
let conv = REWR_CONV pth in
fun tm -> if is_ratconst tm then conv tm else REFL tm;;
let REAL_RAT_OF_RAT5_CONV =
let pth = prove
(`p + &0 * sqrt(&5) = p`,
REAL_ARITH_TAC) in
GEN_REWRITE_CONV TRY_CONV [pth];;
let REAL_RAT5_ADD_CONV =
let pth = prove
(`(a1 + b1 * sqrt(&5)) + (a2 + b2 * sqrt(&5)) =
(a1 + a2) + (b1 + b2) * sqrt(&5)`,
REAL_ARITH_TAC) in
REAL_RAT_ADD_CONV ORELSEC
(BINOP_CONV REAL_RAT5_OF_RAT_CONV THENC
GEN_REWRITE_CONV I [pth] THENC
LAND_CONV REAL_RAT_ADD_CONV THENC
RAND_CONV(LAND_CONV REAL_RAT_ADD_CONV) THENC
REAL_RAT_OF_RAT5_CONV);;
let REAL_RAT5_SUB_CONV =
let pth = prove
(`(a1 + b1 * sqrt(&5)) - (a2 + b2 * sqrt(&5)) =
(a1 - a2) + (b1 - b2) * sqrt(&5)`,
REAL_ARITH_TAC) in
REAL_RAT_SUB_CONV ORELSEC
(BINOP_CONV REAL_RAT5_OF_RAT_CONV THENC
GEN_REWRITE_CONV I [pth] THENC
LAND_CONV REAL_RAT_SUB_CONV THENC
RAND_CONV(LAND_CONV REAL_RAT_SUB_CONV) THENC
REAL_RAT_OF_RAT5_CONV);;
let REAL_RAT5_MUL_CONV =
let pth = prove
(`(a1 + b1 * sqrt(&5)) * (a2 + b2 * sqrt(&5)) =
(a1 * a2 + &5 * b1 * b2) + (a1 * b2 + a2 * b1) * sqrt(&5)`,
MP_TAC(ISPEC `&5`
SQRT_POW_2) THEN CONV_TAC REAL_FIELD) in
REAL_RAT_MUL_CONV ORELSEC
(BINOP_CONV REAL_RAT5_OF_RAT_CONV THENC
GEN_REWRITE_CONV I [pth] THENC
LAND_CONV(COMB_CONV (RAND_CONV REAL_RAT_MUL_CONV) THENC
RAND_CONV REAL_RAT_MUL_CONV THENC
REAL_RAT_ADD_CONV) THENC
RAND_CONV(LAND_CONV
(BINOP_CONV REAL_RAT_MUL_CONV THENC REAL_RAT_ADD_CONV)) THENC
REAL_RAT_OF_RAT5_CONV);;
let REAL_RAT5_INV_CONV =
let pth = prove
(`~(a pow 2 = &5 * b pow 2)
==> inv(a + b * sqrt(&5)) =
a / (a pow 2 - &5 * b pow 2) +
--b / (a pow 2 - &5 * b pow 2) * sqrt(&5)`,
REPEAT GEN_TAC THEN
GEN_REWRITE_TAC (LAND_CONV o ONCE_DEPTH_CONV) [GSYM
REAL_SUB_0] THEN
SUBGOAL_THEN
`a pow 2 - &5 * b pow 2 = (a + b * sqrt(&5)) * (a - b * sqrt(&5))`
SUBST1_TAC THENL
[MP_TAC(SPEC `&5`
SQRT_POW_2) THEN CONV_TAC REAL_FIELD;
REWRITE_TAC[
REAL_ENTIRE; DE_MORGAN_THM] THEN CONV_TAC REAL_FIELD]) in
fun tm ->
try REAL_RAT_INV_CONV tm with Failure _ ->
let th1 = PART_MATCH (lhs o rand) pth tm in
let th2 = MP th1 (EQT_ELIM(REAL_RAT_REDUCE_CONV(lhand(concl th1)))) in
let th3 = CONV_RULE(funpow 2 RAND_CONV (funpow 2 LAND_CONV
REAL_RAT_NEG_CONV)) th2 in
let th4 = CONV_RULE(RAND_CONV(RAND_CONV(LAND_CONV
(RAND_CONV(LAND_CONV REAL_RAT_POW_CONV THENC
RAND_CONV(RAND_CONV REAL_RAT_POW_CONV THENC
REAL_RAT_MUL_CONV) THENC
REAL_RAT_SUB_CONV) THENC
REAL_RAT_DIV_CONV)))) th3 in
let th5 = CONV_RULE(RAND_CONV(LAND_CONV
(RAND_CONV(LAND_CONV REAL_RAT_POW_CONV THENC
RAND_CONV(RAND_CONV REAL_RAT_POW_CONV THENC
REAL_RAT_MUL_CONV) THENC
REAL_RAT_SUB_CONV) THENC
REAL_RAT_DIV_CONV))) th4 in
th5;;
let REAL_RAT5_DIV_CONV =
GEN_REWRITE_CONV I [real_div] THENC
RAND_CONV REAL_RAT5_INV_CONV THENC
REAL_RAT5_MUL_CONV;;
let REAL_RAT5_LE_CONV =
let lemma = prove
(`!x y. x <= y * sqrt(&5) <=>
x <= &0 /\ &0 <= y \/
&0 <= x /\ &0 <= y /\ x pow 2 <= &5 * y pow 2 \/
x <= &0 /\ y <= &0 /\ &5 * y pow 2 <= x pow 2`,
REPEAT GEN_TAC THEN MP_TAC(ISPEC `&5`
SQRT_POW_2) THEN
REWRITE_TAC[
REAL_POS] THEN DISCH_THEN(fun th ->
GEN_REWRITE_TAC (RAND_CONV o ONCE_DEPTH_CONV) [SYM th]) THEN
REWRITE_TAC[GSYM
REAL_POW_MUL; GSYM
REAL_LE_SQUARE_ABS] THEN
MP_TAC(ISPECL [`sqrt(&5)`; `y:real`] (CONJUNCT1
REAL_LE_MUL_EQ)) THEN
SIMP_TAC[
SQRT_POS_LT;
REAL_OF_NUM_LT; ARITH] THEN REAL_ARITH_TAC) in
let pth = prove
(`(a1 + b1 * sqrt(&5)) <= (a2 + b2 * sqrt(&5)) <=>
a1 <= a2 /\ b1 <= b2 \/
a2 <= a1 /\ b1 <= b2 /\ (a1 - a2) pow 2 <= &5 * (b2 - b1) pow 2 \/
a1 <= a2 /\ b2 <= b1 /\ &5 * (b2 - b1) pow 2 <= (a1 - a2) pow 2`,
REWRITE_TAC[REAL_ARITH
`a + b * x <= a' + b' * x <=> a - a' <= (b' - b) * x`] THEN
REWRITE_TAC[lemma] THEN REAL_ARITH_TAC) in
REAL_RAT_LE_CONV ORELSEC
(BINOP_CONV REAL_RAT5_OF_RAT_CONV THENC
GEN_REWRITE_CONV I [pth] THENC
REAL_RAT_REDUCE_CONV);;
let REAL_RAT5_EQ_CONV =
GEN_REWRITE_CONV I [GSYM REAL_LE_ANTISYM] THENC
BINOP_CONV REAL_RAT5_LE_CONV THENC
GEN_REWRITE_CONV I [AND_CLAUSES];;
(* ------------------------------------------------------------------------- *)
(* Conversions for operations on 3D vectors with coordinates in Q[sqrt(5)] *)
(* ------------------------------------------------------------------------- *)
let VECTOR3_SUB_CONV =
let pth = prove
(`vector[x1;x2;x3] - vector[y1;y2;y3]:real^3 =
vector[x1-y1; x2-y2; x3-y3]`,
let VECTOR3_CROSS_CONV =
let pth = prove
(`(vector[x1;x2;x3]) cross (vector[y1;y2;y3]) =
vector[x2 * y3 - x3 * y2; x3 * y1 - x1 * y3; x1 * y2 - x2 * y1]`,
REWRITE_TAC[cross;
VECTOR_3]) in
GEN_REWRITE_CONV I [pth] THENC
RAND_CONV(LIST_CONV(BINOP_CONV REAL_RAT5_MUL_CONV THENC REAL_RAT5_SUB_CONV));;
let VECTOR3_EQ_0_CONV =
let pth = prove
(`vector[x1;x2;x3]:real^3 = vec 0 <=>
x1 = &0 /\ x2 = &0 /\ x3 = &0`,
SIMP_TAC[
CART_EQ; DIMINDEX_3;
FORALL_3] THEN
REWRITE_TAC[
VECTOR_3;
VEC_COMPONENT]) in
GEN_REWRITE_CONV I [pth] THENC
DEPTH_BINOP_CONV `(/\)` REAL_RAT5_EQ_CONV THENC
REWRITE_CONV[];;
let VECTOR3_DOT_CONV =
let pth = prove
(`(vector[x1;x2;x3]:real^3) dot (vector[y1;y2;y3]) =
x1*y1 + x2*y2 + x3*y3`,
REWRITE_TAC[
DOT_3;
VECTOR_3]) in
GEN_REWRITE_CONV I [pth] THENC
DEPTH_BINOP_CONV `(+):real->real->real` REAL_RAT5_MUL_CONV THENC
RAND_CONV REAL_RAT5_ADD_CONV THENC
REAL_RAT5_ADD_CONV;;
(* ------------------------------------------------------------------------- *)
(* Put any irrational coordinates in our standard form. *)
(* ------------------------------------------------------------------------- *)
let STD_DODECAHEDRON = prove
(`
std_dodecahedron =
convex hull
{ vector[&1; &1; &1],
vector[&1; &1; -- &1],
vector[&1; -- &1; &1],
vector[&1; -- &1; -- &1],
vector[-- &1; &1; &1],
vector[-- &1; &1; -- &1],
vector[-- &1; -- &1; &1],
vector[-- &1; -- &1; -- &1],
vector[&0; -- &1 / &2 + &1 / &2 * sqrt(&5); &1 / &2 + &1 / &2 * sqrt(&5)],
vector[&0; -- &1 / &2 + &1 / &2 * sqrt(&5); -- &1 / &2 + -- &1 / &2 * sqrt(&5)],
vector[&0; &1 / &2 + -- &1 / &2 * sqrt(&5); &1 / &2 + &1 / &2 * sqrt(&5)],
vector[&0; &1 / &2 + -- &1 / &2 * sqrt(&5); -- &1 / &2 + -- &1 / &2 * sqrt(&5)],
vector[-- &1 / &2 + &1 / &2 * sqrt(&5); &1 / &2 + &1 / &2 * sqrt(&5); &0],
vector[-- &1 / &2 + &1 / &2 * sqrt(&5); -- &1 / &2 + -- &1 / &2 * sqrt(&5); &0],
vector[&1 / &2 + -- &1 / &2 * sqrt(&5); &1 / &2 + &1 / &2 * sqrt(&5); &0],
vector[&1 / &2 + -- &1 / &2 * sqrt(&5); -- &1 / &2 + -- &1 / &2 * sqrt(&5); &0],
vector[&1 / &2 + &1 / &2 * sqrt(&5); &0; -- &1 / &2 + &1 / &2 * sqrt(&5)],
vector[-- &1 / &2 + -- &1 / &2 * sqrt(&5); &0; -- &1 / &2 + &1 / &2 * sqrt(&5)],
vector[&1 / &2 + &1 / &2 * sqrt(&5); &0; &1 / &2 + -- &1 / &2 * sqrt(&5)],
vector[-- &1 / &2 + -- &1 / &2 * sqrt(&5); &0; &1 / &2 + -- &1 / &2 * sqrt(&5)]}`,
let golden_inverse = prove
(`inv((&1 + sqrt(&5)) / &2) = -- &1 / &2 + &1 / &2 * sqrt(&5)`,
MP_TAC(ISPEC `&5` SQRT_POW_2) THEN CONV_TAC REAL_FIELD) in
REWRITE_TAC[std_dodecahedron] THEN
CONV_TAC(ONCE_DEPTH_CONV let_CONV) THEN
REWRITE_TAC[golden_inverse] THEN
REWRITE_TAC[REAL_ARITH `(&1 + s) / &2 = &1 / &2 + &1 / &2 * s`] THEN
REWRITE_TAC[REAL_ARITH `--(a + b * sqrt(&5)) = --a + --b * sqrt(&5)`] THEN
CONV_TAC REAL_RAT_REDUCE_CONV THEN REWRITE_TAC[]);;
let STD_ICOSAHEDRON = prove
(`
std_icosahedron =
convex hull
{ vector[&0; &1; &1 / &2 + &1 / &2 * sqrt(&5)],
vector[&0; &1; -- &1 / &2 + -- &1 / &2 * sqrt(&5)],
vector[&0; -- &1; &1 / &2 + &1 / &2 * sqrt(&5)],
vector[&0; -- &1; -- &1 / &2 + -- &1 / &2 * sqrt(&5)],
vector[&1; &1 / &2 + &1 / &2 * sqrt(&5); &0],
vector[&1; -- &1 / &2 + -- &1 / &2 * sqrt(&5); &0],
vector[-- &1; &1 / &2 + &1 / &2 * sqrt(&5); &0],
vector[-- &1; -- &1 / &2 + -- &1 / &2 * sqrt(&5); &0],
vector[&1 / &2 + &1 / &2 * sqrt(&5); &0; &1],
vector[-- &1 / &2 + -- &1 / &2 * sqrt(&5); &0; &1],
vector[&1 / &2 + &1 / &2 * sqrt(&5); &0; -- &1],
vector[-- &1 / &2 + -- &1 / &2 * sqrt(&5); &0; -- &1]}`,
REWRITE_TAC[
std_icosahedron] THEN
CONV_TAC(ONCE_DEPTH_CONV let_CONV) THEN
REWRITE_TAC[REAL_ARITH `(&1 + s) / &2 = &1 / &2 + &1 / &2 * s`] THEN
REWRITE_TAC[REAL_ARITH `--(a + b * sqrt(&5)) = --a + --b * sqrt(&5)`] THEN
CONV_TAC REAL_RAT_REDUCE_CONV THEN REWRITE_TAC[]);;
(* ------------------------------------------------------------------------- *)
(* Explicit computation of facets. *)
(* ------------------------------------------------------------------------- *)
let COMPUTE_FACES_2 = prove
(`!f s:real^3->bool.
FINITE s
==> (f
face_of (convex hull s) /\
aff_dim f = &2 <=>
?x y z. x
IN s /\ y
IN s /\ z
IN s /\
let a = (z - x) cross (y - x) in
~(a = vec 0) /\
let b = a dot x in
((!w. w
IN s ==> a dot w <= b) \/
(!w. w
IN s ==> a dot w >= b)) /\
f = convex hull (s
INTER {x | a dot x = b}))`,
REPEAT GEN_TAC THEN STRIP_TAC THEN EQ_TAC THENL
[STRIP_TAC THEN
SUBGOAL_THEN `?t:real^3->bool. t
SUBSET s /\ f = convex hull t`
MP_TAC THENL
[MATCH_MP_TAC
FACE_OF_CONVEX_HULL_SUBSET THEN
ASM_SIMP_TAC[
FINITE_IMP_COMPACT];
DISCH_THEN(X_CHOOSE_THEN `t:real^3->bool` MP_TAC)] THEN
DISCH_THEN(CONJUNCTS_THEN2 ASSUME_TAC SUBST_ALL_TAC) THEN
RULE_ASSUM_TAC(REWRITE_RULE[
AFF_DIM_CONVEX_HULL]) THEN
MP_TAC(ISPEC `t:real^3->bool`
AFFINE_BASIS_EXISTS) THEN
DISCH_THEN(X_CHOOSE_THEN `u:real^3->bool` STRIP_ASSUME_TAC) THEN
SUBGOAL_THEN `(u:real^3->bool)
HAS_SIZE 3` MP_TAC THENL
[ASM_SIMP_TAC[
HAS_SIZE;
AFFINE_INDEPENDENT_IMP_FINITE] THEN
REWRITE_TAC[GSYM
INT_OF_NUM_EQ] THEN MATCH_MP_TAC(INT_ARITH
`
aff_dim(u:real^3->bool) = &2 /\
aff_dim u = &(
CARD u) - &1
==> &(
CARD u):int = &3`) THEN CONJ_TAC
THENL [ASM_MESON_TAC[
AFF_DIM_AFFINE_HULL]; ASM_MESON_TAC[
AFF_DIM_UNIQUE]];
ALL_TAC] THEN
CONV_TAC(LAND_CONV HAS_SIZE_CONV) THEN SIMP_TAC[
LEFT_IMP_EXISTS_THM] THEN
MAP_EVERY X_GEN_TAC [`x:real^3`; `y:real^3`; `z:real^3`] THEN
REPEAT(DISCH_THEN(CONJUNCTS_THEN2 ASSUME_TAC MP_TAC)) THEN
DISCH_THEN SUBST_ALL_TAC THEN
MAP_EVERY EXISTS_TAC [`x:real^3`; `y:real^3`; `z:real^3`] THEN
REPLICATE_TAC 3 (CONJ_TAC THENL [ASM SET_TAC[]; ALL_TAC]) THEN
REPEAT LET_TAC THEN
SUBGOAL_THEN `~collinear{x:real^3,y,z}` MP_TAC THENL
[ASM_REWRITE_TAC[
COLLINEAR_3_EQ_AFFINE_DEPENDENT]; ALL_TAC] THEN
ONCE_REWRITE_TAC[SET_RULE `{x,y,z} = {z,x,y}`] THEN
ONCE_REWRITE_TAC[
COLLINEAR_3] THEN ASM_REWRITE_TAC[GSYM
CROSS_EQ_0] THEN
DISCH_TAC THEN ASM_REWRITE_TAC[] THEN
SUBGOAL_THEN `(a:real^3) dot y = b /\ (a:real^3) dot z = b`
STRIP_ASSUME_TAC THENL
[MAP_EVERY UNDISCH_TAC
[`(z - x) cross (y - x) = a`; `(a:real^3) dot x = b`] THEN VEC3_TAC;
ALL_TAC] THEN
MP_TAC(ISPECL [`convex hull s:real^3->bool`; `convex hull t:real^3->bool`]
EXPOSED_FACE_OF_POLYHEDRON) THEN
ASM_SIMP_TAC[
POLYHEDRON_CONVEX_HULL;
exposed_face_of] THEN
REWRITE_TAC[
LEFT_IMP_EXISTS_THM] THEN
MAP_EVERY X_GEN_TAC [`a':real^3`; `b':real`] THEN
DISCH_THEN(STRIP_ASSUME_TAC o GSYM) THEN
SUBGOAL_THEN
`
aff_dim(t:real^3->bool)
<=
aff_dim({x:real^3 | a dot x = b}
INTER {x | a' dot x = b'})`
MP_TAC THENL
[GEN_REWRITE_TAC LAND_CONV [GSYM
AFF_DIM_AFFINE_HULL] THEN
FIRST_X_ASSUM(fun th -> GEN_REWRITE_TAC (LAND_CONV o RAND_CONV)
[SYM th]) THEN
REWRITE_TAC[
AFF_DIM_AFFINE_HULL] THEN MATCH_MP_TAC
AFF_DIM_SUBSET THEN
REWRITE_TAC[
SUBSET_INTER] THEN CONJ_TAC THENL
[ASM SET_TAC[];
MATCH_MP_TAC
SUBSET_TRANS THEN EXISTS_TAC `t:real^3->bool` THEN
ASM_REWRITE_TAC[] THEN MATCH_MP_TAC
SUBSET_TRANS THEN
EXISTS_TAC `convex hull t:real^3->bool` THEN
REWRITE_TAC[
HULL_SUBSET] THEN ASM SET_TAC[]];
ALL_TAC] THEN
ASM_SIMP_TAC[
AFF_DIM_AFFINE_INTER_HYPERPLANE;
AFF_DIM_HYPERPLANE;
AFFINE_HYPERPLANE; DIMINDEX_3] THEN
REPEAT(COND_CASES_TAC THEN CONV_TAC INT_REDUCE_CONV) THEN
FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I
[
SUBSET_HYPERPLANES]) THEN
ASM_REWRITE_TAC[
HYPERPLANE_EQ_EMPTY] THEN
DISCH_THEN(DISJ_CASES_THEN2 SUBST_ALL_TAC (MP_TAC o SYM)) THENL
[RULE_ASSUM_TAC(REWRITE_RULE[
INTER_UNIV]) THEN
SUBGOAL_THEN `s
SUBSET {x:real^3 | a dot x = b}` ASSUME_TAC THENL
[MATCH_MP_TAC
SUBSET_TRANS THEN
EXISTS_TAC `convex hull s:real^3->bool` THEN
REWRITE_TAC[
HULL_SUBSET] THEN ASM_REWRITE_TAC[] THEN
MATCH_MP_TAC
SUBSET_TRANS THEN
EXISTS_TAC `affine hull t:real^3->bool` THEN
REWRITE_TAC[
CONVEX_HULL_SUBSET_AFFINE_HULL] THEN
FIRST_X_ASSUM(fun th -> GEN_REWRITE_TAC LAND_CONV [SYM th]) THEN
MATCH_MP_TAC
HULL_MINIMAL THEN REWRITE_TAC[
AFFINE_HYPERPLANE] THEN
ASM SET_TAC[];
ALL_TAC] THEN
CONJ_TAC THENL
[RULE_ASSUM_TAC(REWRITE_RULE[
SUBSET;
IN_ELIM_THM]) THEN
ASM_SIMP_TAC[
real_ge;
REAL_LE_REFL];
ASM_SIMP_TAC[SET_RULE `s
SUBSET t ==> s
INTER t = s`]];
ALL_TAC] THEN
DISCH_THEN(fun th -> SUBST_ALL_TAC th THEN ASSUME_TAC th) THEN
CONJ_TAC THENL
[MATCH_MP_TAC(TAUT `(~p /\ ~q ==> F) ==> p \/ q`) THEN
REWRITE_TAC[
NOT_FORALL_THM; NOT_IMP;
real_ge;
REAL_NOT_LE] THEN
DISCH_THEN(CONJUNCTS_THEN2
(X_CHOOSE_TAC `u:real^3`) (X_CHOOSE_TAC `v:real^3`)) THEN
SUBGOAL_THEN `(a':real^3) dot u < b' /\ a' dot v < b'` ASSUME_TAC THENL
[REWRITE_TAC[
REAL_LT_LE] THEN REWRITE_TAC
[SET_RULE `f x <= b /\ ~(f x = b) <=>
x
IN {x | f x <= b} /\ ~(x
IN {x | f x = b})`] THEN
ASM_REWRITE_TAC[] THEN ASM_SIMP_TAC[
IN_ELIM_THM;
REAL_LT_IMP_NE] THEN
SUBGOAL_THEN `(u:real^3)
IN convex hull s /\ v
IN convex hull s`
MP_TAC THENL [ASM_SIMP_TAC[
HULL_INC]; ASM SET_TAC[]];
ALL_TAC] THEN
SUBGOAL_THEN `?w:real^3. w
IN segment[u,v] /\ w
IN {w | a' dot w = b'}`
MP_TAC THENL
[ASM_REWRITE_TAC[] THEN REWRITE_TAC[
IN_ELIM_THM] THEN
MATCH_MP_TAC
CONNECTED_IVT_HYPERPLANE THEN
MAP_EVERY EXISTS_TAC [`v:real^3`; `u:real^3`] THEN
ASM_SIMP_TAC[
ENDS_IN_SEGMENT;
CONNECTED_SEGMENT;
REAL_LT_IMP_LE];
REWRITE_TAC[
IN_SEGMENT;
IN_ELIM_THM;
LEFT_AND_EXISTS_THM] THEN
ONCE_REWRITE_TAC[
SWAP_EXISTS_THM] THEN
REWRITE_TAC[GSYM
CONJ_ASSOC;
RIGHT_EXISTS_AND_THM] THEN
REWRITE_TAC[
UNWIND_THM2;
DOT_RADD;
DOT_RMUL;
CONJ_ASSOC] THEN
DISCH_THEN(CHOOSE_THEN(CONJUNCTS_THEN2 STRIP_ASSUME_TAC MP_TAC)) THEN
MATCH_MP_TAC(REAL_ARITH `a < b ==> a = b ==> F`) THEN
MATCH_MP_TAC
REAL_CONVEX_BOUND_LT THEN ASM_REAL_ARITH_TAC];
MATCH_MP_TAC
SUBSET_ANTISYM THEN CONJ_TAC THENL
[MATCH_MP_TAC
HULL_MONO THEN REWRITE_TAC[
SUBSET_INTER] THEN
ASM_REWRITE_TAC[] THEN MATCH_MP_TAC
SUBSET_TRANS THEN
EXISTS_TAC `convex hull t:real^3->bool` THEN
REWRITE_TAC[
HULL_SUBSET] THEN ASM SET_TAC[];
FIRST_X_ASSUM(fun th -> GEN_REWRITE_TAC RAND_CONV [SYM th]) THEN
REWRITE_TAC[
SUBSET_INTER] THEN
SIMP_TAC[
HULL_MONO;
INTER_SUBSET] THEN
ASM_REWRITE_TAC[] THEN MATCH_MP_TAC
SUBSET_TRANS THEN
EXISTS_TAC `convex hull {x:real^3 | a dot x = b}` THEN
SIMP_TAC[
HULL_MONO;
INTER_SUBSET] THEN
MATCH_MP_TAC(SET_RULE `s = t ==> s
SUBSET t`) THEN
REWRITE_TAC[
CONVEX_HULL_EQ;
CONVEX_HYPERPLANE]]];
REWRITE_TAC[
LEFT_IMP_EXISTS_THM] THEN
MAP_EVERY X_GEN_TAC [`x:real^3`; `y:real^3`; `z:real^3`] THEN
REPEAT LET_TAC THEN
DISCH_THEN(REPEAT_TCL CONJUNCTS_THEN ASSUME_TAC) THEN CONJ_TAC THENL
[ASM_REWRITE_TAC[] THEN
SUBGOAL_THEN
`convex hull (s
INTER {x:real^3 | a dot x = b}) =
(convex hull s)
INTER {x | a dot x = b}`
SUBST1_TAC THENL
[MATCH_MP_TAC
SUBSET_ANTISYM THEN CONJ_TAC THENL
[SIMP_TAC[
SUBSET_INTER;
HULL_MONO;
INTER_SUBSET] THEN
MATCH_MP_TAC
SUBSET_TRANS THEN
EXISTS_TAC `convex hull {x:real^3 | a dot x = b}` THEN
SIMP_TAC[
HULL_MONO;
INTER_SUBSET] THEN
MATCH_MP_TAC(SET_RULE `s = t ==> s
SUBSET t`) THEN
REWRITE_TAC[
CONVEX_HULL_EQ;
CONVEX_HYPERPLANE];
ALL_TAC] THEN
ASM_CASES_TAC `s
SUBSET {x:real^3 | a dot x = b}` THENL
[ASM_SIMP_TAC[SET_RULE `s
SUBSET t ==> s
INTER t = s`] THEN SET_TAC[];
ALL_TAC] THEN
MATCH_MP_TAC
SUBSET_TRANS THEN EXISTS_TAC
`convex hull (convex hull (s
INTER {x:real^3 | a dot x = b})
UNION
convex hull (s
DIFF {x | a dot x = b}))
INTER
{x | a dot x = b}` THEN
CONJ_TAC THENL
[MATCH_MP_TAC(SET_RULE
`s
SUBSET t ==> (s
INTER u)
SUBSET (t
INTER u)`) THEN
MATCH_MP_TAC
HULL_MONO THEN MATCH_MP_TAC(SET_RULE
`s
INTER t
SUBSET (P hull (s
INTER t)) /\
s
DIFF t
SUBSET (P hull (s
DIFF t))
==> s
SUBSET (P hull (s
INTER t))
UNION (P hull (s
DIFF t))`) THEN
REWRITE_TAC[
HULL_SUBSET];
ALL_TAC] THEN
W(MP_TAC o PART_MATCH (lhs o rand)
CONVEX_HULL_UNION_NONEMPTY_EXPLICIT o
lhand o lhand o snd) THEN
ANTS_TAC THENL
[SIMP_TAC[
CONVEX_CONVEX_HULL;
CONVEX_HULL_EQ_EMPTY] THEN ASM SET_TAC[];
DISCH_THEN SUBST1_TAC] THEN
REWRITE_TAC[
SUBSET;
IN_INTER;
IMP_CONJ;
FORALL_IN_GSPEC] THEN
MAP_EVERY X_GEN_TAC [`p:real^3`; `u:real`; `q:real^3`] THEN
REPLICATE_TAC 4 DISCH_TAC THEN ASM_CASES_TAC `u = &0` THEN
ASM_REWRITE_TAC[VECTOR_ARITH `(&1 - &0) % p + &0 % q:real^N = p`] THEN
MATCH_MP_TAC(TAUT `~p ==> p ==> q`) THEN REWRITE_TAC[
IN_ELIM_THM] THEN
REWRITE_TAC[
DOT_RADD;
DOT_RMUL] THEN FIRST_X_ASSUM DISJ_CASES_TAC THENL
[MATCH_MP_TAC(REAL_ARITH `x < y ==> ~(x = y)`) THEN
MATCH_MP_TAC(REAL_ARITH
`(&1 - u) * p = (&1 - u) * b /\ u * q < u * b
==> (&1 - u) * p + u * q < b`) THEN
CONJ_TAC THENL
[SUBGOAL_THEN `p
IN {x:real^3 | a dot x = b}` MP_TAC THENL
[FIRST_X_ASSUM(MATCH_MP_TAC o MATCH_MP (SET_RULE
`x
IN s ==> s
SUBSET t ==> x
IN t`)) THEN
MATCH_MP_TAC
HULL_MINIMAL THEN REWRITE_TAC[
CONVEX_HYPERPLANE] THEN
SET_TAC[];
SIMP_TAC[
IN_ELIM_THM]];
MATCH_MP_TAC
REAL_LT_LMUL THEN CONJ_TAC THENL
[ASM_REAL_ARITH_TAC; ALL_TAC] THEN
ONCE_REWRITE_TAC[SET_RULE
`(a:real^3) dot q < b <=> q
IN {x | a dot x < b}`] THEN
FIRST_X_ASSUM(MATCH_MP_TAC o MATCH_MP (SET_RULE
`x
IN s ==> s
SUBSET t ==> x
IN t`)) THEN
MATCH_MP_TAC
HULL_MINIMAL THEN REWRITE_TAC[
CONVEX_HALFSPACE_LT] THEN
ASM_SIMP_TAC[
SUBSET;
IN_DIFF;
IN_ELIM_THM;
REAL_LT_LE]];
MATCH_MP_TAC(REAL_ARITH `x > y ==> ~(x = y)`) THEN
MATCH_MP_TAC(REAL_ARITH
`(&1 - u) * p = (&1 - u) * b /\ u * b < u * q
==> (&1 - u) * p + u * q > b`) THEN
CONJ_TAC THENL
[SUBGOAL_THEN `p
IN {x:real^3 | a dot x = b}` MP_TAC THENL
[FIRST_X_ASSUM(MATCH_MP_TAC o MATCH_MP (SET_RULE
`x
IN s ==> s
SUBSET t ==> x
IN t`)) THEN
MATCH_MP_TAC
HULL_MINIMAL THEN REWRITE_TAC[
CONVEX_HYPERPLANE] THEN
SET_TAC[];
SIMP_TAC[
IN_ELIM_THM]];
MATCH_MP_TAC
REAL_LT_LMUL THEN CONJ_TAC THENL
[ASM_REAL_ARITH_TAC; REWRITE_TAC[GSYM
real_gt]] THEN
ONCE_REWRITE_TAC[SET_RULE
`(a:real^3) dot q > b <=> q
IN {x | a dot x > b}`] THEN
FIRST_X_ASSUM(MATCH_MP_TAC o MATCH_MP (SET_RULE
`x
IN s ==> s
SUBSET t ==> x
IN t`)) THEN
MATCH_MP_TAC
HULL_MINIMAL THEN REWRITE_TAC[
CONVEX_HALFSPACE_GT] THEN
RULE_ASSUM_TAC(REWRITE_RULE[
real_ge]) THEN
ASM_SIMP_TAC[
SUBSET;
IN_DIFF;
IN_ELIM_THM;
real_gt;
REAL_LT_LE]]];
ALL_TAC] THEN
FIRST_X_ASSUM DISJ_CASES_TAC THENL
[MATCH_MP_TAC
FACE_OF_INTER_SUPPORTING_HYPERPLANE_LE THEN
REWRITE_TAC[
CONVEX_CONVEX_HULL] THEN
SIMP_TAC[SET_RULE `(!x. x
IN s ==> P x) <=> s
SUBSET {x | P x}`] THEN
MATCH_MP_TAC
HULL_MINIMAL THEN REWRITE_TAC[
CONVEX_HALFSPACE_LE] THEN
ASM_SIMP_TAC[
SUBSET;
IN_ELIM_THM];
MATCH_MP_TAC
FACE_OF_INTER_SUPPORTING_HYPERPLANE_GE THEN
REWRITE_TAC[
CONVEX_CONVEX_HULL] THEN
SIMP_TAC[SET_RULE `(!x. x
IN s ==> P x) <=> s
SUBSET {x | P x}`] THEN
MATCH_MP_TAC
HULL_MINIMAL THEN REWRITE_TAC[
CONVEX_HALFSPACE_GE] THEN
ASM_SIMP_TAC[
SUBSET;
IN_ELIM_THM]];
REWRITE_TAC[GSYM
INT_LE_ANTISYM] THEN CONJ_TAC THENL
[MATCH_MP_TAC
INT_LE_TRANS THEN
EXISTS_TAC `
aff_dim {x:real^3 | a dot x = b}` THEN CONJ_TAC THENL
[MATCH_MP_TAC
AFF_DIM_SUBSET THEN ASM_REWRITE_TAC[] THEN
MATCH_MP_TAC
HULL_MINIMAL THEN REWRITE_TAC[
CONVEX_HYPERPLANE] THEN
SET_TAC[];
ASM_SIMP_TAC[
AFF_DIM_HYPERPLANE; DIMINDEX_3] THEN INT_ARITH_TAC];
MATCH_MP_TAC
INT_LE_TRANS THEN EXISTS_TAC `
aff_dim {x:real^3,y,z}` THEN
CONJ_TAC THENL
[SUBGOAL_THEN `~collinear{x:real^3,y,z}` MP_TAC THENL
[ONCE_REWRITE_TAC[SET_RULE `{x,y,z} = {z,x,y}`] THEN
ONCE_REWRITE_TAC[
COLLINEAR_3] THEN
ASM_REWRITE_TAC[GSYM
CROSS_EQ_0];
REWRITE_TAC[
COLLINEAR_3_EQ_AFFINE_DEPENDENT; DE_MORGAN_THM] THEN
STRIP_TAC] THEN
ASM_SIMP_TAC[
AFF_DIM_AFFINE_INDEPENDENT] THEN
SIMP_TAC[
CARD_CLAUSES;
FINITE_INSERT;
FINITE_EMPTY] THEN
ASM_REWRITE_TAC[
IN_INSERT;
NOT_IN_EMPTY; ARITH] THEN
CONV_TAC INT_REDUCE_CONV;
MATCH_MP_TAC
AFF_DIM_SUBSET THEN ASM_REWRITE_TAC[
INSERT_SUBSET] THEN
REWRITE_TAC[
EMPTY_SUBSET] THEN REPEAT CONJ_TAC THEN
MATCH_MP_TAC
HULL_INC THEN
ASM_REWRITE_TAC[
IN_INTER;
IN_ELIM_THM] THEN
MAP_EVERY UNDISCH_TAC
[`(z - x) cross (y - x) = a`; `(a:real^3) dot x = b`] THEN
VEC3_TAC]]]]);;
let COMPUTE_FACES_2_STEP_1 = prove
(`!f v s t:real^3->bool.
(?x y z. x
IN (v
INSERT s) /\ y
IN (v
INSERT s) /\ z
IN (v
INSERT s) /\
let a = (z - x) cross (y - x) in
~(a = vec 0) /\
let b = a dot x in
((!w. w
IN t ==> a dot w <= b) \/
(!w. w
IN t ==> a dot w >= b)) /\
f = convex hull (t
INTER {x | a dot x = b})) <=>
(?y z. y
IN s /\ z
IN s /\
let a = (z - v) cross (y - v) in
~(a = vec 0) /\
let b = a dot v in
((!w. w
IN t ==> a dot w <= b) \/
(!w. w
IN t ==> a dot w >= b)) /\
f = convex hull (t
INTER {x | a dot x = b})) \/
(?x y z. x
IN s /\ y
IN s /\ z
IN s /\
let a = (z - x) cross (y - x) in
~(a = vec 0) /\
let b = a dot x in
((!w. w
IN t ==> a dot w <= b) \/
(!w. w
IN t ==> a dot w >= b)) /\
f = convex hull (t
INTER {x | a dot x = b}))`,
REPEAT GEN_TAC THEN REWRITE_TAC[
IN_INSERT] THEN MATCH_MP_TAC(MESON[]
`(!x y z. Q x y z ==> Q x z y) /\
(!x y z. Q x y z ==> Q y x z) /\
(!x z. ~(Q x x z))
==> ((?x y z. (x = v \/ P x) /\ (y = v \/ P y) /\ (z = v \/ P z) /\
Q x y z) <=>
(?y z. P y /\ P z /\ Q v y z) \/
(?x y z. P x /\ P y /\ P z /\ Q x y z))`) THEN
CONV_TAC(ONCE_DEPTH_CONV let_CONV) THEN
REWRITE_TAC[
VECTOR_SUB_REFL;
CROSS_0] THEN
CONJ_TAC THEN REPEAT GEN_TAC THEN
CONV_TAC(ONCE_DEPTH_CONV let_CONV) THEN
MAP_EVERY (SUBST1_TAC o VEC3_RULE)
[`(z - y) cross (x - y) = --((z - x) cross (y - x))`;
`(y - x) cross (z - x) = --((z - x) cross (y - x))`] THEN
REWRITE_TAC[
VECTOR_NEG_EQ_0;
DOT_LNEG;
REAL_EQ_NEG2;
REAL_LE_NEG2;
real_ge] THEN
REWRITE_TAC[
DISJ_ACI] THEN
REWRITE_TAC[VEC3_RULE
`((z - x) cross (y - x)) dot y = ((z - x) cross (y - x)) dot x`]);;
let COMPUTE_FACES_2_STEP_2 = prove
(`!f u v s:real^3->bool.
(?y z. y
IN (u
INSERT s) /\ z
IN (u
INSERT s) /\
let a = (z - v) cross (y - v) in
~(a = vec 0) /\
let b = a dot v in
((!w. w
IN t ==> a dot w <= b) \/
(!w. w
IN t ==> a dot w >= b)) /\
f = convex hull (t
INTER {x | a dot x = b})) <=>
(?z. z
IN s /\
let a = (z - v) cross (u - v) in
~(a = vec 0) /\
let b = a dot v in
((!w. w
IN t ==> a dot w <= b) \/
(!w. w
IN t ==> a dot w >= b)) /\
f = convex hull (t
INTER {x | a dot x = b})) \/
(?y z. y
IN s /\ z
IN s /\
let a = (z - v) cross (y - v) in
~(a = vec 0) /\
let b = a dot v in
((!w. w
IN t ==> a dot w <= b) \/
(!w. w
IN t ==> a dot w >= b)) /\
f = convex hull (t
INTER {x | a dot x = b}))`,
REPEAT GEN_TAC THEN REWRITE_TAC[
IN_INSERT] THEN MATCH_MP_TAC(MESON[]
`(!x y. Q x y ==> Q y x) /\
(!x. ~(Q x x))
==> ((?y z. (y = u \/ P y) /\ (z = u \/ P z) /\
Q y z) <=>
(?z. P z /\ Q u z) \/
(?y z. P y /\ P z /\ Q y z))`) THEN
CONV_TAC(ONCE_DEPTH_CONV let_CONV) THEN
REWRITE_TAC[
CROSS_REFL] THEN REPEAT GEN_TAC THEN
CONV_TAC(ONCE_DEPTH_CONV let_CONV) THEN SUBST1_TAC
(VEC3_RULE `(x - v) cross (y - v) = --((y - v) cross (x - v))`) THEN
REWRITE_TAC[
VECTOR_NEG_EQ_0;
DOT_LNEG;
REAL_EQ_NEG2;
REAL_LE_NEG2;
real_ge] THEN REWRITE_TAC[
DISJ_ACI]);;
let COMPUTE_FACES_TAC =
(* ------------------------------------------------------------------------- *)
(* Apply this to our standard Platonic solids to derive facets. *)
(* Note: this is quite slow and can take a couple of hours. *)
(* ------------------------------------------------------------------------- *)
let TETRAHEDRON_FACETS = time prove
(`!f:real^3->bool.
f face_of std_tetrahedron /\ aff_dim f = &2 <=>
f = convex hull {vector[-- &1; -- &1; &1], vector[-- &1; &1; -- &1], vector[&1; -- &1; -- &1]} \/
f = convex hull {vector[-- &1; -- &1; &1], vector[-- &1; &1; -- &1], vector[&1; &1; &1]} \/
f = convex hull {vector[-- &1; -- &1; &1], vector[&1; -- &1; -- &1], vector[&1; &1; &1]} \/
f = convex hull {vector[-- &1; &1; -- &1], vector[&1; -- &1; -- &1], vector[&1; &1; &1]}`,
GEN_TAC THEN REWRITE_TAC[std_tetrahedron] THEN COMPUTE_FACES_TAC);;
let CUBE_FACETS = time prove
(`!f:real^3->bool.
f face_of std_cube /\ aff_dim f = &2 <=>
f = convex hull {vector[-- &1; -- &1; -- &1], vector[-- &1; -- &1; &1], vector[-- &1; &1; -- &1], vector[-- &1; &1; &1]} \/
f = convex hull {vector[-- &1; -- &1; -- &1], vector[-- &1; -- &1; &1], vector[&1; -- &1; -- &1], vector[&1; -- &1; &1]} \/
f = convex hull {vector[-- &1; -- &1; -- &1], vector[-- &1; &1; -- &1], vector[&1; -- &1; -- &1], vector[&1; &1; -- &1]} \/
f = convex hull {vector[-- &1; -- &1; &1], vector[-- &1; &1; &1], vector[&1; -- &1; &1], vector[&1; &1; &1]} \/
f = convex hull {vector[-- &1; &1; -- &1], vector[-- &1; &1; &1], vector[&1; &1; -- &1], vector[&1; &1; &1]} \/
f = convex hull {vector[&1; -- &1; -- &1], vector[&1; -- &1; &1], vector[&1; &1; -- &1], vector[&1; &1; &1]}`,
GEN_TAC THEN REWRITE_TAC[std_cube] THEN COMPUTE_FACES_TAC);;
let OCTAHEDRON_FACETS = time prove
(`!f:real^3->bool.
f face_of std_octahedron /\ aff_dim f = &2 <=>
f = convex hull {vector[-- &1; &0; &0], vector[&0; -- &1; &0], vector[&0; &0; -- &1]} \/
f = convex hull {vector[-- &1; &0; &0], vector[&0; -- &1; &0], vector[&0; &0; &1]} \/
f = convex hull {vector[-- &1; &0; &0], vector[&0; &1; &0], vector[&0; &0; -- &1]} \/
f = convex hull {vector[-- &1; &0; &0], vector[&0; &1; &0], vector[&0; &0; &1]} \/
f = convex hull {vector[&1; &0; &0], vector[&0; -- &1; &0], vector[&0; &0; -- &1]} \/
f = convex hull {vector[&1; &0; &0], vector[&0; -- &1; &0], vector[&0; &0; &1]} \/
f = convex hull {vector[&1; &0; &0], vector[&0; &1; &0], vector[&0; &0; -- &1]} \/
f = convex hull {vector[&1; &0; &0], vector[&0; &1; &0], vector[&0; &0; &1]}`,
GEN_TAC THEN REWRITE_TAC[std_octahedron] THEN COMPUTE_FACES_TAC);;
let ICOSAHEDRON_FACETS = time prove
(`!f:real^3->bool.
f face_of std_icosahedron /\ aff_dim f = &2 <=>
f = convex hull {vector[-- &1 / &2 + -- &1 / &2 * sqrt(&5); &0; -- &1], vector[-- &1 / &2 + -- &1 / &2 * sqrt(&5); &0; &1], vector[-- &1; -- &1 / &2 + -- &1 / &2 * sqrt(&5); &0]} \/
f = convex hull {vector[-- &1 / &2 + -- &1 / &2 * sqrt(&5); &0; -- &1], vector[-- &1 / &2 + -- &1 / &2 * sqrt(&5); &0; &1], vector[-- &1; &1 / &2 + &1 / &2 * sqrt(&5); &0]} \/
f = convex hull {vector[-- &1 / &2 + -- &1 / &2 * sqrt(&5); &0; -- &1], vector[-- &1; -- &1 / &2 + -- &1 / &2 * sqrt(&5); &0], vector[&0; -- &1; -- &1 / &2 + -- &1 / &2 * sqrt(&5)]} \/
f = convex hull {vector[-- &1 / &2 + -- &1 / &2 * sqrt(&5); &0; -- &1], vector[-- &1; &1 / &2 + &1 / &2 * sqrt(&5); &0], vector[&0; &1; -- &1 / &2 + -- &1 / &2 * sqrt(&5)]} \/
f = convex hull {vector[-- &1 / &2 + -- &1 / &2 * sqrt(&5); &0; -- &1], vector[&0; -- &1; -- &1 / &2 + -- &1 / &2 * sqrt(&5)], vector[&0; &1; -- &1 / &2 + -- &1 / &2 * sqrt(&5)]} \/
f = convex hull {vector[-- &1 / &2 + -- &1 / &2 * sqrt(&5); &0; &1], vector[-- &1; -- &1 / &2 + -- &1 / &2 * sqrt(&5); &0], vector[&0; -- &1; &1 / &2 + &1 / &2 * sqrt(&5)]} \/
f = convex hull {vector[-- &1 / &2 + -- &1 / &2 * sqrt(&5); &0; &1], vector[-- &1; &1 / &2 + &1 / &2 * sqrt(&5); &0], vector[&0; &1; &1 / &2 + &1 / &2 * sqrt(&5)]} \/
f = convex hull {vector[-- &1 / &2 + -- &1 / &2 * sqrt(&5); &0; &1], vector[&0; -- &1; &1 / &2 + &1 / &2 * sqrt(&5)], vector[&0; &1; &1 / &2 + &1 / &2 * sqrt(&5)]} \/
f = convex hull {vector[&1 / &2 + &1 / &2 * sqrt(&5); &0; -- &1], vector[&1 / &2 + &1 / &2 * sqrt(&5); &0; &1], vector[&1; -- &1 / &2 + -- &1 / &2 * sqrt(&5); &0]} \/
f = convex hull {vector[&1 / &2 + &1 / &2 * sqrt(&5); &0; -- &1], vector[&1 / &2 + &1 / &2 * sqrt(&5); &0; &1], vector[&1; &1 / &2 + &1 / &2 * sqrt(&5); &0]} \/
f = convex hull {vector[&1 / &2 + &1 / &2 * sqrt(&5); &0; -- &1], vector[&1; -- &1 / &2 + -- &1 / &2 * sqrt(&5); &0], vector[&0; -- &1; -- &1 / &2 + -- &1 / &2 * sqrt(&5)]} \/
f = convex hull {vector[&1 / &2 + &1 / &2 * sqrt(&5); &0; -- &1], vector[&1; &1 / &2 + &1 / &2 * sqrt(&5); &0], vector[&0; &1; -- &1 / &2 + -- &1 / &2 * sqrt(&5)]} \/
f = convex hull {vector[&1 / &2 + &1 / &2 * sqrt(&5); &0; -- &1], vector[&0; -- &1; -- &1 / &2 + -- &1 / &2 * sqrt(&5)], vector[&0; &1; -- &1 / &2 + -- &1 / &2 * sqrt(&5)]} \/
f = convex hull {vector[&1 / &2 + &1 / &2 * sqrt(&5); &0; &1], vector[&1; -- &1 / &2 + -- &1 / &2 * sqrt(&5); &0], vector[&0; -- &1; &1 / &2 + &1 / &2 * sqrt(&5)]} \/
f = convex hull {vector[&1 / &2 + &1 / &2 * sqrt(&5); &0; &1], vector[&1; &1 / &2 + &1 / &2 * sqrt(&5); &0], vector[&0; &1; &1 / &2 + &1 / &2 * sqrt(&5)]} \/
f = convex hull {vector[&1 / &2 + &1 / &2 * sqrt(&5); &0; &1], vector[&0; -- &1; &1 / &2 + &1 / &2 * sqrt(&5)], vector[&0; &1; &1 / &2 + &1 / &2 * sqrt(&5)]} \/
f = convex hull {vector[-- &1; -- &1 / &2 + -- &1 / &2 * sqrt(&5); &0], vector[&1; -- &1 / &2 + -- &1 / &2 * sqrt(&5); &0], vector[&0; -- &1; -- &1 / &2 + -- &1 / &2 * sqrt(&5)]} \/
f = convex hull {vector[-- &1; -- &1 / &2 + -- &1 / &2 * sqrt(&5); &0], vector[&1; -- &1 / &2 + -- &1 / &2 * sqrt(&5); &0], vector[&0; -- &1; &1 / &2 + &1 / &2 * sqrt(&5)]} \/
f = convex hull {vector[-- &1; &1 / &2 + &1 / &2 * sqrt(&5); &0], vector[&1; &1 / &2 + &1 / &2 * sqrt(&5); &0], vector[&0; &1; -- &1 / &2 + -- &1 / &2 * sqrt(&5)]} \/
f = convex hull {vector[-- &1; &1 / &2 + &1 / &2 * sqrt(&5); &0], vector[&1; &1 / &2 + &1 / &2 * sqrt(&5); &0], vector[&0; &1; &1 / &2 + &1 / &2 * sqrt(&5)]}`,
GEN_TAC THEN REWRITE_TAC[STD_ICOSAHEDRON] THEN COMPUTE_FACES_TAC);;
let DODECAHEDRON_FACETS = time prove
(`!f:real^3->bool.
f face_of std_dodecahedron /\ aff_dim f = &2 <=>
f = convex hull {vector[-- &1 / &2 + -- &1 / &2 * sqrt(&5); &0; -- &1 / &2 + &1 / &2 * sqrt(&5)], vector[-- &1 / &2 + -- &1 / &2 * sqrt(&5); &0; &1 / &2 + -- &1 / &2 * sqrt(&5)], vector[&1 / &2 + -- &1 / &2 * sqrt(&5); -- &1 / &2 + -- &1 / &2 * sqrt(&5); &0], vector[-- &1; -- &1; -- &1], vector[-- &1; -- &1; &1]} \/
f = convex hull {vector[-- &1 / &2 + -- &1 / &2 * sqrt(&5); &0; -- &1 / &2 + &1 / &2 * sqrt(&5)], vector[-- &1 / &2 + -- &1 / &2 * sqrt(&5); &0; &1 / &2 + -- &1 / &2 * sqrt(&5)], vector[&1 / &2 + -- &1 / &2 * sqrt(&5); &1 / &2 + &1 / &2 * sqrt(&5); &0], vector[-- &1; &1; -- &1], vector[-- &1; &1; &1]} \/
f = convex hull {vector[-- &1 / &2 + -- &1 / &2 * sqrt(&5); &0; -- &1 / &2 + &1 / &2 * sqrt(&5)], vector[-- &1; -- &1; &1], vector[-- &1; &1; &1], vector[&0; -- &1 / &2 + &1 / &2 * sqrt(&5); &1 / &2 + &1 / &2 * sqrt(&5)], vector[&0; &1 / &2 + -- &1 / &2 * sqrt(&5); &1 / &2 + &1 / &2 * sqrt(&5)]} \/
f = convex hull {vector[-- &1 / &2 + -- &1 / &2 * sqrt(&5); &0; &1 / &2 + -- &1 / &2 * sqrt(&5)], vector[-- &1; -- &1; -- &1], vector[-- &1; &1; -- &1], vector[&0; -- &1 / &2 + &1 / &2 * sqrt(&5); -- &1 / &2 + -- &1 / &2 * sqrt(&5)], vector[&0; &1 / &2 + -- &1 / &2 * sqrt(&5); -- &1 / &2 + -- &1 / &2 * sqrt(&5)]} \/
f = convex hull {vector[-- &1 / &2 + &1 / &2 * sqrt(&5); -- &1 / &2 + -- &1 / &2 * sqrt(&5); &0], vector[&1 / &2 + -- &1 / &2 * sqrt(&5); -- &1 / &2 + -- &1 / &2 * sqrt(&5); &0], vector[-- &1; -- &1; -- &1], vector[&1; -- &1; -- &1], vector[&0; &1 / &2 + -- &1 / &2 * sqrt(&5); -- &1 / &2 + -- &1 / &2 * sqrt(&5)]} \/
f = convex hull {vector[-- &1 / &2 + &1 / &2 * sqrt(&5); -- &1 / &2 + -- &1 / &2 * sqrt(&5); &0], vector[&1 / &2 + -- &1 / &2 * sqrt(&5); -- &1 / &2 + -- &1 / &2 * sqrt(&5); &0], vector[-- &1; -- &1; &1], vector[&1; -- &1; &1], vector[&0; &1 / &2 + -- &1 / &2 * sqrt(&5); &1 / &2 + &1 / &2 * sqrt(&5)]} \/
f = convex hull {vector[-- &1 / &2 + &1 / &2 * sqrt(&5); -- &1 / &2 + -- &1 / &2 * sqrt(&5); &0], vector[&1 / &2 + &1 / &2 * sqrt(&5); &0; -- &1 / &2 + &1 / &2 * sqrt(&5)], vector[&1 / &2 + &1 / &2 * sqrt(&5); &0; &1 / &2 + -- &1 / &2 * sqrt(&5)], vector[&1; -- &1; -- &1], vector[&1; -- &1; &1]} \/
f = convex hull {vector[-- &1 / &2 + &1 / &2 * sqrt(&5); &1 / &2 + &1 / &2 * sqrt(&5); &0], vector[&1 / &2 + -- &1 / &2 * sqrt(&5); &1 / &2 + &1 / &2 * sqrt(&5); &0], vector[-- &1; &1; -- &1], vector[&1; &1; -- &1], vector[&0; -- &1 / &2 + &1 / &2 * sqrt(&5); -- &1 / &2 + -- &1 / &2 * sqrt(&5)]} \/
f = convex hull {vector[-- &1 / &2 + &1 / &2 * sqrt(&5); &1 / &2 + &1 / &2 * sqrt(&5); &0], vector[&1 / &2 + -- &1 / &2 * sqrt(&5); &1 / &2 + &1 / &2 * sqrt(&5); &0], vector[-- &1; &1; &1], vector[&1; &1; &1], vector[&0; -- &1 / &2 + &1 / &2 * sqrt(&5); &1 / &2 + &1 / &2 * sqrt(&5)]} \/
f = convex hull {vector[-- &1 / &2 + &1 / &2 * sqrt(&5); &1 / &2 + &1 / &2 * sqrt(&5); &0], vector[&1 / &2 + &1 / &2 * sqrt(&5); &0; -- &1 / &2 + &1 / &2 * sqrt(&5)], vector[&1 / &2 + &1 / &2 * sqrt(&5); &0; &1 / &2 + -- &1 / &2 * sqrt(&5)], vector[&1; &1; -- &1], vector[&1; &1; &1]} \/
f = convex hull {vector[&1 / &2 + &1 / &2 * sqrt(&5); &0; -- &1 / &2 + &1 / &2 * sqrt(&5)], vector[&1; -- &1; &1], vector[&1; &1; &1], vector[&0; -- &1 / &2 + &1 / &2 * sqrt(&5); &1 / &2 + &1 / &2 * sqrt(&5)], vector[&0; &1 / &2 + -- &1 / &2 * sqrt(&5); &1 / &2 + &1 / &2 * sqrt(&5)]} \/
f = convex hull {vector[&1 / &2 + &1 / &2 * sqrt(&5); &0; &1 / &2 + -- &1 / &2 * sqrt(&5)], vector[&1; -- &1; -- &1], vector[&1; &1; -- &1], vector[&0; -- &1 / &2 + &1 / &2 * sqrt(&5); -- &1 / &2 + -- &1 / &2 * sqrt(&5)], vector[&0; &1 / &2 + -- &1 / &2 * sqrt(&5); -- &1 / &2 + -- &1 / &2 * sqrt(&5)]}`,
GEN_TAC THEN REWRITE_TAC[STD_DODECAHEDRON] THEN COMPUTE_FACES_TAC);;
(* ------------------------------------------------------------------------- *)
(* Given a coplanar set, return a hyperplane containing it. *)
(* Maps term s to theorem |- !x. x IN s ==> n dot x = d *)
(* Currently assumes |s| >= 3 but it would be trivial to do other cases. *)
(* ------------------------------------------------------------------------- *)
let COPLANAR_HYPERPLANE_RULE =
let rec allsets m l =
if m = 0 then [[]] else
match l with
[] -> []
| h::t -> map (fun g -> h::g) (allsets (m - 1) t) @ allsets m t in
let mk_sub = mk_binop `(-):real^3->real^3->real^3`
and mk_cross = mk_binop `cross`
and mk_dot = mk_binop `(dot):real^3->real^3->real`
and zerovec_tm = `vector[&0;&0;&0]:real^3`
and template = `(!x:real^3. x IN s ==> n dot x = d)`
and s_tm = `s:real^3->bool`
and n_tm = `n:real^3`
and d_tm = `d:real` in
let mk_normal [x;y;z] = mk_cross (mk_sub y x) (mk_sub z x) in
let eval_normal t =
(BINOP_CONV VECTOR3_SUB_CONV THENC VECTOR3_CROSS_CONV) (mk_normal t) in
let check_normal t =
let th = eval_normal t in
let n = rand(concl th) in
if n = zerovec_tm then failwith "check_normal" else n in
fun tm ->
let s = dest_setenum tm in
if length s < 3 then failwith "COPLANAR_HYPERPLANE_RULE: trivial" else
let n = tryfind check_normal (allsets 3 s) in
let d = rand(concl(VECTOR3_DOT_CONV(mk_dot n (hd s)))) in
let ptm = vsubst [tm,s_tm; n,n_tm; d,d_tm] template in
EQT_ELIM
((REWRITE_CONV[FORALL_IN_INSERT; NOT_IN_EMPTY] THENC
DEPTH_BINOP_CONV `/\`
(LAND_CONV VECTOR3_DOT_CONV THENC REAL_RAT5_EQ_CONV) THENC
GEN_REWRITE_CONV DEPTH_CONV [AND_CLAUSES]) ptm);;
(* ------------------------------------------------------------------------- *)
(* Explicit computation of edges, assuming hyperplane containing the set. *)
(* ------------------------------------------------------------------------- *)
let COMPUTE_FACES_1 = prove
(`!s:real^3->bool n d.
(!x. x
IN s ==> n dot x = d)
==>
FINITE s /\ ~(n = vec 0)
==> !f. f
face_of (convex hull s) /\
aff_dim f = &1 <=>
?x y. x
IN s /\ y
IN s /\
let a = n cross (y - x) in
~(a = vec 0) /\
let b = a dot x in
((!w. w
IN s ==> a dot w <= b) \/
(!w. w
IN s ==> a dot w >= b)) /\
f = convex hull (s
INTER {x | a dot x = b})`,
(* ------------------------------------------------------------------------- *)
(* Given a coplanar set, return exhaustive edge case theorem. *)
(* ------------------------------------------------------------------------- *)
let COMPUTE_EDGES_CONV =
let lemma = prove
(`(x
INSERT s)
INTER {x | P x} =
if P x then x
INSERT (s
INTER {x | P x})
else s
INTER {x | P x}`,
COND_CASES_TAC THEN ASM SET_TAC[]) in
fun tm ->
let th1 = MATCH_MP
COMPUTE_FACES_1 (COPLANAR_HYPERPLANE_RULE tm) in
let th2 = MP (CONV_RULE(LAND_CONV
(COMB2_CONV (RAND_CONV(PURE_REWRITE_CONV[
FINITE_INSERT;
FINITE_EMPTY]))
(RAND_CONV VECTOR3_EQ_0_CONV THENC
GEN_REWRITE_CONV I [NOT_CLAUSES]) THENC
GEN_REWRITE_CONV I [
AND_CLAUSES])) th1) TRUTH in
CONV_RULE
(BINDER_CONV(RAND_CONV
(REWRITE_CONV[
RIGHT_EXISTS_AND_THM] THENC
REWRITE_CONV[
EXISTS_IN_INSERT;
NOT_IN_EMPTY] THENC
REWRITE_CONV[
FORALL_IN_INSERT;
NOT_IN_EMPTY] THENC
ONCE_DEPTH_CONV VECTOR3_SUB_CONV THENC
ONCE_DEPTH_CONV VECTOR3_CROSS_CONV THENC
ONCE_DEPTH_CONV let_CONV THENC
ONCE_DEPTH_CONV VECTOR3_EQ_0_CONV THENC
REWRITE_CONV[
real_ge] THENC
ONCE_DEPTH_CONV VECTOR3_DOT_CONV THENC
ONCE_DEPTH_CONV let_CONV THENC
ONCE_DEPTH_CONV REAL_RAT5_LE_CONV THENC
REWRITE_CONV[
INSERT_AC] THENC REWRITE_CONV[
DISJ_ACI] THENC
REPEATC(CHANGED_CONV
(ONCE_REWRITE_CONV[lemma] THENC
ONCE_DEPTH_CONV(LAND_CONV VECTOR3_DOT_CONV THENC
REAL_RAT5_EQ_CONV) THENC
REWRITE_CONV[])) THENC
REWRITE_CONV[
INTER_EMPTY] THENC
REWRITE_CONV[
INSERT_AC] THENC REWRITE_CONV[
DISJ_ACI]
))) th2;;
(* ------------------------------------------------------------------------- *)
(* Use this to prove the number of edges per face for each Platonic solid. *)
(* ------------------------------------------------------------------------- *)
let EDGES_PER_FACE_TAC th =
REPEAT STRIP_TAC THEN MATCH_MP_TAC EQ_TRANS THEN
EXISTS_TAC `CARD {e:real^3->bool | e face_of f /\ aff_dim(e) = &1}` THEN
CONJ_TAC THENL
[AP_TERM_TAC THEN GEN_REWRITE_TAC I [EXTENSION] THEN
REWRITE_TAC[IN_ELIM_THM] THEN
ASM_MESON_TAC[FACE_OF_FACE; FACE_OF_TRANS; FACE_OF_IMP_SUBSET];
ALL_TAC] THEN
MP_TAC(ISPEC `f:real^3->bool` th) THEN ASM_REWRITE_TAC[] THEN
DISCH_THEN(REPEAT_TCL DISJ_CASES_THEN SUBST1_TAC) THEN
W(fun (_,w) -> REWRITE_TAC[COMPUTE_EDGES_CONV(find_term is_setenum w)]) THEN
REWRITE_TAC[SET_RULE `x = a \/ x = b <=> x IN {a,b}`] THEN
REWRITE_TAC[GSYM IN_INSERT; SET_RULE `{x | x IN s} = s`] THEN
REWRITE_TAC[GSYM SEGMENT_CONVEX_HULL] THEN MATCH_MP_TAC
(MESON[HAS_SIZE] `s HAS_SIZE n ==> CARD s = n`) THEN
REPEAT
(MATCH_MP_TAC CARD_EQ_LEMMA THEN REPEAT CONJ_TAC THENL
[CONV_TAC NUM_REDUCE_CONV THEN NO_TAC;
REWRITE_TAC[IN_INSERT; NOT_IN_EMPTY; SEGMENT_EQ; DE_MORGAN_THM] THEN
REPEAT CONJ_TAC THEN MATCH_MP_TAC(SET_RULE
`~(a = c /\ b = d) /\ ~(a = d /\ b = c) /\ ~(a = b /\ c = d)
==> ~({a,b} = {c,d})`) THEN
PURE_ONCE_REWRITE_TAC[GSYM VECTOR_SUB_EQ] THEN
CONV_TAC(ONCE_DEPTH_CONV VECTOR3_SUB_CONV) THEN
CONV_TAC(ONCE_DEPTH_CONV VECTOR3_EQ_0_CONV) THEN
REWRITE_TAC[] THEN NO_TAC;
ALL_TAC]) THEN
CONV_TAC NUM_REDUCE_CONV THEN REWRITE_TAC[CONJUNCT1 HAS_SIZE_CLAUSES];;
(* ------------------------------------------------------------------------- *)
(* Show that the Platonic solids are all full-dimensional. *)
(* ------------------------------------------------------------------------- *)
let POLYTOPE_FULLDIM_TAC =
MATCH_MP_TAC POLYTOPE_3D_LEMMA THEN
CONV_TAC(ONCE_DEPTH_CONV VECTOR3_SUB_CONV) THEN
CONV_TAC(ONCE_DEPTH_CONV VECTOR3_CROSS_CONV) THEN
CONV_TAC(ONCE_DEPTH_CONV let_CONV) THEN CONJ_TAC THENL
[CONV_TAC(RAND_CONV VECTOR3_EQ_0_CONV) THEN REWRITE_TAC[];
CONV_TAC(ONCE_DEPTH_CONV VECTOR3_DOT_CONV) THEN
REWRITE_TAC[EXISTS_IN_INSERT; NOT_IN_EMPTY] THEN
CONV_TAC(ONCE_DEPTH_CONV VECTOR3_DOT_CONV) THEN
CONV_TAC(ONCE_DEPTH_CONV REAL_RAT5_EQ_CONV) THEN
REWRITE_TAC[]];;
(* ------------------------------------------------------------------------- *)
(* Complete list of edges for each Platonic solid. *)
(* ------------------------------------------------------------------------- *)
let COMPUTE_EDGES_TAC defn fulldim facets =
GEN_TAC THEN MATCH_MP_TAC EQ_TRANS THEN
EXISTS_TAC
(vsubst[lhs(concl defn),`p:real^3->bool`]
`?f:real^3->bool. (f face_of p /\ aff_dim f = &2) /\
(e face_of f /\ aff_dim e = &1)`) THEN
CONJ_TAC THENL
[EQ_TAC THENL [STRIP_TAC; MESON_TAC[FACE_OF_TRANS]] THEN
MP_TAC(ISPECL [lhs(concl defn); `e:real^3->bool`]
FACE_OF_POLYHEDRON_SUBSET_FACET) THEN
ANTS_TAC THENL
[ASM_REWRITE_TAC[] THEN CONJ_TAC THENL
[REWRITE_TAC[defn] THEN
MATCH_MP_TAC POLYHEDRON_CONVEX_HULL THEN
REWRITE_TAC[FINITE_INSERT; FINITE_EMPTY];
CONJ_TAC THEN
DISCH_THEN(MP_TAC o AP_TERM `aff_dim:(real^3->bool)->int`) THEN
ASM_REWRITE_TAC[fulldim; AFF_DIM_EMPTY] THEN
CONV_TAC INT_REDUCE_CONV];
MATCH_MP_TAC MONO_EXISTS THEN REWRITE_TAC[facet_of] THEN
REWRITE_TAC[fulldim] THEN CONV_TAC INT_REDUCE_CONV THEN
ASM_MESON_TAC[FACE_OF_FACE]];
REWRITE_TAC[facets] THEN
REWRITE_TAC[TAUT `(a \/ b) /\ c <=> a /\ c \/ b /\ c`] THEN
REWRITE_TAC[EXISTS_OR_THM; UNWIND_THM2] THEN
CONV_TAC(LAND_CONV(DEPTH_BINOP_CONV `\/`
(fun tm -> REWR_CONV (COMPUTE_EDGES_CONV(rand(rand(lhand tm)))) tm))) THEN
REWRITE_TAC[INSERT_AC] THEN REWRITE_TAC[DISJ_ACI]];;
let TETRAHEDRON_EDGES = prove
(`!e. e
face_of std_tetrahedron /\
aff_dim e = &1 <=>
e = convex hull {vector[-- &1; -- &1; &1], vector[-- &1; &1; -- &1]} \/
e = convex hull {vector[-- &1; -- &1; &1], vector[&1; -- &1; -- &1]} \/
e = convex hull {vector[-- &1; -- &1; &1], vector[&1; &1; &1]} \/
e = convex hull {vector[-- &1; &1; -- &1], vector[&1; -- &1; -- &1]} \/
e = convex hull {vector[-- &1; &1; -- &1], vector[&1; &1; &1]} \/
e = convex hull {vector[&1; -- &1; -- &1], vector[&1; &1; &1]}`,
let CUBE_EDGES = prove
(`!e. e
face_of std_cube /\
aff_dim e = &1 <=>
e = convex hull {vector[-- &1; -- &1; -- &1], vector[-- &1; -- &1; &1]} \/
e = convex hull {vector[-- &1; -- &1; -- &1], vector[-- &1; &1; -- &1]} \/
e = convex hull {vector[-- &1; -- &1; -- &1], vector[&1; -- &1; -- &1]} \/
e = convex hull {vector[-- &1; -- &1; &1], vector[-- &1; &1; &1]} \/
e = convex hull {vector[-- &1; -- &1; &1], vector[&1; -- &1; &1]} \/
e = convex hull {vector[-- &1; &1; -- &1], vector[-- &1; &1; &1]} \/
e = convex hull {vector[-- &1; &1; -- &1], vector[&1; &1; -- &1]} \/
e = convex hull {vector[-- &1; &1; &1], vector[&1; &1; &1]} \/
e = convex hull {vector[&1; -- &1; -- &1], vector[&1; -- &1; &1]} \/
e = convex hull {vector[&1; -- &1; -- &1], vector[&1; &1; -- &1]} \/
e = convex hull {vector[&1; -- &1; &1], vector[&1; &1; &1]} \/
e = convex hull {vector[&1; &1; -- &1], vector[&1; &1; &1]}`,
let OCTAHEDRON_EDGES = prove
(`!e. e
face_of std_octahedron /\
aff_dim e = &1 <=>
e = convex hull {vector[-- &1; &0; &0], vector[&0; -- &1; &0]} \/
e = convex hull {vector[-- &1; &0; &0], vector[&0; &1; &0]} \/
e = convex hull {vector[-- &1; &0; &0], vector[&0; &0; -- &1]} \/
e = convex hull {vector[-- &1; &0; &0], vector[&0; &0; &1]} \/
e = convex hull {vector[&1; &0; &0], vector[&0; -- &1; &0]} \/
e = convex hull {vector[&1; &0; &0], vector[&0; &1; &0]} \/
e = convex hull {vector[&1; &0; &0], vector[&0; &0; -- &1]} \/
e = convex hull {vector[&1; &0; &0], vector[&0; &0; &1]} \/
e = convex hull {vector[&0; -- &1; &0], vector[&0; &0; -- &1]} \/
e = convex hull {vector[&0; -- &1; &0], vector[&0; &0; &1]} \/
e = convex hull {vector[&0; &1; &0], vector[&0; &0; -- &1]} \/
e = convex hull {vector[&0; &1; &0], vector[&0; &0; &1]}`,
let DODECAHEDRON_EDGES = prove
(`!e. e
face_of std_dodecahedron /\
aff_dim e = &1 <=>
e = convex hull {vector[-- &1 / &2 + -- &1 / &2 * sqrt (&5); &0; -- &1 / &2 + &1 / &2 * sqrt (&5)], vector[-- &1 / &2 + -- &1 / &2 * sqrt (&5); &0; &1 / &2 + -- &1 / &2 * sqrt (&5)]} \/
e = convex hull {vector[-- &1 / &2 + -- &1 / &2 * sqrt (&5); &0; -- &1 / &2 + &1 / &2 * sqrt (&5)], vector[-- &1; -- &1; &1]} \/
e = convex hull {vector[-- &1 / &2 + -- &1 / &2 * sqrt (&5); &0; -- &1 / &2 + &1 / &2 * sqrt (&5)], vector[-- &1; &1; &1]} \/
e = convex hull {vector[-- &1 / &2 + -- &1 / &2 * sqrt (&5); &0; &1 / &2 + -- &1 / &2 * sqrt (&5)], vector[-- &1; -- &1; -- &1]} \/
e = convex hull {vector[-- &1 / &2 + -- &1 / &2 * sqrt (&5); &0; &1 / &2 + -- &1 / &2 * sqrt (&5)], vector[-- &1; &1; -- &1]} \/
e = convex hull {vector[-- &1 / &2 + &1 / &2 * sqrt (&5); -- &1 / &2 + -- &1 / &2 * sqrt (&5); &0], vector[&1 / &2 + -- &1 / &2 * sqrt (&5); -- &1 / &2 + -- &1 / &2 * sqrt (&5); &0]} \/
e = convex hull {vector[-- &1 / &2 + &1 / &2 * sqrt (&5); -- &1 / &2 + -- &1 / &2 * sqrt (&5); &0], vector[&1; -- &1; -- &1]} \/
e = convex hull {vector[-- &1 / &2 + &1 / &2 * sqrt (&5); -- &1 / &2 + -- &1 / &2 * sqrt (&5); &0], vector[&1; -- &1; &1]} \/
e = convex hull {vector[-- &1 / &2 + &1 / &2 * sqrt (&5); &1 / &2 + &1 / &2 * sqrt (&5); &0], vector[&1 / &2 + -- &1 / &2 * sqrt (&5); &1 / &2 + &1 / &2 * sqrt (&5); &0]} \/
e = convex hull {vector[-- &1 / &2 + &1 / &2 * sqrt (&5); &1 / &2 + &1 / &2 * sqrt (&5); &0], vector[&1; &1; -- &1]} \/
e = convex hull {vector[-- &1 / &2 + &1 / &2 * sqrt (&5); &1 / &2 + &1 / &2 * sqrt (&5); &0], vector[&1; &1; &1]} \/
e = convex hull {vector[&1 / &2 + -- &1 / &2 * sqrt (&5); -- &1 / &2 + -- &1 / &2 * sqrt (&5); &0], vector[-- &1; -- &1; -- &1]} \/
e = convex hull {vector[&1 / &2 + -- &1 / &2 * sqrt (&5); -- &1 / &2 + -- &1 / &2 * sqrt (&5); &0], vector[-- &1; -- &1; &1]} \/
e = convex hull {vector[&1 / &2 + -- &1 / &2 * sqrt (&5); &1 / &2 + &1 / &2 * sqrt (&5); &0], vector[-- &1; &1; -- &1]} \/
e = convex hull {vector[&1 / &2 + -- &1 / &2 * sqrt (&5); &1 / &2 + &1 / &2 * sqrt (&5); &0], vector[-- &1; &1; &1]} \/
e = convex hull {vector[&1 / &2 + &1 / &2 * sqrt (&5); &0; -- &1 / &2 + &1 / &2 * sqrt (&5)], vector[&1 / &2 + &1 / &2 * sqrt (&5); &0; &1 / &2 + -- &1 / &2 * sqrt (&5)]} \/
e = convex hull {vector[&1 / &2 + &1 / &2 * sqrt (&5); &0; -- &1 / &2 + &1 / &2 * sqrt (&5)], vector[&1; -- &1; &1]} \/
e = convex hull {vector[&1 / &2 + &1 / &2 * sqrt (&5); &0; -- &1 / &2 + &1 / &2 * sqrt (&5)], vector[&1; &1; &1]} \/
e = convex hull {vector[&1 / &2 + &1 / &2 * sqrt (&5); &0; &1 / &2 + -- &1 / &2 * sqrt (&5)], vector[&1; -- &1; -- &1]} \/
e = convex hull {vector[&1 / &2 + &1 / &2 * sqrt (&5); &0; &1 / &2 + -- &1 / &2 * sqrt (&5)], vector[&1; &1; -- &1]} \/
e = convex hull {vector[-- &1; -- &1; -- &1], vector[&0; &1 / &2 + -- &1 / &2 * sqrt (&5); -- &1 / &2 + -- &1 / &2 * sqrt (&5)]} \/
e = convex hull {vector[-- &1; -- &1; &1], vector[&0; &1 / &2 + -- &1 / &2 * sqrt (&5); &1 / &2 + &1 / &2 * sqrt (&5)]} \/
e = convex hull {vector[-- &1; &1; -- &1], vector[&0; -- &1 / &2 + &1 / &2 * sqrt (&5); -- &1 / &2 + -- &1 / &2 * sqrt (&5)]} \/
e = convex hull {vector[-- &1; &1; &1], vector[&0; -- &1 / &2 + &1 / &2 * sqrt (&5); &1 / &2 + &1 / &2 * sqrt (&5)]} \/
e = convex hull {vector[&1; -- &1; -- &1], vector[&0; &1 / &2 + -- &1 / &2 * sqrt (&5); -- &1 / &2 + -- &1 / &2 * sqrt (&5)]} \/
e = convex hull {vector[&1; -- &1; &1], vector[&0; &1 / &2 + -- &1 / &2 * sqrt (&5); &1 / &2 + &1 / &2 * sqrt (&5)]} \/
e = convex hull {vector[&1; &1; -- &1], vector[&0; -- &1 / &2 + &1 / &2 * sqrt (&5); -- &1 / &2 + -- &1 / &2 * sqrt (&5)]} \/
e = convex hull {vector[&1; &1; &1], vector[&0; -- &1 / &2 + &1 / &2 * sqrt (&5); &1 / &2 + &1 / &2 * sqrt (&5)]} \/
e = convex hull {vector[&0; -- &1 / &2 + &1 / &2 * sqrt (&5); -- &1 / &2 + -- &1 / &2 * sqrt (&5)], vector[&0; &1 / &2 + -- &1 / &2 * sqrt (&5); -- &1 / &2 + -- &1 / &2 * sqrt (&5)]} \/
e = convex hull {vector[&0; -- &1 / &2 + &1 / &2 * sqrt (&5); &1 / &2 + &1 / &2 * sqrt (&5)], vector[&0; &1 / &2 + -- &1 / &2 * sqrt (&5); &1 / &2 + &1 / &2 * sqrt (&5)]}`,
let ICOSAHEDRON_EDGES = prove
(`!e. e
face_of std_icosahedron /\
aff_dim e = &1 <=>
e = convex hull {vector[-- &1 / &2 + -- &1 / &2 * sqrt (&5); &0; -- &1], vector[-- &1 / &2 + -- &1 / &2 * sqrt (&5); &0; &1]} \/
e = convex hull {vector[-- &1 / &2 + -- &1 / &2 * sqrt (&5); &0; -- &1], vector[-- &1; -- &1 / &2 + -- &1 / &2 * sqrt (&5); &0]} \/
e = convex hull {vector[-- &1 / &2 + -- &1 / &2 * sqrt (&5); &0; -- &1], vector[-- &1; &1 / &2 + &1 / &2 * sqrt (&5); &0]} \/
e = convex hull {vector[-- &1 / &2 + -- &1 / &2 * sqrt (&5); &0; -- &1], vector[&0; -- &1; -- &1 / &2 + -- &1 / &2 * sqrt (&5)]} \/
e = convex hull {vector[-- &1 / &2 + -- &1 / &2 * sqrt (&5); &0; -- &1], vector[&0; &1; -- &1 / &2 + -- &1 / &2 * sqrt (&5)]} \/
e = convex hull {vector[-- &1 / &2 + -- &1 / &2 * sqrt (&5); &0; &1], vector[-- &1; -- &1 / &2 + -- &1 / &2 * sqrt (&5); &0]} \/
e = convex hull {vector[-- &1 / &2 + -- &1 / &2 * sqrt (&5); &0; &1], vector[-- &1; &1 / &2 + &1 / &2 * sqrt (&5); &0]} \/
e = convex hull {vector[-- &1 / &2 + -- &1 / &2 * sqrt (&5); &0; &1], vector[&0; -- &1; &1 / &2 + &1 / &2 * sqrt (&5)]} \/
e = convex hull {vector[-- &1 / &2 + -- &1 / &2 * sqrt (&5); &0; &1], vector[&0; &1; &1 / &2 + &1 / &2 * sqrt (&5)]} \/
e = convex hull {vector[&1 / &2 + &1 / &2 * sqrt (&5); &0; -- &1], vector[&1 / &2 + &1 / &2 * sqrt (&5); &0; &1]} \/
e = convex hull {vector[&1 / &2 + &1 / &2 * sqrt (&5); &0; -- &1], vector[&1; -- &1 / &2 + -- &1 / &2 * sqrt (&5); &0]} \/
e = convex hull {vector[&1 / &2 + &1 / &2 * sqrt (&5); &0; -- &1], vector[&1; &1 / &2 + &1 / &2 * sqrt (&5); &0]} \/
e = convex hull {vector[&1 / &2 + &1 / &2 * sqrt (&5); &0; -- &1], vector[&0; -- &1; -- &1 / &2 + -- &1 / &2 * sqrt (&5)]} \/
e = convex hull {vector[&1 / &2 + &1 / &2 * sqrt (&5); &0; -- &1], vector[&0; &1; -- &1 / &2 + -- &1 / &2 * sqrt (&5)]} \/
e = convex hull {vector[&1 / &2 + &1 / &2 * sqrt (&5); &0; &1], vector[&1; -- &1 / &2 + -- &1 / &2 * sqrt (&5); &0]} \/
e = convex hull {vector[&1 / &2 + &1 / &2 * sqrt (&5); &0; &1], vector[&1; &1 / &2 + &1 / &2 * sqrt (&5); &0]} \/
e = convex hull {vector[&1 / &2 + &1 / &2 * sqrt (&5); &0; &1], vector[&0; -- &1; &1 / &2 + &1 / &2 * sqrt (&5)]} \/
e = convex hull {vector[&1 / &2 + &1 / &2 * sqrt (&5); &0; &1], vector[&0; &1; &1 / &2 + &1 / &2 * sqrt (&5)]} \/
e = convex hull {vector[-- &1; -- &1 / &2 + -- &1 / &2 * sqrt (&5); &0], vector[&1; -- &1 / &2 + -- &1 / &2 * sqrt (&5); &0]} \/
e = convex hull {vector[-- &1; -- &1 / &2 + -- &1 / &2 * sqrt (&5); &0], vector[&0; -- &1; -- &1 / &2 + -- &1 / &2 * sqrt (&5)]} \/
e = convex hull {vector[-- &1; -- &1 / &2 + -- &1 / &2 * sqrt (&5); &0], vector[&0; -- &1; &1 / &2 + &1 / &2 * sqrt (&5)]} \/
e = convex hull {vector[-- &1; &1 / &2 + &1 / &2 * sqrt (&5); &0], vector[&1; &1 / &2 + &1 / &2 * sqrt (&5); &0]} \/
e = convex hull {vector[-- &1; &1 / &2 + &1 / &2 * sqrt (&5); &0], vector[&0; &1; -- &1 / &2 + -- &1 / &2 * sqrt (&5)]} \/
e = convex hull {vector[-- &1; &1 / &2 + &1 / &2 * sqrt (&5); &0], vector[&0; &1; &1 / &2 + &1 / &2 * sqrt (&5)]} \/
e = convex hull {vector[&1; -- &1 / &2 + -- &1 / &2 * sqrt (&5); &0], vector[&0; -- &1; -- &1 / &2 + -- &1 / &2 * sqrt (&5)]} \/
e = convex hull {vector[&1; -- &1 / &2 + -- &1 / &2 * sqrt (&5); &0], vector[&0; -- &1; &1 / &2 + &1 / &2 * sqrt (&5)]} \/
e = convex hull {vector[&1; &1 / &2 + &1 / &2 * sqrt (&5); &0], vector[&0; &1; -- &1 / &2 + -- &1 / &2 * sqrt (&5)]} \/
e = convex hull {vector[&1; &1 / &2 + &1 / &2 * sqrt (&5); &0], vector[&0; &1; &1 / &2 + &1 / &2 * sqrt (&5)]} \/
e = convex hull {vector[&0; -- &1; -- &1 / &2 + -- &1 / &2 * sqrt (&5)], vector[&0; &1; -- &1 / &2 + -- &1 / &2 * sqrt (&5)]} \/
e = convex hull {vector[&0; -- &1; &1 / &2 + &1 / &2 * sqrt (&5)], vector[&0; &1; &1 / &2 + &1 / &2 * sqrt (&5)]}`,
(* ------------------------------------------------------------------------- *)
(* Enumerate all the vertices. *)
(* ------------------------------------------------------------------------- *)
let COMPUTE_VERTICES_TAC defn fulldim edges =
GEN_TAC THEN MATCH_MP_TAC EQ_TRANS THEN
EXISTS_TAC
(vsubst[lhs(concl defn),`p:real^3->bool`]
`?e:real^3->bool. (e face_of p /\ aff_dim e = &1) /\
(v face_of e /\ aff_dim v = &0)`) THEN
CONJ_TAC THENL
[EQ_TAC THENL [STRIP_TAC; MESON_TAC[FACE_OF_TRANS]] THEN
MP_TAC(ISPECL [lhs(concl defn); `v:real^3->bool`]
FACE_OF_POLYHEDRON_SUBSET_FACET) THEN
ANTS_TAC THENL
[ASM_REWRITE_TAC[] THEN CONJ_TAC THENL
[REWRITE_TAC[defn] THEN
MATCH_MP_TAC POLYHEDRON_CONVEX_HULL THEN
REWRITE_TAC[FINITE_INSERT; FINITE_EMPTY];
CONJ_TAC THEN
DISCH_THEN(MP_TAC o AP_TERM `aff_dim:(real^3->bool)->int`) THEN
ASM_REWRITE_TAC[fulldim; AFF_DIM_EMPTY] THEN
CONV_TAC INT_REDUCE_CONV];
REWRITE_TAC[facet_of] THEN
DISCH_THEN(X_CHOOSE_THEN `f:real^3->bool` STRIP_ASSUME_TAC)] THEN
MP_TAC(ISPECL [`f:real^3->bool`; `v:real^3->bool`]
FACE_OF_POLYHEDRON_SUBSET_FACET) THEN
ANTS_TAC THENL
[REPEAT CONJ_TAC THENL
[MATCH_MP_TAC FACE_OF_POLYHEDRON_POLYHEDRON THEN
FIRST_ASSUM(fun th ->
EXISTS_TAC (rand(concl th)) THEN
CONJ_TAC THENL [ALL_TAC; ACCEPT_TAC th]) THEN
REWRITE_TAC[defn] THEN
MATCH_MP_TAC POLYHEDRON_CONVEX_HULL THEN
REWRITE_TAC[FINITE_INSERT; FINITE_EMPTY];
ASM_MESON_TAC[FACE_OF_FACE];
DISCH_THEN(MP_TAC o AP_TERM `aff_dim:(real^3->bool)->int`) THEN
ASM_REWRITE_TAC[fulldim; AFF_DIM_EMPTY] THEN
CONV_TAC INT_REDUCE_CONV;
DISCH_THEN(MP_TAC o AP_TERM `aff_dim:(real^3->bool)->int`) THEN
ASM_REWRITE_TAC[fulldim; AFF_DIM_EMPTY] THEN
CONV_TAC INT_REDUCE_CONV];
MATCH_MP_TAC MONO_EXISTS THEN REWRITE_TAC[facet_of] THEN
ASM_REWRITE_TAC[fulldim] THEN CONV_TAC INT_REDUCE_CONV THEN
ASM_MESON_TAC[FACE_OF_FACE; FACE_OF_TRANS]];
REWRITE_TAC[edges] THEN
REWRITE_TAC[TAUT `(a \/ b) /\ c <=> a /\ c \/ b /\ c`] THEN
REWRITE_TAC[EXISTS_OR_THM; UNWIND_THM2] THEN
REWRITE_TAC[AFF_DIM_EQ_0; RIGHT_AND_EXISTS_THM] THEN
ONCE_REWRITE_TAC[MESON[]
`v face_of s /\ v = {a} <=> {a} face_of s /\ v = {a}`] THEN
REWRITE_TAC[GSYM SEGMENT_CONVEX_HULL; FACE_OF_SING] THEN
REWRITE_TAC[EXTREME_POINT_OF_SEGMENT] THEN
REWRITE_TAC[TAUT `(a \/ b) /\ c <=> a /\ c \/ b /\ c`] THEN
REWRITE_TAC[EXISTS_OR_THM; UNWIND_THM2] THEN
REWRITE_TAC[DISJ_ACI]];;
let CUBE_VERTICES = prove
(`!v. v
face_of std_cube /\
aff_dim v = &0 <=>
v = {vector [-- &1; -- &1; -- &1]} \/
v = {vector [-- &1; -- &1; &1]} \/
v = {vector [-- &1; &1; -- &1]} \/
v = {vector [-- &1; &1; &1]} \/
v = {vector [&1; -- &1; -- &1]} \/
v = {vector [&1; -- &1; &1]} \/
v = {vector [&1; &1; -- &1]} \/
v = {vector [&1; &1; &1]}`,
let DODECAHEDRON_VERTICES = prove
(`!v. v
face_of std_dodecahedron /\
aff_dim v = &0 <=>
v = {vector[-- &1 / &2 + -- &1 / &2 * sqrt (&5); &0; -- &1 / &2 + &1 / &2 * sqrt (&5)]} \/
v = {vector[-- &1 / &2 + -- &1 / &2 * sqrt (&5); &0; &1 / &2 + -- &1 / &2 * sqrt (&5)]} \/
v = {vector[-- &1 / &2 + &1 / &2 * sqrt (&5); -- &1 / &2 + -- &1 / &2 * sqrt (&5); &0]} \/
v = {vector[-- &1 / &2 + &1 / &2 * sqrt (&5); &1 / &2 + &1 / &2 * sqrt (&5); &0]} \/
v = {vector[&1 / &2 + -- &1 / &2 * sqrt (&5); -- &1 / &2 + -- &1 / &2 * sqrt (&5); &0]} \/
v = {vector[&1 / &2 + -- &1 / &2 * sqrt (&5); &1 / &2 + &1 / &2 * sqrt (&5); &0]} \/
v = {vector[&1 / &2 + &1 / &2 * sqrt (&5); &0; -- &1 / &2 + &1 / &2 * sqrt (&5)]} \/
v = {vector[&1 / &2 + &1 / &2 * sqrt (&5); &0; &1 / &2 + -- &1 / &2 * sqrt (&5)]} \/
v = {vector[-- &1; -- &1; -- &1]} \/
v = {vector[-- &1; -- &1; &1]} \/
v = {vector[-- &1; &1; -- &1]} \/
v = {vector[-- &1; &1; &1]} \/
v = {vector[&1; -- &1; -- &1]} \/
v = {vector[&1; -- &1; &1]} \/
v = {vector[&1; &1; -- &1]} \/
v = {vector[&1; &1; &1]} \/
v = {vector[&0; -- &1 / &2 + &1 / &2 * sqrt (&5); -- &1 / &2 + -- &1 / &2 * sqrt (&5)]} \/
v = {vector[&0; -- &1 / &2 + &1 / &2 * sqrt (&5); &1 / &2 + &1 / &2 * sqrt (&5)]} \/
v = {vector[&0; &1 / &2 + -- &1 / &2 * sqrt (&5); -- &1 / &2 + -- &1 / &2 * sqrt (&5)]} \/
v = {vector[&0; &1 / &2 + -- &1 / &2 * sqrt (&5); &1 / &2 + &1 / &2 * sqrt (&5)]}`,
let ICOSAHEDRON_VERTICES = prove
(`!v. v
face_of std_icosahedron /\
aff_dim v = &0 <=>
v = {vector [-- &1 / &2 + -- &1 / &2 * sqrt (&5); &0; -- &1]} \/
v = {vector [-- &1 / &2 + -- &1 / &2 * sqrt (&5); &0; &1]} \/
v = {vector [&1 / &2 + &1 / &2 * sqrt (&5); &0; -- &1]} \/
v = {vector [&1 / &2 + &1 / &2 * sqrt (&5); &0; &1]} \/
v = {vector [-- &1; -- &1 / &2 + -- &1 / &2 * sqrt (&5); &0]} \/
v = {vector [-- &1; &1 / &2 + &1 / &2 * sqrt (&5); &0]} \/
v = {vector [&1; -- &1 / &2 + -- &1 / &2 * sqrt (&5); &0]} \/
v = {vector [&1; &1 / &2 + &1 / &2 * sqrt (&5); &0]} \/
v = {vector [&0; -- &1; -- &1 / &2 + -- &1 / &2 * sqrt (&5)]} \/
v = {vector [&0; -- &1; &1 / &2 + &1 / &2 * sqrt (&5)]} \/
v = {vector [&0; &1; -- &1 / &2 + -- &1 / &2 * sqrt (&5)]} \/
v = {vector [&0; &1; &1 / &2 + &1 / &2 * sqrt (&5)]}`,
(* ------------------------------------------------------------------------- *)
(* Number of edges meeting at each vertex. *)
(* ------------------------------------------------------------------------- *)
let EDGES_PER_VERTEX_TAC defn edges verts =
REPEAT STRIP_TAC THEN MATCH_MP_TAC EQ_TRANS THEN
EXISTS_TAC
(vsubst[lhs(concl defn),`p:real^3->bool`]
`CARD {e | (e face_of p /\ aff_dim(e) = &1) /\
(v:real^3->bool) face_of e}`) THEN
CONJ_TAC THENL
[AP_TERM_TAC THEN REWRITE_TAC[EXTENSION; IN_ELIM_THM] THEN
ASM_MESON_TAC[FACE_OF_FACE];
ALL_TAC] THEN
MP_TAC(ISPEC `v:real^3->bool` verts) THEN
ASM_REWRITE_TAC[] THEN
DISCH_THEN(REPEAT_TCL DISJ_CASES_THEN SUBST1_TAC) THEN
REWRITE_TAC[edges] THEN
REWRITE_TAC[SET_RULE
`{e | (P e \/ Q e) /\ R e} =
{e | P e /\ R e} UNION {e | Q e /\ R e}`] THEN
REWRITE_TAC[MESON[FACE_OF_SING]
`e = a /\ {x} face_of e <=> e = a /\ x extreme_point_of a`] THEN
REWRITE_TAC[GSYM SEGMENT_CONVEX_HULL; EXTREME_POINT_OF_SEGMENT] THEN
ONCE_REWRITE_TAC[GSYM VECTOR_SUB_EQ] THEN
CONV_TAC(ONCE_DEPTH_CONV VECTOR3_SUB_CONV) THEN
CONV_TAC(ONCE_DEPTH_CONV VECTOR3_EQ_0_CONV) THEN
REWRITE_TAC[EMPTY_GSPEC; UNION_EMPTY] THEN
REWRITE_TAC[SET_RULE `{x | x = a} = {a}`] THEN
REWRITE_TAC[SET_RULE `{x} UNION s = x INSERT s`] THEN MATCH_MP_TAC
(MESON[HAS_SIZE] `s HAS_SIZE n ==> CARD s = n`) THEN
REPEAT
(MATCH_MP_TAC CARD_EQ_LEMMA THEN REPEAT CONJ_TAC THENL
[CONV_TAC NUM_REDUCE_CONV THEN NO_TAC;
REWRITE_TAC[IN_INSERT; NOT_IN_EMPTY; DE_MORGAN_THM; SEGMENT_EQ] THEN
REPEAT CONJ_TAC THEN MATCH_MP_TAC(SET_RULE
`~(a = c /\ b = d) /\ ~(a = d /\ b = c) /\ ~(a = b /\ c = d)
==> ~({a,b} = {c,d})`) THEN
PURE_ONCE_REWRITE_TAC[GSYM VECTOR_SUB_EQ] THEN
CONV_TAC(ONCE_DEPTH_CONV VECTOR3_SUB_CONV) THEN
CONV_TAC(ONCE_DEPTH_CONV VECTOR3_EQ_0_CONV) THEN
REWRITE_TAC[] THEN NO_TAC;
ALL_TAC]) THEN
CONV_TAC NUM_REDUCE_CONV THEN REWRITE_TAC[CONJUNCT1 HAS_SIZE_CLAUSES];;
(* ------------------------------------------------------------------------- *)
(* Number of Platonic solids. *)
(* ------------------------------------------------------------------------- *)
let PLATONIC_SOLIDS_LIMITS = prove
(`!p:real^3->bool m n.
polytope p /\
aff_dim p = &3 /\
(!f. f
face_of p /\
aff_dim(f) = &2
==>
CARD {e | e
face_of p /\
aff_dim(e) = &1 /\ e
SUBSET f} = m) /\
(!v. v
face_of p /\
aff_dim(v) = &0
==>
CARD {e | e
face_of p /\
aff_dim(e) = &1 /\ v
SUBSET e} = n)
==> m = 3 /\ n = 3 \/ // Tetrahedron
m = 4 /\ n = 3 \/ // Cube
m = 3 /\ n = 4 \/ // Octahedron
m = 5 /\ n = 3 \/ // Dodecahedron
m = 3 /\ n = 5 // Icosahedron`,
REPEAT STRIP_TAC THEN
MP_TAC(ISPEC `p:real^3->bool`
EULER_RELATION) THEN
ASM_REWRITE_TAC[] THEN
SUBGOAL_THEN
`m *
CARD {f:real^3->bool | f
face_of p /\
aff_dim f = &2} =
2 *
CARD {e | e
face_of p /\
aff_dim e = &1} /\
n *
CARD {v | v
face_of p /\
aff_dim v = &0} =
2 *
CARD {e | e
face_of p /\
aff_dim e = &1}`
MP_TAC THENL
[CONJ_TAC THEN MATCH_MP_TAC
MULTIPLE_COUNTING_LEMMA THENL
[EXISTS_TAC `\(f:real^3->bool) (e:real^3->bool). e
SUBSET f`;
EXISTS_TAC `\(v:real^3->bool) (e:real^3->bool). v
SUBSET e`] THEN
ONCE_REWRITE_TAC[SET_RULE `f
face_of s <=> f
IN {f | f
face_of s}`] THEN
ASM_SIMP_TAC[
FINITE_POLYTOPE_FACES;
FINITE_RESTRICT] THEN
ASM_REWRITE_TAC[
IN_ELIM_THM; GSYM
CONJ_ASSOC] THEN
X_GEN_TAC `e:real^3->bool` THEN STRIP_TAC THENL
[MP_TAC(ISPECL [`p:real^3->bool`; `e:real^3->bool`]
POLYHEDRON_RIDGE_TWO_FACETS) THEN
ASM_SIMP_TAC[
POLYTOPE_IMP_POLYHEDRON] THEN ANTS_TAC THENL
[CONV_TAC INT_REDUCE_CONV THEN DISCH_THEN SUBST_ALL_TAC THEN
RULE_ASSUM_TAC(REWRITE_RULE[
AFF_DIM_EMPTY]) THEN ASM_INT_ARITH_TAC;
CONV_TAC INT_REDUCE_CONV THEN REWRITE_TAC[
LEFT_IMP_EXISTS_THM] THEN
MAP_EVERY X_GEN_TAC [`f1:real^3->bool`; `f2:real^3->bool`] THEN
STRIP_TAC THEN MATCH_MP_TAC
EQ_TRANS THEN
EXISTS_TAC `
CARD {f1:real^3->bool,f2}` THEN CONJ_TAC THENL
[AP_TERM_TAC THEN GEN_REWRITE_TAC I [
EXTENSION] THEN
REWRITE_TAC[
IN_ELIM_THM;
IN_INSERT;
NOT_IN_EMPTY] THEN
ASM_MESON_TAC[];
ASM_SIMP_TAC[
CARD_CLAUSES;
IN_INSERT;
FINITE_RULES;
NOT_IN_EMPTY; ARITH]]];
SUBGOAL_THEN `?a b:real^3. e = segment[a,b]` STRIP_ASSUME_TAC THENL
[MATCH_MP_TAC
COMPACT_CONVEX_COLLINEAR_SEGMENT THEN
REPEAT CONJ_TAC THENL
[DISCH_THEN SUBST_ALL_TAC THEN
RULE_ASSUM_TAC(REWRITE_RULE[
AFF_DIM_EMPTY]) THEN ASM_INT_ARITH_TAC;
MATCH_MP_TAC
FACE_OF_IMP_COMPACT THEN
EXISTS_TAC `p:real^3->bool` THEN
ASM_SIMP_TAC[
POLYTOPE_IMP_CONVEX;
POLYTOPE_IMP_COMPACT];
ASM_MESON_TAC[
FACE_OF_IMP_CONVEX];
MP_TAC(ISPEC `e:real^3->bool`
AFF_DIM) THEN
DISCH_THEN(X_CHOOSE_THEN `b:real^3->bool` MP_TAC) THEN
ASM_REWRITE_TAC[INT_ARITH `&1:int = b - &1 <=> b = &2`] THEN
DISCH_THEN(CONJUNCTS_THEN2 (ASSUME_TAC o SYM) MP_TAC) THEN
ASM_CASES_TAC `
FINITE(b:real^3->bool)` THENL
[ALL_TAC; ASM_MESON_TAC[
AFFINE_INDEPENDENT_IMP_FINITE]] THEN
REWRITE_TAC[
INT_OF_NUM_EQ] THEN STRIP_TAC THEN
SUBGOAL_THEN `(b:real^3->bool)
HAS_SIZE 2` MP_TAC THENL
[ASM_REWRITE_TAC[
HAS_SIZE]; CONV_TAC(LAND_CONV HAS_SIZE_CONV)] THEN
REWRITE_TAC[
COLLINEAR_AFFINE_HULL] THEN
REPEAT(MATCH_MP_TAC
MONO_EXISTS THEN GEN_TAC) THEN
ASM_MESON_TAC[
HULL_SUBSET]];
ASM_CASES_TAC `a:real^3 = b` THENL
[UNDISCH_TAC `
aff_dim(e:real^3->bool) = &1` THEN
ASM_REWRITE_TAC[
SEGMENT_REFL;
AFF_DIM_SING;
INT_OF_NUM_EQ;
ARITH_EQ];
ALL_TAC] THEN
MATCH_MP_TAC
EQ_TRANS THEN
EXISTS_TAC `
CARD {v:real^3 | v
extreme_point_of segment[a,b]}` THEN
CONJ_TAC THENL
[MATCH_MP_TAC
CARD_IMAGE_INJ_EQ THEN
EXISTS_TAC `\v:real^3. {v}` THEN
REWRITE_TAC[
IN_ELIM_THM;
FACE_OF_SING;
AFF_DIM_SING] THEN
REPEAT CONJ_TAC THENL
[ASM_REWRITE_TAC[
EXTREME_POINT_OF_SEGMENT] THEN
REWRITE_TAC[SET_RULE `{x | x = a \/ x = b} = {a,b}`] THEN
REWRITE_TAC[
FINITE_INSERT;
FINITE_EMPTY];
X_GEN_TAC `v:real^3` THEN REWRITE_TAC[GSYM
FACE_OF_SING] THEN
ASM_MESON_TAC[
FACE_OF_TRANS;
FACE_OF_IMP_SUBSET];
X_GEN_TAC `s:real^3->bool` THEN REWRITE_TAC[
AFF_DIM_EQ_0] THEN
DISCH_THEN(CONJUNCTS_THEN2 ASSUME_TAC MP_TAC) THEN
DISCH_THEN(CONJUNCTS_THEN2 MP_TAC ASSUME_TAC) THEN
DISCH_THEN(X_CHOOSE_THEN `v:real^3` SUBST_ALL_TAC) THEN
REWRITE_TAC[
EXISTS_UNIQUE] THEN EXISTS_TAC `v:real^3` THEN
ASM_REWRITE_TAC[GSYM
FACE_OF_SING] THEN CONJ_TAC THENL
[ASM_MESON_TAC[
FACE_OF_FACE]; SET_TAC[]]];
ASM_REWRITE_TAC[
EXTREME_POINT_OF_SEGMENT] THEN
REWRITE_TAC[SET_RULE `{x | x = a \/ x = b} = {a,b}`] THEN
ASM_SIMP_TAC[
FINITE_INSERT;
CARD_CLAUSES;
FINITE_EMPTY] THEN
ASM_REWRITE_TAC[
IN_SING;
NOT_IN_EMPTY; ARITH]]]];
ALL_TAC] THEN
STRIP_TAC THEN
DISCH_THEN(ASSUME_TAC o MATCH_MP (ARITH_RULE
`(a + b) - c = 2 ==> a + b = c + 2`)) THEN
SUBGOAL_THEN `4 <=
CARD {v:real^3->bool | v
face_of p /\
aff_dim v = &0}`
ASSUME_TAC THENL
[ASM_SIMP_TAC[
SIZE_ZERO_DIMENSIONAL_FACES;
POLYTOPE_IMP_POLYHEDRON] THEN
MP_TAC(ISPEC `p:real^3->bool`
POLYTOPE_VERTEX_LOWER_BOUND) THEN
ASM_REWRITE_TAC[] THEN CONV_TAC INT_REDUCE_CONV THEN
REWRITE_TAC[
INT_OF_NUM_LE];
ALL_TAC] THEN
SUBGOAL_THEN `4 <=
CARD {f:real^3->bool | f
face_of p /\
aff_dim f = &2}`
ASSUME_TAC THENL
[MP_TAC(ISPEC `p:real^3->bool`
POLYTOPE_FACET_LOWER_BOUND) THEN
ASM_REWRITE_TAC[] THEN CONV_TAC INT_REDUCE_CONV THEN
ASM_REWRITE_TAC[
INT_OF_NUM_LE;
facet_of] THEN
MATCH_MP_TAC EQ_IMP THEN AP_TERM_TAC THEN AP_TERM_TAC THEN
GEN_REWRITE_TAC I [
EXTENSION] THEN REWRITE_TAC[
IN_ELIM_THM] THEN
CONV_TAC INT_REDUCE_CONV THEN GEN_TAC THEN EQ_TAC THEN
STRIP_TAC THEN ASM_REWRITE_TAC[] THEN
ASM_MESON_TAC[INT_ARITH `~(&2:int = -- &1)`;
AFF_DIM_EMPTY];
ALL_TAC] THEN
FIRST_ASSUM(MP_TAC o MATCH_MP (ARITH_RULE
`v + f = e + 2 ==> 4 <= v /\ 4 <= f ==> 6 <= e`)) THEN
ASM_REWRITE_TAC[] THEN
ASM_CASES_TAC
`
CARD {e:real^3->bool | e
face_of p /\
aff_dim e = &1} = 0` THEN
ASM_REWRITE_TAC[ARITH] THEN DISCH_TAC THEN
SUBGOAL_THEN `3 <= m` ASSUME_TAC THENL
[ASM_CASES_TAC `{f:real^3->bool | f
face_of p /\
aff_dim f = &2} = {}` THENL
[UNDISCH_TAC
`4 <=
CARD {f:real^3->bool | f
face_of p /\
aff_dim f = &2}` THEN
ASM_REWRITE_TAC[
CARD_CLAUSES] THEN ARITH_TAC;
FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [GSYM
MEMBER_NOT_EMPTY])] THEN
REWRITE_TAC[
IN_ELIM_THM] THEN
DISCH_THEN(X_CHOOSE_THEN `f:real^3->bool` MP_TAC) THEN
DISCH_THEN(fun th -> STRIP_ASSUME_TAC th THEN
FIRST_X_ASSUM(SUBST1_TAC o SYM o C MATCH_MP th)) THEN
MP_TAC(ISPEC `f:real^3->bool`
POLYTOPE_FACET_LOWER_BOUND) THEN
ASM_REWRITE_TAC[
facet_of] THEN CONV_TAC INT_REDUCE_CONV THEN
ANTS_TAC THENL [ASM_MESON_TAC[
FACE_OF_POLYTOPE_POLYTOPE]; ALL_TAC] THEN
REWRITE_TAC[
INT_OF_NUM_LE] THEN MATCH_MP_TAC EQ_IMP THEN
AP_TERM_TAC THEN AP_TERM_TAC THEN
GEN_REWRITE_TAC I [
EXTENSION] THEN REWRITE_TAC[
IN_ELIM_THM] THEN
CONV_TAC INT_REDUCE_CONV THEN X_GEN_TAC `e:real^3->bool` THEN
EQ_TAC THEN ASM_CASES_TAC `e:real^3->bool = {}` THEN
ASM_SIMP_TAC[
AFF_DIM_EMPTY] THEN CONV_TAC INT_REDUCE_CONV THENL
[ASM_MESON_TAC[
FACE_OF_TRANS;
FACE_OF_IMP_SUBSET];
ASM_MESON_TAC[
FACE_OF_FACE]];
ALL_TAC] THEN
FIRST_ASSUM(ASSUME_TAC o MATCH_MP (ARITH_RULE `3 <= m ==> ~(m = 0)`)) THEN
ASM_CASES_TAC `n = 0` THENL
[UNDISCH_THEN `n = 0` SUBST_ALL_TAC THEN
FIRST_X_ASSUM(MP_TAC o MATCH_MP (ARITH_RULE
`0 * x = 2 * e ==> e = 0`)) THEN ASM_REWRITE_TAC[];
ALL_TAC] THEN
FIRST_ASSUM(MP_TAC o MATCH_MP (NUM_RING
`v + f = e + 2 ==> !m n. m * n * v + n * m * f = m * n * (e + 2)`)) THEN
DISCH_THEN(MP_TAC o SPECL [`m:num`; `n:num`]) THEN ASM_REWRITE_TAC[] THEN
REWRITE_TAC[ARITH_RULE `m * 2 * e + n * 2 * e = m * n * (e + 2) <=>
e * 2 * (m + n) = m * n * (e + 2)`] THEN
ABBREV_TAC `E =
CARD {e:real^3->bool | e
face_of p /\
aff_dim e = &1}` THEN
ASM_CASES_TAC `n = 1` THENL
[ASM_REWRITE_TAC[
MULT_CLAUSES; ARITH_RULE
`E * 2 * (n + 1) = n * (E + 2) <=> E * (n + 2) = 2 * n`] THEN
MATCH_MP_TAC(TAUT `~p ==> p ==> q`) THEN
MATCH_MP_TAC(ARITH_RULE `n:num < m ==> ~(m = n)`) THEN
MATCH_MP_TAC
LTE_TRANS THEN EXISTS_TAC `2 * (m + 2)` THEN
CONJ_TAC THENL [ARITH_TAC; MATCH_MP_TAC
LE_MULT2 THEN ASM_ARITH_TAC];
ALL_TAC] THEN
ASM_CASES_TAC `n = 2` THENL
[ASM_REWRITE_TAC[ARITH_RULE `E * 2 * (n + 2) = n * 2 * (E + 2) <=>
E = n`] THEN
DISCH_THEN(SUBST_ALL_TAC o SYM) THEN
FIRST_X_ASSUM(MP_TAC o MATCH_MP (NUM_RING
`E * c = 2 * E ==> E = 0 \/ c = 2`)) THEN
ASM_ARITH_TAC;
ALL_TAC] THEN
SUBGOAL_THEN `3 <= n` ASSUME_TAC THENL [ASM_ARITH_TAC; ALL_TAC] THEN
ASM_CASES_TAC `m * n < 2 * (m + n)` THENL
[DISCH_TAC;
DISCH_TAC THEN RULE_ASSUM_TAC(REWRITE_RULE[
NOT_LT]) THEN
SUBGOAL_THEN `E * 2 * (m + n) <= E * m * n` MP_TAC THENL
[REWRITE_TAC[
LE_MULT_LCANCEL] THEN ASM_ARITH_TAC;
ASM_REWRITE_TAC[ARITH_RULE `m * n * (E + 2) <= E * m * n <=>
2 * m * n = 0`] THEN
MATCH_MP_TAC(TAUT `~p ==> p ==> q`) THEN
REWRITE_TAC[
MULT_EQ_0] THEN ASM_ARITH_TAC]] THEN
SUBGOAL_THEN `&m - &2:real < &4 /\ &n - &2 < &4` MP_TAC THENL
[CONJ_TAC THENL
[MATCH_MP_TAC
REAL_LT_RCANCEL_IMP THEN EXISTS_TAC `&n - &2`;
MATCH_MP_TAC
REAL_LT_LCANCEL_IMP THEN EXISTS_TAC `&m - &2`] THEN
ASM_SIMP_TAC[
REAL_SUB_LT;
REAL_OF_NUM_LT;
ARITH_RULE `2 < n <=> 3 <= n`] THEN
MATCH_MP_TAC
REAL_LTE_TRANS THEN EXISTS_TAC `&4` THEN
REWRITE_TAC[REAL_ARITH `(m - &2) * (n - &2) < &4 <=>
m * n < &2 * (m + n)`] THEN
ASM_REWRITE_TAC[REAL_OF_NUM_MUL; REAL_OF_NUM_ADD;
REAL_OF_NUM_LT] THEN
REWRITE_TAC[
REAL_SUB_LDISTRIB;
REAL_SUB_RDISTRIB;
REAL_LE_SUB_LADD] THEN
REWRITE_TAC[REAL_OF_NUM_MUL; REAL_OF_NUM_ADD; REAL_OF_NUM_LE] THEN
ASM_ARITH_TAC;
ALL_TAC] THEN
REWRITE_TAC[
REAL_LT_SUB_RADD; REAL_OF_NUM_ADD;
REAL_OF_NUM_LT] THEN
REWRITE_TAC[ARITH_RULE `m < 4 + 2 <=> m <= 5`] THEN
ASM_SIMP_TAC[ARITH_RULE
`3 <= m ==> (m <= 5 <=> m = 3 \/ m = 4 \/ m = 5)`] THEN
STRIP_TAC THEN UNDISCH_TAC `E * 2 * (m + n) = m * n * (E + 2)` THEN
ASM_REWRITE_TAC[] THEN CONV_TAC NUM_REDUCE_CONV THEN ASM_ARITH_TAC);;
(* ------------------------------------------------------------------------- *)
(* If-and-only-if version. *)
(* ------------------------------------------------------------------------- *)
(* ------------------------------------------------------------------------- *)
(* Show that the regular polyhedra do have all edges and faces congruent. *)
(* ------------------------------------------------------------------------- *)
parse_as_infix("congruent",(12,"right"));;
let CONGRUENT_SEGMENTS = prove
(`!a b c d:real^N.
dist(a,b) = dist(c,d)
==> segment[a,b] congruent segment[c,d]`,
REPEAT STRIP_TAC THEN
MP_TAC(ISPECL [`b - a:real^N`; `d - c:real^N`]
ORTHOGONAL_TRANSFORMATION_EXISTS) THEN
ANTS_TAC THENL [POP_ASSUM MP_TAC THEN NORM_ARITH_TAC; ALL_TAC] THEN
DISCH_THEN(X_CHOOSE_THEN `f:real^N->real^N` STRIP_ASSUME_TAC) THEN
REWRITE_TAC[congruent] THEN
EXISTS_TAC `c - (f:real^N->real^N) a` THEN
EXISTS_TAC `f:real^N->real^N` THEN
FIRST_ASSUM(ASSUME_TAC o MATCH_MP
ORTHOGONAL_TRANSFORMATION_LINEAR) THEN
SUBGOAL_THEN
`(\x. (c - f a) + (f:real^N->real^N) x) = (\x. (c - f a) + x) o f`
SUBST1_TAC THENL [REWRITE_TAC[
FUN_EQ_THM;
o_THM]; ALL_TAC] THEN
ASM_SIMP_TAC[GSYM
CONVEX_HULL_LINEAR_IMAGE;
SEGMENT_CONVEX_HULL;
IMAGE_o;
GSYM
CONVEX_HULL_TRANSLATION] THEN
REWRITE_TAC[
IMAGE_CLAUSES] THEN
AP_TERM_TAC THEN BINOP_TAC THENL
[VECTOR_ARITH_TAC; AP_THM_TAC THEN AP_TERM_TAC] THEN
REWRITE_TAC[VECTOR_ARITH `d:real^N = c - a + b <=> b - a = d - c`] THEN
ASM_MESON_TAC[
LINEAR_SUB]);;
let compute_dist =
let mk_sub = mk_binop `(-):real^3->real^3->real^3`
and dot_tm = `(dot):real^3->real^3->real` in
fun v1 v2 -> let vth = VECTOR3_SUB_CONV(mk_sub v1 v2) in
let dth = CONV_RULE(RAND_CONV VECTOR3_DOT_CONV)
(MK_COMB(AP_TERM dot_tm vth,vth)) in
rand(concl dth);;
let le_rat5 =
let mk_le = mk_binop `(<=):real->real->bool` and t_tm = `T` in
fun r1 r2 -> rand(concl(REAL_RAT5_LE_CONV(mk_le r1 r2))) = t_tm;;
let three_adjacent_points s =
match s with
| x::t -> let (y,_)::(z,_)::_ =
sort (fun (_,r1) (_,r2) -> le_rat5 r1 r2)
(map (fun y -> y,compute_dist x y) t) in
x,y,z
| _ -> failwith "three_adjacent_points: no points";;
let mk_33matrix =
let a11_tm = `a11:real`
and a12_tm = `a12:real`
and a13_tm = `a13:real`
and a21_tm = `a21:real`
and a22_tm = `a22:real`
and a23_tm = `a23:real`
and a31_tm = `a31:real`
and a32_tm = `a32:real`
and a33_tm = `a33:real`
and pat_tm =
`vector[vector[a11; a12; a13];
vector[a21; a22; a23];
vector[a31; a32; a33]]:real^3^3` in
fun [a11;a12;a13;a21;a22;a23;a31;a32;a33] ->
vsubst[a11,a11_tm;
a12,a12_tm;
a13,a13_tm;
a21,a21_tm;
a22,a22_tm;
a23,a23_tm;
a31,a31_tm;
a32,a32_tm;
a33,a33_tm] pat_tm;;
let MATRIX_VECTOR_MUL_3 = prove
(`(vector[vector[a11;a12;a13];
vector[a21; a22; a23];
vector[a31; a32; a33]]:real^3^3) **
(vector[x1;x2;x3]:real^3) =
vector[a11 * x1 + a12 * x2 + a13 * x3;
a21 * x1 + a22 * x2 + a23 * x3;
a31 * x1 + a32 * x2 + a33 * x3]`,
let MATRIX_LEMMA = prove
(`!A:real^3^3.
A ** x1 = x2 /\
A ** y1 = y2 /\
A ** z1 = z2 <=>
(vector [x1; y1; z1]:real^3^3) ** (row 1 A:real^3) =
vector [x2$1; y2$1; z2$1] /\
(vector [x1; y1; z1]:real^3^3) ** (row 2 A:real^3) =
vector [x2$2; y2$2; z2$2] /\
(vector [x1; y1; z1]:real^3^3) ** (row 3 A:real^3) =
vector [x2$3; y2$3; z2$3]`,
let MATRIX_BY_CRAMER_LEMMA = prove
(`!A:real^3^3.
~(det(vector[x1; y1; z1]:real^3^3) = &0)
==> (A ** x1 = x2 /\
A ** y1 = y2 /\
A ** z1 = z2 <=>
A = lambda m k. det((lambda i j.
if j = k
then (vector[x2$m; y2$m; z2$m]:real^3)$i
else (vector[x1; y1; z1]:real^3^3)$i$j)
:real^3^3) /
det(vector[x1;y1;z1]:real^3^3))`,
let MATRIX_BY_CRAMER = prove
(`!A:real^3^3 x1 y1 z1 x2 y2 z2.
let d = det(vector[x1; y1; z1]:real^3^3) in
~(d = &0)
==> (A ** x1 = x2 /\
A ** y1 = y2 /\
A ** z1 = z2 <=>
A$1$1 =
(x2$1 * y1$2 * z1$3 +
x1$2 * y1$3 * z2$1 +
x1$3 * y2$1 * z1$2 -
x2$1 * y1$3 * z1$2 -
x1$2 * y2$1 * z1$3 -
x1$3 * y1$2 * z2$1) / d /\
A$1$2 =
(x1$1 * y2$1 * z1$3 +
x2$1 * y1$3 * z1$1 +
x1$3 * y1$1 * z2$1 -
x1$1 * y1$3 * z2$1 -
x2$1 * y1$1 * z1$3 -
x1$3 * y2$1 * z1$1) / d /\
A$1$3 =
(x1$1 * y1$2 * z2$1 +
x1$2 * y2$1 * z1$1 +
x2$1 * y1$1 * z1$2 -
x1$1 * y2$1 * z1$2 -
x1$2 * y1$1 * z2$1 -
x2$1 * y1$2 * z1$1) / d /\
A$2$1 =
(x2$2 * y1$2 * z1$3 +
x1$2 * y1$3 * z2$2 +
x1$3 * y2$2 * z1$2 -
x2$2 * y1$3 * z1$2 -
x1$2 * y2$2 * z1$3 -
x1$3 * y1$2 * z2$2) / d /\
A$2$2 =
(x1$1 * y2$2 * z1$3 +
x2$2 * y1$3 * z1$1 +
x1$3 * y1$1 * z2$2 -
x1$1 * y1$3 * z2$2 -
x2$2 * y1$1 * z1$3 -
x1$3 * y2$2 * z1$1) / d /\
A$2$3 =
(x1$1 * y1$2 * z2$2 +
x1$2 * y2$2 * z1$1 +
x2$2 * y1$1 * z1$2 -
x1$1 * y2$2 * z1$2 -
x1$2 * y1$1 * z2$2 -
x2$2 * y1$2 * z1$1) / d /\
A$3$1 =
(x2$3 * y1$2 * z1$3 +
x1$2 * y1$3 * z2$3 +
x1$3 * y2$3 * z1$2 -
x2$3 * y1$3 * z1$2 -
x1$2 * y2$3 * z1$3 -
x1$3 * y1$2 * z2$3) / d /\
A$3$2 =
(x1$1 * y2$3 * z1$3 +
x2$3 * y1$3 * z1$1 +
x1$3 * y1$1 * z2$3 -
x1$1 * y1$3 * z2$3 -
x2$3 * y1$1 * z1$3 -
x1$3 * y2$3 * z1$1) / d /\
A$3$3 =
(x1$1 * y1$2 * z2$3 +
x1$2 * y2$3 * z1$1 +
x2$3 * y1$1 * z1$2 -
x1$1 * y2$3 * z1$2 -
x1$2 * y1$1 * z2$3 -
x2$3 * y1$2 * z1$1) / d)`,
let CONGRUENT_EDGES_TAC edges =
REWRITE_TAC[IMP_CONJ; RIGHT_FORALL_IMP_THM] THEN REWRITE_TAC[IMP_IMP] THEN
REWRITE_TAC[edges] THEN
REPEAT STRIP_TAC THEN ASM_REWRITE_TAC[GSYM SEGMENT_CONVEX_HULL] THEN
MATCH_MP_TAC CONGRUENT_SEGMENTS THEN REWRITE_TAC[DIST_EQ] THEN
REWRITE_TAC[dist; NORM_POW_2] THEN
CONV_TAC(ONCE_DEPTH_CONV VECTOR3_SUB_CONV) THEN
CONV_TAC(ONCE_DEPTH_CONV VECTOR3_DOT_CONV) THEN
CONV_TAC(ONCE_DEPTH_CONV REAL_RAT5_EQ_CONV) THEN
REWRITE_TAC[];;
let CONGRUENT_FACES_TAC facets =
REWRITE_TAC[IMP_CONJ; RIGHT_FORALL_IMP_THM] THEN REWRITE_TAC[IMP_IMP] THEN
REWRITE_TAC[facets] THEN
REPEAT STRIP_TAC THEN ASM_REWRITE_TAC[] THEN
W(fun (asl,w) ->
let t1 = rand(lhand w) and t2 = rand(rand w) in
let (x1,y1,z1) = three_adjacent_points (dest_setenum t1)
and (x2,y2,z2) = three_adjacent_points (dest_setenum t2) in
let th1 = SPECL [`A:real^3^3`;x1;y1;z1;x2;y2;z2] MATRIX_BY_CRAMER in
let th2 = REWRITE_RULE[VECTOR_3; DET_3] th1 in
let th3 = CONV_RULE (DEPTH_CONV REAL_RAT5_MUL_CONV) th2 in
let th4 = CONV_RULE (DEPTH_CONV
(REAL_RAT5_ADD_CONV ORELSEC REAL_RAT5_SUB_CONV)) th3 in
let th5 = CONV_RULE let_CONV th4 in
let th6 = CONV_RULE(ONCE_DEPTH_CONV REAL_RAT5_DIV_CONV) th5 in
let th7 = CONV_RULE(ONCE_DEPTH_CONV REAL_RAT5_EQ_CONV) th6 in
let th8 = MP th7 (EQT_ELIM(REWRITE_CONV[] (lhand(concl th7)))) in
let tms = map rhs (conjuncts(rand(concl th8))) in
let matt = mk_33matrix tms in
MATCH_MP_TAC CONGRUENT_SIMPLE THEN EXISTS_TAC matt THEN CONJ_TAC THENL
[REWRITE_TAC[ORTHOGONAL_MATRIX; CART_EQ] THEN
SIMP_TAC[transp; LAMBDA_BETA; matrix_mul; mat] THEN
REWRITE_TAC[DIMINDEX_3; SUM_3; FORALL_3; VECTOR_3; ARITH] THEN
CONV_TAC(ONCE_DEPTH_CONV REAL_RAT5_MUL_CONV) THEN
CONV_TAC(DEPTH_CONV REAL_RAT5_ADD_CONV) THEN
CONV_TAC(ONCE_DEPTH_CONV REAL_RAT5_EQ_CONV) THEN
REWRITE_TAC[] THEN NO_TAC;
REWRITE_TAC[IMAGE_CLAUSES; MATRIX_VECTOR_MUL_3] THEN
CONV_TAC(ONCE_DEPTH_CONV REAL_RAT5_MUL_CONV) THEN
CONV_TAC(DEPTH_CONV REAL_RAT5_ADD_CONV) THEN
REWRITE_TAC[INSERT_AC]]);;