(* ========================================================================= *) (* Geometric "without loss of generality" tactics to pick convenient coords. *) (* ========================================================================= *) needs "Multivariate/determinants.ml";; needs "Multivariate/convex.ml";; (* ------------------------------------------------------------------------- *) (* Flyspeck definition of plane, and its invariance theorems. *) (* ------------------------------------------------------------------------- *) let plane = new_definition `plane x = (?u v w. ~(collinear {u,v,w}) /\ x = affine hull {u,v,w})`;; let PLANE_TRANSLATION_EQ = prove (`!a:real^N s. plane(IMAGE (\x. a + x) s) <=> plane s`, REWRITE_TAC[plane] THEN GEOM_TRANSLATE_TAC[]);; let PLANE_TRANSLATION = prove (`!a:real^N s. plane s ==> plane(IMAGE (\x. a + x) s)`, REWRITE_TAC[PLANE_TRANSLATION_EQ]);; add_translation_invariants [PLANE_TRANSLATION_EQ];; let PLANE_LINEAR_IMAGE_EQ = prove (`!f:real^M->real^N p. linear f /\ (!x y. f x = f y ==> x = y) ==> (plane(IMAGE f p) <=> plane p)`, REPEAT STRIP_TAC THEN REWRITE_TAC[plane] THEN MATCH_MP_TAC EQ_TRANS THEN EXISTS_TAC `?u. u IN IMAGE f (:real^M) /\ ?v. v IN IMAGE f (:real^M) /\ ?w. w IN IMAGE (f:real^M->real^N) (:real^M) /\ ~collinear {u, v, w} /\ IMAGE f p = affine hull {u, v, w}` THEN CONJ_TAC THENL [REWRITE_TAC[RIGHT_AND_EXISTS_THM; IN_IMAGE; IN_UNIV] THEN REPEAT(AP_TERM_TAC THEN ABS_TAC) THEN EQ_TAC THEN DISCH_TAC THEN ASM_REWRITE_TAC[] THEN SUBGOAL_THEN `{u,v,w} SUBSET IMAGE (f:real^M->real^N) p` MP_TAC THENL [ASM_REWRITE_TAC[HULL_SUBSET]; SET_TAC[]]; REWRITE_TAC[EXISTS_IN_IMAGE; IN_UNIV] THEN REWRITE_TAC[SET_RULE `{f a,f b,f c} = IMAGE f {a,b,c}`] THEN ASM_SIMP_TAC[AFFINE_HULL_LINEAR_IMAGE] THEN REPEAT(AP_TERM_TAC THEN ABS_TAC) THEN BINOP_TAC THENL [ASM_MESON_TAC[COLLINEAR_LINEAR_IMAGE_EQ]; ASM SET_TAC[]]]);; let PLANE_LINEAR_IMAGE = prove (`!f:real^M->real^N p. linear f /\ plane p /\ (!x y. f x = f y ==> x = y) ==> plane(IMAGE f p)`, MESON_TAC[PLANE_LINEAR_IMAGE_EQ]);; add_linear_invariants [PLANE_LINEAR_IMAGE_EQ];; (* ------------------------------------------------------------------------- *) (* Rotating and translating so a given plane in R^3 becomes {x | x$3 = &0}. *) (* ------------------------------------------------------------------------- *) let ROTATION_PLANE_HORIZONTAL = prove (`!s. plane s ==> ?a f. orthogonal_transformation f /\ det(matrix f) = &1 /\ IMAGE f (IMAGE (\x. a + x) s) = {z:real^3 | z$3 = &0}`, let lemma = prove (`span {z:real^3 | z$3 = &0} = {z:real^3 | z$3 = &0}`, REWRITE_TAC[SPAN_EQ_SELF; subspace; IN_ELIM_THM] THEN SIMP_TAC[VECTOR_ADD_COMPONENT; VECTOR_MUL_COMPONENT; VEC_COMPONENT; DIMINDEX_3; ARITH] THEN REAL_ARITH_TAC) in REPEAT STRIP_TAC THEN FIRST_ASSUM(MP_TAC o GEN_REWRITE_RULE I [plane]) THEN REWRITE_TAC[LEFT_IMP_EXISTS_THM] THEN MAP_EVERY X_GEN_TAC [`a:real^3`; `b:real^3`; `c:real^3`] THEN MAP_EVERY (fun t -> ASM_CASES_TAC t THENL [ASM_REWRITE_TAC[COLLINEAR_2; INSERT_AC]; ALL_TAC]) [`a:real^3 = b`; `a:real^3 = c`; `b:real^3 = c`] THEN DISCH_THEN(CONJUNCTS_THEN2 ASSUME_TAC SUBST1_TAC) THEN ASM_SIMP_TAC[AFFINE_HULL_INSERT_SPAN; IN_INSERT; NOT_IN_EMPTY] THEN EXISTS_TAC `--a:real^3` THEN REWRITE_TAC[SET_RULE `IMAGE (\x:real^3. --a + x) {a + x | x | x IN s} = IMAGE (\x. --a + a + x) s`] THEN REWRITE_TAC[VECTOR_ARITH `--a + a + x:real^3 = x`; IMAGE_ID] THEN REWRITE_TAC[SET_RULE `{x - a:real^x | x = b \/ x = c} = {b - a,c - a}`] THEN MP_TAC(ISPEC `span{b - a:real^3,c - a}` ROTATION_LOWDIM_HORIZONTAL) THEN REWRITE_TAC[DIMINDEX_3] THEN ANTS_TAC THENL [MATCH_MP_TAC LET_TRANS THEN EXISTS_TAC `CARD{b - a:real^3,c - a}` THEN SIMP_TAC[DIM_SPAN; DIM_LE_CARD; FINITE_RULES] THEN SIMP_TAC[CARD_CLAUSES; FINITE_RULES] THEN ARITH_TAC; ALL_TAC] THEN MATCH_MP_TAC MONO_EXISTS THEN X_GEN_TAC `f:real^3->real^3` THEN STRIP_TAC THEN ASM_REWRITE_TAC[] THEN FIRST_ASSUM(ASSUME_TAC o MATCH_MP ORTHOGONAL_TRANSFORMATION_LINEAR) THEN ASM_SIMP_TAC[GSYM SPAN_LINEAR_IMAGE] THEN GEN_REWRITE_TAC RAND_CONV [GSYM lemma] THEN MATCH_MP_TAC DIM_EQ_SPAN THEN CONJ_TAC THENL [ASM_MESON_TAC[IMAGE_SUBSET; SPAN_INC; SUBSET_TRANS]; ALL_TAC] THEN MATCH_MP_TAC LE_TRANS THEN EXISTS_TAC `2` THEN CONJ_TAC THENL [MP_TAC(ISPECL [`{z:real^3 | z$3 = &0}`; `(:real^3)`] DIM_EQ_SPAN) THEN REWRITE_TAC[SUBSET_UNIV; DIM_UNIV; DIMINDEX_3; lemma] THEN MATCH_MP_TAC(TAUT `~r /\ (~p ==> q) ==> (q ==> r) ==> p`) THEN REWRITE_TAC[ARITH_RULE `~(x <= 2) <=> 3 <= x`] THEN REWRITE_TAC[EXTENSION; SPAN_UNIV; IN_ELIM_THM] THEN DISCH_THEN(MP_TAC o SPEC `vector[&0;&0;&1]:real^3`) THEN REWRITE_TAC[IN_UNIV; VECTOR_3] THEN REAL_ARITH_TAC; ALL_TAC] THEN MATCH_MP_TAC LE_TRANS THEN EXISTS_TAC `dim {b - a:real^3,c - a}` THEN CONJ_TAC THENL [ALL_TAC; ASM_MESON_TAC[LE_REFL; DIM_INJECTIVE_LINEAR_IMAGE; ORTHOGONAL_TRANSFORMATION_INJECTIVE]] THEN MP_TAC(ISPEC `{b - a:real^3,c - a}` INDEPENDENT_BOUND_GENERAL) THEN SIMP_TAC[CARD_CLAUSES; FINITE_RULES; IN_SING; NOT_IN_EMPTY] THEN ASM_REWRITE_TAC[VECTOR_ARITH `b - a:real^3 = c - a <=> b = c`; ARITH] THEN DISCH_THEN MATCH_MP_TAC THEN FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE (RAND_CONV o RAND_CONV) [SET_RULE `{a,b,c} = {b,a,c}`]) THEN REWRITE_TAC[] THEN ONCE_REWRITE_TAC[COLLINEAR_3] THEN REWRITE_TAC[independent; CONTRAPOS_THM; dependent] THEN REWRITE_TAC[IN_INSERT; NOT_IN_EMPTY; RIGHT_OR_DISTRIB] THEN REWRITE_TAC[EXISTS_OR_THM; UNWIND_THM2] THEN ASM_SIMP_TAC[SET_RULE `~(a = b) ==> {a,b} DELETE b = {a}`; SET_RULE `~(a = b) ==> {a,b} DELETE a = {b}`; VECTOR_ARITH `b - a:real^3 = c - a <=> b = c`] THEN REWRITE_TAC[SPAN_BREAKDOWN_EQ; SPAN_EMPTY; IN_SING] THEN ONCE_REWRITE_TAC[VECTOR_SUB_EQ] THEN MESON_TAC[COLLINEAR_LEMMA; INSERT_AC]);; let ROTATION_HORIZONTAL_PLANE = prove (`!p. plane p ==> ?a f. orthogonal_transformation f /\ det(matrix f) = &1 /\ IMAGE (\x. a + x) (IMAGE f {z:real^3 | z$3 = &0}) = p`, REPEAT STRIP_TAC THEN FIRST_X_ASSUM(MP_TAC o MATCH_MP ROTATION_PLANE_HORIZONTAL) THEN DISCH_THEN(X_CHOOSE_THEN `a:real^3` (X_CHOOSE_THEN `f:real^3->real^3` STRIP_ASSUME_TAC)) THEN FIRST_ASSUM(X_CHOOSE_THEN `g:real^3->real^3` STRIP_ASSUME_TAC o MATCH_MP ORTHOGONAL_TRANSFORMATION_INVERSE) THEN MAP_EVERY EXISTS_TAC [`--a:real^3`; `g:real^3->real^3`] THEN FIRST_X_ASSUM(SUBST1_TAC o SYM) THEN ASM_REWRITE_TAC[GSYM IMAGE_o; o_DEF; IMAGE_ID; VECTOR_ARITH `--a + a + x:real^3 = x`] THEN MATCH_MP_TAC(REAL_RING `!f. f * g = &1 /\ f = &1 ==> g = &1`) THEN EXISTS_TAC `det(matrix(f:real^3->real^3))` THEN REWRITE_TAC[GSYM DET_MUL] THEN ASM_SIMP_TAC[GSYM MATRIX_COMPOSE; ORTHOGONAL_TRANSFORMATION_LINEAR] THEN ASM_REWRITE_TAC[o_DEF; MATRIX_ID; DET_I]);; (* ------------------------------------------------------------------------- *) (* Apply plane rotation to a goal. *) (* ------------------------------------------------------------------------- *) let GEOM_HORIZONTAL_PLANE_RULE = let ifn = MATCH_MP (TAUT `(p ==> (x <=> x')) /\ (~p ==> (x <=> T)) ==> (x' ==> x)`) and pth = prove (`!a f. orthogonal_transformation (f:real^N->real^N) ==> ((!P. (!x. P x) <=> (!x. P (a + f x))) /\ (!P. (?x. P x) <=> (?x. P (a + f x))) /\ (!Q. (!s. Q s) <=> (!s. Q (IMAGE (\x. a + x) (IMAGE f s)))) /\ (!Q. (?s. Q s) <=> (?s. Q (IMAGE (\x. a + x) (IMAGE f s))))) /\ (!P. {x | P x} = IMAGE (\x. a + x) (IMAGE f {x | P(a + f x)}))`, REPEAT GEN_TAC THEN DISCH_TAC THEN MP_TAC(ISPEC `(\x. a + x) o (f:real^N->real^N)` QUANTIFY_SURJECTION_THM) THEN REWRITE_TAC[o_THM; IMAGE_o] THEN DISCH_THEN MATCH_MP_TAC THEN ASM_MESON_TAC[ORTHOGONAL_TRANSFORMATION_SURJECTIVE; VECTOR_ARITH `a + (x - a:real^N) = x`]) and cth = prove (`!a f. {} = IMAGE (\x:real^3. a + x) (IMAGE f {})`, REWRITE_TAC[IMAGE_CLAUSES]) and oth = prove (`!f:real^3->real^3. orthogonal_transformation f /\ det(matrix f) = &1 ==> linear f /\ (!x y. f x = f y ==> x = y) /\ (!y. ?x. f x = y) /\ (!x. norm(f x) = norm x) /\ (2 <= dimindex(:3) ==> det(matrix f) = &1)`, GEN_TAC THEN STRIP_TAC THEN ASM_REWRITE_TAC[] THEN REPEAT CONJ_TAC THENL [ASM_SIMP_TAC[ORTHOGONAL_TRANSFORMATION_LINEAR]; ASM_MESON_TAC[ORTHOGONAL_TRANSFORMATION_INJECTIVE]; ASM_MESON_TAC[ORTHOGONAL_TRANSFORMATION_SURJECTIVE]; ASM_MESON_TAC[ORTHOGONAL_TRANSFORMATION]]) and fth = MESON[] `(!a f. q a f ==> (p <=> p' a f)) ==> ((?a f. q a f) ==> (p <=> !a f. q a f ==> p' a f))` in fun tm -> let x,bod = dest_forall tm in let th1 = EXISTS_GENVAR_RULE (UNDISCH(ISPEC x ROTATION_HORIZONTAL_PLANE)) in let [a;f],tm1 = strip_exists(concl th1) in let [th_orth;th_det;th_im] = CONJUNCTS(ASSUME tm1) in let th2 = PROVE_HYP th_orth (UNDISCH(ISPECL [a;f] pth)) in let th3 = (EXPAND_QUANTS_CONV(ASSUME(concl th2)) THENC SUBS_CONV[GSYM th_im; ISPECL [a;f] cth]) bod in let th4 = PROVE_HYP th2 th3 in let th5 = TRANSLATION_INVARIANTS a in let th6 = GEN_REWRITE_RULE (RAND_CONV o REDEPTH_CONV) [ASSUME(concl th5)] th4 in let th7 = PROVE_HYP th5 th6 in let th8s = CONJUNCTS(MATCH_MP oth (CONJ th_orth th_det)) in let th9 = LINEAR_INVARIANTS f th8s in let th10 = GEN_REWRITE_RULE (RAND_CONV o REDEPTH_CONV) [th9] th7 in let th11 = if intersect (frees(concl th10)) [a;f] = [] then PROVE_HYP th1 (itlist SIMPLE_CHOOSE [a;f] th10) else MP (MATCH_MP fth (GENL [a;f] (DISCH_ALL th10))) th1 in let th12 = REWRITE_CONV[ASSUME(mk_neg(hd(hyp th11)))] bod in let th13 = ifn(CONJ (DISCH_ALL th11) (DISCH_ALL th12)) in let th14 = MATCH_MP MONO_FORALL (GEN x th13) in GEN_REWRITE_RULE (TRY_CONV o LAND_CONV) [FORALL_SIMP] th14;; let GEOM_HORIZONTAL_PLANE_TAC p = W(fun (asl,w) -> let avs,bod = strip_forall w and avs' = subtract (frees w) (freesl(map (concl o snd) asl)) in let avs,bod = strip_forall w in MAP_EVERY X_GEN_TAC avs THEN MAP_EVERY (fun t -> SPEC_TAC(t,t)) (rev(subtract (avs@avs') [p])) THEN SPEC_TAC(p,p) THEN W(MATCH_MP_TAC o GEOM_HORIZONTAL_PLANE_RULE o snd));; (* ------------------------------------------------------------------------- *) (* Injection from real^2 -> real^3 plane with zero last coordinate. *) (* ------------------------------------------------------------------------- *) let pad2d3d = new_definition `(pad2d3d:real^2->real^3) x = lambda i. if i < 3 then x$i else &0`;; let FORALL_PAD2D3D_THM = prove (`!P. (!y:real^3. y$3 = &0 ==> P y) <=> (!x. P(pad2d3d x))`, GEN_TAC THEN EQ_TAC THEN REPEAT STRIP_TAC THENL [FIRST_X_ASSUM MATCH_MP_TAC THEN REWRITE_TAC[pad2d3d] THEN SIMP_TAC[LAMBDA_BETA; DIMINDEX_3; ARITH; LT_REFL]; FIRST_X_ASSUM(MP_TAC o SPEC `(lambda i. (y:real^3)$i):real^2`) THEN MATCH_MP_TAC EQ_IMP THEN AP_TERM_TAC THEN SIMP_TAC[CART_EQ; pad2d3d; DIMINDEX_3; ARITH; LAMBDA_BETA; DIMINDEX_2; ARITH_RULE `i < 3 <=> i <= 2`] THEN REWRITE_TAC[ARITH_RULE `i <= 3 <=> i <= 2 \/ i = 3`] THEN ASM_MESON_TAC[]]);; let QUANTIFY_PAD2D3D_THM = prove (`(!P. (!y:real^3. y$3 = &0 ==> P y) <=> (!x. P(pad2d3d x))) /\ (!P. (?y:real^3. y$3 = &0 /\ P y) <=> (?x. P(pad2d3d x)))`, REWRITE_TAC[MESON[] `(?y. P y) <=> ~(!x. ~P x)`] THEN REWRITE_TAC[GSYM FORALL_PAD2D3D_THM] THEN MESON_TAC[]);; let LINEAR_PAD2D3D = prove (`linear pad2d3d`, REWRITE_TAC[linear; pad2d3d] THEN SIMP_TAC[CART_EQ; VECTOR_ADD_COMPONENT; VECTOR_MUL_COMPONENT; LAMBDA_BETA; DIMINDEX_2; DIMINDEX_3; ARITH; ARITH_RULE `i < 3 ==> i <= 2`] THEN REPEAT STRIP_TAC THEN REPEAT(COND_CASES_TAC THEN ASM_REWRITE_TAC[]) THEN REAL_ARITH_TAC);; let INJECTIVE_PAD2D3D = prove (`!x y. pad2d3d x = pad2d3d y ==> x = y`, SIMP_TAC[CART_EQ; pad2d3d; LAMBDA_BETA; DIMINDEX_3; DIMINDEX_2] THEN REWRITE_TAC[ARITH_RULE `i < 3 <=> i <= 2`] THEN MESON_TAC[ARITH_RULE `i <= 2 ==> i <= 3`]);; let NORM_PAD2D3D = prove (`!x. norm(pad2d3d x) = norm x`, SIMP_TAC[NORM_EQ; DOT_2; DOT_3; pad2d3d; LAMBDA_BETA; DIMINDEX_2; DIMINDEX_3; ARITH] THEN REAL_ARITH_TAC);; (* ------------------------------------------------------------------------- *) (* Apply 3D->2D conversion to a goal. Take care to preserve variable names. *) (* ------------------------------------------------------------------------- *) let PAD2D3D_QUANTIFY_CONV = let gv = genvar `:real^2` in let pth = CONV_RULE (BINOP_CONV(BINDER_CONV(RAND_CONV(GEN_ALPHA_CONV gv)))) QUANTIFY_PAD2D3D_THM in let conv1 = GEN_REWRITE_CONV I [pth] and dest_quant tm = try dest_forall tm with Failure _ -> dest_exists tm in fun tm -> let th = conv1 tm in let name = fst(dest_var(fst(dest_quant tm))) in let ty = snd(dest_var(fst(dest_quant(rand(concl th))))) in CONV_RULE(RAND_CONV(GEN_ALPHA_CONV(mk_var(name,ty)))) th;; let PAD2D3D_TAC = let pad2d3d_tm = `pad2d3d` and pths = [LINEAR_PAD2D3D; INJECTIVE_PAD2D3D; NORM_PAD2D3D] and cth = prove (`{} = IMAGE pad2d3d {} /\ vec 0 = pad2d3d(vec 0)`, REWRITE_TAC[IMAGE_CLAUSES] THEN MESON_TAC[LINEAR_PAD2D3D; LINEAR_0]) in let lasttac = GEN_REWRITE_TAC REDEPTH_CONV [LINEAR_INVARIANTS pad2d3d_tm pths] in fun gl -> (GEN_REWRITE_TAC ONCE_DEPTH_CONV [cth] THEN CONV_TAC(DEPTH_CONV PAD2D3D_QUANTIFY_CONV) THEN lasttac) gl;; (* ------------------------------------------------------------------------- *) (* Rotating so a given line from the origin becomes the x-axis. *) (* ------------------------------------------------------------------------- *) let ROTATION_HORIZONTAL_LINE = prove (`!a:real^N. ?b f. orthogonal_transformation f /\ det(matrix f) = &1 /\ f b = a /\ (!k. 1 < k /\ k <= dimindex(:N) ==> b$k = &0)`, GEN_TAC THEN ASM_CASES_TAC `dimindex(:N) = 1` THENL [MAP_EVERY EXISTS_TAC [`a:real^N`; `\x:real^N. x`] THEN ASM_SIMP_TAC[DET_I; MATRIX_ID; ORTHOGONAL_TRANSFORMATION_ID; LTE_ANTISYM]; EXISTS_TAC `norm(a:real^N) % (basis 1):real^N` THEN SIMP_TAC[VECTOR_MUL_COMPONENT; LT_IMP_LE; BASIS_COMPONENT] THEN SIMP_TAC[ARITH_RULE `1 < k ==> ~(k = 1)`; REAL_MUL_RZERO] THEN MATCH_MP_TAC ROTATION_EXISTS THEN SIMP_TAC[NORM_MUL; NORM_BASIS; LE_REFL; DIMINDEX_GE_1] THEN REWRITE_TAC[REAL_ABS_NORM; REAL_MUL_RID] THEN MATCH_MP_TAC(ARITH_RULE `~(n = 1) /\ 1 <= n ==> 2 <= n`) THEN ASM_REWRITE_TAC[DIMINDEX_GE_1]]);; let GEOM_HORIZONTAL_LINE_RULE = let pth = prove (`!f. orthogonal_transformation (f:real^N->real^N) ==> (vec 0 = f(vec 0) /\ {} = IMAGE f {}) /\ ((!P. (!x. P x) <=> (!x. P (f x))) /\ (!P. (?x. P x) <=> (?x. P (f x))) /\ (!Q. (!s. Q s) <=> (!s. Q (IMAGE f s))) /\ (!Q. (?s. Q s) <=> (?s. Q (IMAGE f s)))) /\ (!P. {x | P x} = IMAGE f {x | P(f x)})`, REPEAT GEN_TAC THEN DISCH_TAC THEN REWRITE_TAC[IMAGE_CLAUSES] THEN CONJ_TAC THENL [FIRST_X_ASSUM(MP_TAC o MATCH_MP ORTHOGONAL_TRANSFORMATION_LINEAR) THEN MESON_TAC[LINEAR_0]; MATCH_MP_TAC QUANTIFY_SURJECTION_THM THEN ASM_MESON_TAC[ORTHOGONAL_TRANSFORMATION_SURJECTIVE]]) and oth = prove (`!f:real^N->real^N. orthogonal_transformation f /\ det(matrix f) = &1 ==> linear f /\ (!x y. f x = f y ==> x = y) /\ (!y. ?x. f x = y) /\ (!x. norm(f x) = norm x) /\ (2 <= dimindex(:N) ==> det(matrix f) = &1)`, GEN_TAC THEN STRIP_TAC THEN ASM_REWRITE_TAC[] THEN REPEAT CONJ_TAC THENL [ASM_SIMP_TAC[ORTHOGONAL_TRANSFORMATION_LINEAR]; ASM_MESON_TAC[ORTHOGONAL_TRANSFORMATION_INJECTIVE]; ASM_MESON_TAC[ORTHOGONAL_TRANSFORMATION_SURJECTIVE]; ASM_MESON_TAC[ORTHOGONAL_TRANSFORMATION]]) and sth = prove (`((!k. 1 < k /\ k <= dimindex(:2) ==> b$k = &0) <=> b$2 = &0) /\ ((!k. 1 < k /\ k <= dimindex(:3) ==> b$k = &0) <=> b$2 = &0 /\ b$3 = &0)`, REWRITE_TAC[DIMINDEX_2; DIMINDEX_3; ARITH_RULE `k <= 3 <=> k = 3 \/ k <= 2`; ARITH_RULE `k <= 2 <=> k = 2 \/ ~(1 < k)`] THEN MESON_TAC[ARITH_RULE `1 < 2 /\ 1 < 3`]) in let sfn = GEN_REWRITE_RULE ONCE_DEPTH_CONV [sth] in fun tm -> let x,bod = dest_forall tm in let th1 = EXISTS_GENVAR_RULE (sfn(ISPEC x ROTATION_HORIZONTAL_LINE)) in let [a;f],tm1 = strip_exists(concl th1) in let th_orth,th2 = CONJ_PAIR(ASSUME tm1) in let th_det,th2a = CONJ_PAIR th2 in let th_works,th_zero = CONJ_PAIR th2a in let thc,thq = CONJ_PAIR(PROVE_HYP th2 (UNDISCH(ISPEC f pth))) in let th3 = CONV_RULE(RAND_CONV(SUBS_CONV(GSYM th_works::CONJUNCTS thc))) (EXPAND_QUANTS_CONV(ASSUME(concl thq)) bod) in let th4 = PROVE_HYP thq th3 in let thps = CONJUNCTS(MATCH_MP oth (CONJ th_orth th_det)) in let th5 = LINEAR_INVARIANTS f thps in let th6 = PROVE_HYP th_orth (GEN_REWRITE_RULE (RAND_CONV o REDEPTH_CONV) [th5] th4) in let ntm = mk_forall(a,mk_imp(concl th_zero,rand(concl th6))) in let th7 = MP(SPEC a (ASSUME ntm)) th_zero in let th8 = DISCH ntm (EQ_MP (SYM th6) th7) in if intersect (frees(concl th8)) [a;f] = [] then let th9 = PROVE_HYP th1 (itlist SIMPLE_CHOOSE [a;f] th8) in let th10 = DISCH ntm (GEN x (UNDISCH th9)) in CONV_RULE(LAND_CONV (GEN_ALPHA_CONV x)) th10 else let mtm = list_mk_forall([a;f],mk_imp(hd(hyp th8),rand(concl th6))) in let th9 = EQ_MP (SYM th6) (UNDISCH(SPECL [a;f] (ASSUME mtm))) in let th10 = itlist SIMPLE_CHOOSE [a;f] (DISCH mtm th9) in let th11 = GEN x (PROVE_HYP th1 th10) in MATCH_MP MONO_FORALL th11;; let GEOM_HORIZONTAL_LINE_TAC l (asl,w as gl) = let avs,bod = strip_forall w and avs' = subtract (frees w) (freesl(map (concl o snd) asl)) in (MAP_EVERY X_GEN_TAC avs THEN MAP_EVERY (fun t -> SPEC_TAC(t,t)) (rev(subtract (avs@avs') [l])) THEN SPEC_TAC(l,l) THEN W(MATCH_MP_TAC o GEOM_HORIZONTAL_LINE_RULE o snd)) gl;;