(* ========================================================================= *)
(* Derived properties of provability. *)
(* ========================================================================= *)
(* ------------------------------------------------------------------------- *)
(* The primitive basis, separated into its named components. *)
(* ------------------------------------------------------------------------- *)
let axiom_funcong = prove
(`(!A s t. A |-- s === t --> Suc s === Suc t) /\
(!A s t u v. A |-- s === t --> u === v --> s ++ u === t ++ v) /\
(!A s t u v. A |-- s === t --> u === v --> s ** u === t ** v)`,
let axiom_predcong = prove
(`(!A s t u v. A |-- s === t --> u === v --> s === u --> t === v) /\
(!A s t u v. A |-- s === t --> u === v --> s << u --> t << v) /\
(!A s t u v. A |-- s === t --> u === v --> s <<= u --> t <<= v)`,
(* ------------------------------------------------------------------------- *)
(* Now some theorems corresponding to derived rules. *)
(* ------------------------------------------------------------------------- *)
(*****
let imp_trans_chain = prove
(`!A p qs r. ALL (\q. A |-- p --> q) qs /\
A |-- ITLIST (-->) qs r
==> A |-- p --> r`,
GEN_TAC THEN GEN_TAC THEN LIST_INDUCT_TAC THEN
REWRITE_TAC[ALL; ITLIST] THENL
[ASM_MESON_TAC[add_assum]; ALL_TAC] THEN
REPEAT STRIP_TAC THEN FIRST_X_ASSUM MATCH_MP_TAC
ASM_MESON_TAC[imp_trans; imp_swap; imp_unduplicate; axiom_distribimp;
modusponens; add_assum]
add_assum] THEN
... needs more thought. Maybe the REV
*****)
let imp_trans2 = prove
(`!A p q r s. A |-- p --> q --> r /\ A |-- r --> s ==> A |-- p --> q --> s`,
let imp_contrf = prove
(`!A p r. A |-- p --> negatef p --> r`,
REPEAT GEN_TAC THEN REWRITE_TAC[negatef; negativef] THEN
COND_CASES_TAC THEN POP_ASSUM STRIP_ASSUME_TAC THEN
ASM_REWRITE_TAC[form_INJ] THEN
ASM_MESON_TAC[
imp_contr;
imp_swap]);;
(****
let imp_front = prove
(`...` a bi more structure);;
****)
(*** This takes about a minute, but it does work ***)
let imp_true_rule = prove
(`!A p q r. A |-- (p --> False) --> r /\ A |-- q --> r
==> A |-- (p --> q) --> r`,
(* ------------------------------------------------------------------------- *)
(* Equality rules. *)
(* ------------------------------------------------------------------------- *)
(* ------------------------------------------------------------------------- *)
(* First-order rules. *)
(* ------------------------------------------------------------------------- *)
let subalpha = prove
(`!A x y p q. ((x = y) \/ ~(x
IN FV(q)) /\ ~(y
IN FV(p))) /\
A |-- V x === V y --> p --> q
==> A |-- (!!x p) --> (!!y q)`,
REPEAT GEN_TAC THEN ASM_CASES_TAC `x = y:num` THEN ASM_REWRITE_TAC[] THEN
STRIP_TAC THENL
[FIRST_X_ASSUM SUBST_ALL_TAC THEN
ASM_MESON_TAC[genimp; modusponens;
axiom_eqrefl];
ALL_TAC] THEN
MATCH_MP_TAC
gen_right THEN ASM_REWRITE_TAC[
FV;
IN_DELETE] THEN
MATCH_MP_TAC subspec THEN EXISTS_TAC `V y` THEN
ASM_REWRITE_TAC[
FVT;
IN_SING]);;
(* ------------------------------------------------------------------------- *)
(* We'll perform induction on this measure. *)
(* ------------------------------------------------------------------------- *)
let complexity = new_recursive_definition form_RECURSION
`(complexity False = 1) /\
(complexity True = 1) /\
(!s t. complexity (s === t) = 1) /\
(!s t. complexity (s << t) = 1) /\
(!s t. complexity (s <<= t) = 1) /\
(!p. complexity (Not p) = complexity p + 3) /\
(!p q. complexity (p && q) = complexity p + complexity q + 6) /\
(!p q. complexity (p || q) = complexity p + complexity q + 16) /\
(!p q. complexity (p --> q) = complexity p + complexity q + 1) /\
(!p q. complexity (p <-> q) = 2 * (complexity p + complexity q) + 9) /\
(!x p. complexity (!!x p) = complexity p + 1) /\
(!x p. complexity (??x p) = complexity p + 8)`;;
let isubst_general = prove
(`!A p x v s t. A |-- s === t
--> formsubst ((x |-> s) v) p
--> formsubst ((x |-> t) v) p`,
GEN_TAC THEN GEN_TAC THEN WF_INDUCT_TAC `complexity p` THEN
POP_ASSUM MP_TAC THEN SPEC_TAC(`p:form`,`p:form`) THEN
MATCH_MP_TAC form_INDUCT THEN REWRITE_TAC[formsubst; complexity] THEN
REPEAT CONJ_TAC THENL
[MESON_TAC[
imp_refl;
add_assum];
MESON_TAC[
imp_refl;
add_assum];
MESON_TAC[
imp_trans_chain_2;
axiom_predcong;
icongruence_general];
MESON_TAC[
imp_trans_chain_2;
axiom_predcong;
icongruence_general];
MESON_TAC[
imp_trans_chain_2;
axiom_predcong;
icongruence_general];
X_GEN_TAC `p:form` THEN DISCH_THEN(K ALL_TAC) THEN
DISCH_THEN(MP_TAC o SPEC `p --> False`) THEN
REWRITE_TAC[complexity] THEN ANTS_TAC THENL [ARITH_TAC; ALL_TAC] THEN
REWRITE_TAC[formsubst] THEN
MESON_TAC[
axiom_not;
iff_imp1;
iff_imp2;
imp_swap;
imp_trans;
imp_trans2];
MAP_EVERY X_GEN_TAC [`p:form`; `q:form`] THEN DISCH_THEN(K ALL_TAC) THEN
DISCH_THEN(MP_TAC o SPEC `(p --> q --> False) --> False`) THEN
REWRITE_TAC[complexity] THEN ANTS_TAC THENL [ARITH_TAC; ALL_TAC] THEN
REWRITE_TAC[formsubst] THEN
MESON_TAC[
axiom_and;
iff_imp1;
iff_imp2;
imp_swap;
imp_trans;
imp_trans2];
MAP_EVERY X_GEN_TAC [`p:form`; `q:form`] THEN DISCH_THEN(K ALL_TAC) THEN
DISCH_THEN(MP_TAC o SPEC `Not(Not p && Not q)`) THEN
REWRITE_TAC[complexity] THEN ANTS_TAC THENL [ARITH_TAC; ALL_TAC] THEN
REWRITE_TAC[formsubst] THEN
MESON_TAC[
axiom_or;
iff_imp1;
iff_imp2;
imp_swap;
imp_trans;
imp_trans2];
MAP_EVERY X_GEN_TAC [`p:form`; `q:form`] THEN DISCH_THEN(K ALL_TAC) THEN
DISCH_THEN(fun th -> MP_TAC(SPEC `p:form` th) THEN
MP_TAC(SPEC `q:form` th)) THEN
REWRITE_TAC[ARITH_RULE `p < p + q + 1 /\ q < p + q + 1`] THEN
MESON_TAC[
imp_mono_th;
eq_sym;
imp_trans;
imp_trans_chain_2];
MAP_EVERY X_GEN_TAC [`p:form`; `q:form`] THEN DISCH_THEN(K ALL_TAC) THEN
DISCH_THEN(MP_TAC o SPEC `(p --> q) && (q --> p)`) THEN
REWRITE_TAC[complexity] THEN ANTS_TAC THENL [ARITH_TAC; ALL_TAC] THEN
REWRITE_TAC[formsubst] THEN
MESON_TAC[
iff_def;
iff_imp1;
iff_imp2;
imp_swap;
imp_trans;
imp_trans2];
ALL_TAC;
MAP_EVERY X_GEN_TAC [`x:num`; `p:form`] THEN DISCH_THEN(K ALL_TAC) THEN
DISCH_THEN(MP_TAC o SPEC `Not(!!x (Not p))`) THEN
REWRITE_TAC[complexity] THEN ANTS_TAC THENL [ARITH_TAC; ALL_TAC] THEN
REWRITE_TAC[formsubst] THEN
REPEAT(MATCH_MP_TAC
MONO_FORALL THEN GEN_TAC) THEN
REWRITE_TAC[
FV] THEN REPEAT LET_TAC THEN
ASM_MESON_TAC[
axiom_exists;
iff_imp1;
iff_imp2;
imp_swap;
imp_trans;
imp_trans2]] THEN
MAP_EVERY X_GEN_TAC [`u:num`; `p:form`] THEN DISCH_THEN(K ALL_TAC) THEN
REWRITE_TAC[ARITH_RULE `a < b + 1 <=> a <= b`] THEN DISCH_TAC THEN
MAP_EVERY X_GEN_TAC [`v:num`; `i:num->term`; `s:term`; `t:term`] THEN
MAP_EVERY ABBREV_TAC
[`x = if ?y. y
IN FV (!! u p) /\ u
IN FVT ((v |-> s) i y)
then
VARIANT (
FV (formsubst ((u |-> V u) ((v |-> s) i)) p))
else u`;
`y = if ?y. y
IN FV (!! u p) /\ u
IN FVT ((v |-> t) i y)
then
VARIANT (
FV (formsubst ((u |-> V u) ((v |-> t) i)) p))
else u`] THEN
REWRITE_TAC[
LET_DEF;
LET_END_DEF] THEN
SUBGOAL_THEN `~(x
IN FV(formsubst ((v |-> s) i) (!!u p))) /\
~(y
IN FV(formsubst ((v |-> t) i) (!!u p)))`
STRIP_ASSUME_TAC THENL
[MAP_EVERY EXPAND_TAC ["x";
"y"] THEN CONJ_TAC THEN
(COND_CASES_TAC THENL
[ALL_TAC; ASM_REWRITE_TAC[FORMSUBST_FV; IN_ELIM_THM]] THEN
MATCH_MP_TAC NOT_IN_VARIANT THEN REWRITE_TAC[FV_FINITE] THEN
REWRITE_TAC[SUBSET; FORMSUBST_FV; IN_ELIM_THM; FV; IN_DELETE] THEN
REWRITE_TAC[valmod] THEN MESON_TAC[FVT; IN_SING]);
ALL_TAC] THEN
ASM_CASES_TAC `v:num = u` THENL
[ASM_REWRITE_TAC[VALMOD_VALMOD_BASIC] THEN
MATCH_MP_TAC add_assum THEN MATCH_MP_TAC subalpha THEN
ASM_SIMP_TAC[LE_REFL] THEN
ASM_CASES_TAC `y:num = x` THEN ASM_REWRITE_TAC[] THEN CONJ_TAC THENL
[UNDISCH_TAC `~(x IN FV (formsubst ((v |-> s) i) (!! u p)))`;
UNDISCH_TAC `~(y IN FV (formsubst ((v |-> t) i) (!! u p)))`] THEN
ASM_REWRITE_TAC[FORMSUBST_FV; FV; IN_ELIM_THM; IN_DELETE] THEN
MATCH_MP_TAC MONO_NOT THEN MATCH_MP_TAC MONO_EXISTS THEN
X_GEN_TAC `w:num` THEN ASM_CASES_TAC `w:num = u` THEN
ASM_REWRITE_TAC[VALMOD_BASIC; FVT; IN_SING] THEN
ASM_REWRITE_TAC[valmod; FVT; IN_SING];
ALL_TAC] THEN
SUBGOAL_THEN
`?z. ~(z IN FVT s) /\ ~(z IN FVT t) /\
A |-- !!x (formsubst ((u |-> V x) ((v |-> s) i)) p)
--> !!z (formsubst ((u |-> V z) ((v |-> s) i)) p) /\
A |-- !!z (formsubst ((u |-> V z) ((v |-> t) i)) p)
--> !!y (formsubst ((u |-> V y) ((v |-> t) i)) p)`
MP_TAC THENL
[ALL_TAC;
DISCH_THEN(X_CHOOSE_THEN `z:num` STRIP_ASSUME_TAC) THEN
MATCH_MP_TAC imp_trans THEN
EXISTS_TAC `(!!z (formsubst ((v |-> s) ((u |-> V z) i)) p))
--> (!!z (formsubst ((v |-> t) ((u |-> V z) i)) p))` THEN
CONJ_TAC THENL
[MATCH_MP_TAC imp_trans THEN
EXISTS_TAC `!!z (formsubst ((v |-> s) ((u |-> V z) i)) p
--> formsubst ((v |-> t) ((u |-> V z) i)) p)` THEN
REWRITE_TAC[axiom_allimp] THEN
ASM_SIMP_TAC[complexity; LE_REFL; FV; IN_UNION; gen_right];
ALL_TAC] THEN
FIRST_ASSUM(fun th -> ONCE_REWRITE_TAC[MATCH_MP VALMOD_SWAP th]) THEN
ASM_MESON_TAC[imp_mono_th; modusponens]] THEN
MP_TAC(SPEC
`FVT(s) UNION FVT(t) UNION
FV(formsubst ((u |-> V x) ((v |-> s) i)) p) UNION
FV(formsubst ((u |-> V y) ((v |-> t) i)) p)` VARIANT_FINITE) THEN
REWRITE_TAC[FINITE_UNION; FV_FINITE; FVT_FINITE] THEN
W(fun (_,w) -> ABBREV_TAC(mk_comb(`(=) (z:num)`,lhand(rand(lhand w))))) THEN
REWRITE_TAC[IN_UNION; DE_MORGAN_THM] THEN STRIP_TAC THEN
EXISTS_TAC `z:num` THEN ASM_REWRITE_TAC[] THEN
CONJ_TAC THEN MATCH_MP_TAC subalpha THEN ASM_SIMP_TAC[LE_REFL] THENL
[ASM_CASES_TAC `z:num = x` THEN ASM_REWRITE_TAC[] THEN
UNDISCH_TAC `~(x IN FV (formsubst ((v |-> s) i) (!! u p)))`;
ASM_CASES_TAC `z:num = y` THEN ASM_REWRITE_TAC[] THEN
UNDISCH_TAC `~(y IN FV (formsubst ((v |-> t) i) (!! u p)))`] THEN
ASM_REWRITE_TAC[FORMSUBST_FV; FV; IN_ELIM_THM; IN_DELETE] THEN
MATCH_MP_TAC MONO_NOT THEN MATCH_MP_TAC MONO_EXISTS THEN
X_GEN_TAC `w:num` THEN ASM_CASES_TAC `w:num = u` THEN
ASM_REWRITE_TAC[VALMOD_BASIC; FVT; IN_SING] THEN
ASM_REWRITE_TAC[valmod; FVT; IN_SING]);;
let isubst = prove
(`!A p x s t. A |-- s === t
--> formsubst (x |=> s) p --> formsubst (x |=> t) p`,
(* ------------------------------------------------------------------------- *)
(* To conclude cleanly, useful to have all variables. *)
(* ------------------------------------------------------------------------- *)
let TERMSUBST_TWICE_GENERAL = prove
(`!x z t v s. ~(z
IN FVT s)
==> (termsubst ((x |-> t) v) s =
termsubst ((z |-> t) v) (termsubst (x |=> V z) s))`,
GEN_TAC THEN GEN_TAC THEN GEN_TAC THEN GEN_TAC THEN
MATCH_MP_TAC term_INDUCT THEN
REWRITE_TAC[termsubst;
ASSIGN; valmod;
FVT;
IN_SING;
IN_UNION] THEN
MESON_TAC[termsubst;
ASSIGN]);;
let spec = prove
(`!A x p t. A |-- !!x p ==> A |-- formsubst (x |=> t) p`,
MESON_TAC[ispec; modusponens]);;
(* ------------------------------------------------------------------------- *)
(* Monotonicity and the deduction theorem. *)
(* ------------------------------------------------------------------------- *)