(* ========================================================================== *)
(* FLYSPECK - BOOK FORMALIZATION *)
(* *)
(* Lemma: General Tactics *)
(* Author: Thomas C. Hales *)
(* Date: 2010-07-16 *)
(* ========================================================================== *)
module Tactics = struct
(* ASSUMPTION LISTS *)
let ASM_STRIP_TAC =
FIRST[FIRST_X_ASSUM CHOOSE_TAC;
FIRST_X_ASSUM (CONJUNCTS_THEN ASSUME_TAC);
];;
let FIRST_RULE_ASSUM rule ttc = FIRST_ASSUM (ttc o rule );;
let FIRST_RULE_X_ASSUM rule ttc = FIRST_X_ASSUM (ttc o rule );;
(* INDUCTION *)
let INDUCT_SPEC_TAC vn =
let v = mk_var (vn,`:nat`) in
SPEC_TAC (v,v) THEN INDUCT_TAC;;
(* ------------------------------------------------------------------ *)
(* SELECT ELIMINATION.
SELECT_TAC should work whenever there is a single predicate selected.
Something more sophisticated might be needed when there
is (@)A and (@)B
in the same formula.
Useful for proving statements such as `1 + (@x. (x=3)) = 4` *)
(* ------------------------------------------------------------------ *)
(* spec form of SELECT_AX *)
let select_thm select_fn select_exist =
BETA_RULE (ISPECL [select_fn;select_exist]
SELECT_AX);;
(* example *)
select_thm
`\m. (X:num->bool) m /\ (!n. X n ==> m <= n)` `n:num`;;
let SELECT_EXIST = prove_by_refinement(
`!(P:A->bool) Q. (?y. P y) /\ (!t. (P t ==> Q t)) ==> Q ((@) P)`,
(* {{{ proof *)
[
REPEAT STRIP_TAC;
ASSUME_TAC (ISPECL[`P:(A->bool)`;`y:A`] SELECT_AX);
ASM_MESON_TAC[];
]);;
(* }}} *)
let SELECT_THM = MESON[SELECT_EXIST]
`!(P:A->bool) Q. (((?y. P y) ==> (!t. (P t ==> Q t))) /\ ((~(?y. P y)) ==>
(!t. Q t))) ==> Q ((@) P)`;;
let SELECT_TAC =
let unbeta = prove(
`!(P:A->bool) (Q:A->bool). (Q ((@) P)) <=> (\t. Q t) ((@) P)`,
MESON_TAC[]) in
let unbeta_tac = CONV_TAC (HIGHER_REWRITE_CONV[
unbeta] true) in
unbeta_tac THEN (MATCH_MP_TAC
SELECT_THM) THEN BETA_TAC THEN
REPEAT STRIP_TAC;;
(* PATTERNS *)
let (PAT_MATCH:term list -> (string*thm) -> bool) = fun pat sth ->
not(search_thml (term_match[]) pat [sth] = []);;
let (PAT_TAC2:tactic -> tactic -> term list -> (string * thm) -> tactic) = fun tac1 tac2 pat sth -> if PAT_MATCH pat sth then tac1 else tac2;;
let (PAT_TAC:term list -> (string * thm) -> tactic) =
PAT_TAC2 ALL_TAC NO_TAC;;
let (FIRST_PAT_ASSUM: term list -> thm_tactic -> tactic) =
fun pat ttac gl -> tryfind (fun sth -> (PAT_TAC pat sth THEN ttac (snd sth)) gl) (goal_asms gl);;
let (FIRST_PAT_X_ASSUM:term list -> thm_tactic -> tactic) =
fun pat ttac ->
FIRST_PAT_ASSUM pat (fun th -> UNDISCH_THEN (concl th) ttac);;
let (EVERY_PAT_ASSUM:term list -> thm_tactic -> tactic) =
fun pat ttac gl ->
let rl = map snd (filter (PAT_MATCH pat) (goal_asms gl)) in
let tacl = map ttac rl in
EVERY tacl gl;;
(* Well defined functions *)
(* Harrison's lemma *)
let WELLDEFINED_FUNCTION_1 = prove
(`(?f:B->C. !x:A. f(s x) = t x) <=> (!x x'. s x = s x' ==> t x = t x')`,
MATCH_MP_TAC
EQ_TRANS THEN
EXISTS_TAC `?f:B->C. !y. !x:A. s x = y ==> f y = t x` THEN
CONJ_TAC THENL
[MESON_TAC[]; REWRITE_TAC[GSYM
SKOLEM_THM] THEN
MESON_TAC[]]);;
let WELLDEFINED_FUNCTION_2b = prove_by_refinement(
`(?f:C->D. (!x:A y:B. P x y ==> f(s x y) = t x y)) <=>
(!x x' y y'. (P x y /\ P x' y' /\ (s x y = s x' y')) ==> t x y = t x' y')`,
[
MATCH_MP_TAC
EQ_TRANS ;
EXISTS_TAC `?f:C->D. !z. !x:A y:B. ((P x y) /\ (s x y = z)) ==> f z = t x y`;
CONJ_TAC;
MESON_TAC[];
REWRITE_TAC[GSYM
SKOLEM_THM];
MESON_TAC[];
]);;
end;;