File ‹~~/src/Provers/quantifier1.ML›
signature QUANTIFIER1_DATA =
sig
val dest_eq: term -> (term * term) option
val dest_conj: term -> (term * term) option
val dest_imp: term -> (term * term) option
val conj: term
val imp: term
val iff_reflection: thm
val iffI: thm
val iff_trans: thm
val conjI: thm
val conjE: thm
val impI: thm
val mp: thm
val exI: thm
val exE: thm
val uncurry: thm
val iff_allI: thm
val iff_exI: thm
val all_comm: thm
val ex_comm: thm
val atomize: Proof.context -> conv
end;
signature QUANTIFIER1 =
sig
val rearrange_all: Simplifier.proc
val rearrange_All: Simplifier.proc
val rearrange_Ball: (Proof.context -> tactic) -> Simplifier.proc
val rearrange_Ex: Simplifier.proc
val rearrange_Bex: (Proof.context -> tactic) -> Simplifier.proc
val rearrange_Collect: (Proof.context -> tactic) -> Simplifier.proc
end;
functor Quantifier1(Data: QUANTIFIER1_DATA): QUANTIFIER1 =
struct
fun def xs eq =
(case Data.dest_eq eq of
SOME (s, t) =>
let val n = length xs in
s = Bound n andalso not (loose_bvar1 (t, n)) orelse
t = Bound n andalso not (loose_bvar1 (s, n))
end
| NONE => false);
fun extract_conj fst xs t =
(case Data.dest_conj t of
NONE => NONE
| SOME (P, Q) =>
if def xs P then (if fst then NONE else SOME (xs, P, Q))
else if def xs Q then SOME (xs, Q, P)
else
(case extract_conj false xs P of
SOME (xs, eq, P') => SOME (xs, eq, Data.conj $ P' $ Q)
| NONE =>
(case extract_conj false xs Q of
SOME (xs, eq, Q') => SOME (xs, eq, Data.conj $ P $ Q')
| NONE => NONE)));
fun extract_imp fst xs t =
(case Data.dest_imp t of
NONE => NONE
| SOME (P, Q) =>
if def xs P then (if fst then NONE else SOME (xs, P, Q))
else
(case extract_conj false xs P of
SOME (xs, eq, P') => SOME (xs, eq, Data.imp $ P' $ Q)
| NONE =>
(case extract_imp false xs Q of
NONE => NONE
| SOME (xs, eq, Q') => SOME (xs, eq, Data.imp $ P $ Q'))));
fun extract_conj_from_judgment ctxt fst xs t =
if Object_Logic.is_judgment ctxt t
then
let
val judg $ t' = t
in
case extract_conj fst xs t' of
NONE => NONE
| SOME (xs, eq, P) => SOME (xs, judg $ eq, judg $ P)
end
else NONE;
fun extract_implies ctxt fst xs t =
(case try Logic.dest_implies t of
NONE => NONE
| SOME (P, Q) =>
if def xs P then (if fst then NONE else SOME (xs, P, Q))
else
(case extract_conj_from_judgment ctxt false xs P of
SOME (xs, eq, P') => SOME (xs, eq, Logic.implies $ P' $ Q)
| NONE =>
(case extract_implies ctxt false xs Q of
NONE => NONE
| SOME (xs, eq, Q') => (SOME (xs, eq, Logic.implies $ P $ Q')))));
fun extract_quant ctxt extract q =
let
fun exqu xs ((qC as Const (qa, _)) $ Abs (x, T, Q)) =
if qa = q then exqu ((qC, x, T) :: xs) Q else NONE
| exqu xs P = extract ctxt (null xs) xs P
in exqu [] end;
fun iff_reflection_tac ctxt =
resolve_tac ctxt [Data.iff_reflection] 1;
fun qcomm_tac ctxt qcomm qI i =
REPEAT_DETERM (resolve_tac ctxt [qcomm] i THEN resolve_tac ctxt [qI] i);
local
val excomm = Data.ex_comm RS Data.iff_trans;
in
fun prove_one_point_Ex_tac ctxt =
qcomm_tac ctxt excomm Data.iff_exI 1 THEN resolve_tac ctxt [Data.iffI] 1 THEN
ALLGOALS
(EVERY' [eresolve_tac ctxt [Data.exE], REPEAT_DETERM o eresolve_tac ctxt [Data.conjE],
resolve_tac ctxt [Data.exI],
DEPTH_SOLVE_1 o ares_tac ctxt [Data.conjI]])
end;
local
fun tac ctxt =
SELECT_GOAL
(EVERY1 [REPEAT o dresolve_tac ctxt [Data.uncurry],
REPEAT o resolve_tac ctxt [Data.impI],
eresolve_tac ctxt [Data.mp],
REPEAT o eresolve_tac ctxt [Data.conjE],
REPEAT o ares_tac ctxt [Data.conjI]]);
val all_comm = Data.all_comm RS Data.iff_trans;
val All_comm = @{thm swap_params [THEN transitive]};
in
fun prove_one_point_All_tac ctxt =
EVERY1 [qcomm_tac ctxt all_comm Data.iff_allI,
resolve_tac ctxt [Data.iff_allI],
resolve_tac ctxt [Data.iffI],
tac ctxt,
tac ctxt];
fun prove_one_point_all_tac ctxt =
EVERY1 [qcomm_tac ctxt All_comm @{thm equal_allI},
resolve_tac ctxt [@{thm equal_allI}],
CONVERSION (Data.atomize ctxt),
resolve_tac ctxt [@{thm equal_intr_rule}],
tac ctxt,
tac ctxt];
end
fun prove_conv ctxt tu tac =
let
val (goal, ctxt') =
yield_singleton (Variable.import_terms true) (Logic.mk_equals tu) ctxt;
val thm =
Goal.prove ctxt' [] [] goal
(fn {context = ctxt'', ...} => tac ctxt'');
in singleton (Variable.export ctxt' ctxt) thm end;
fun renumber l u (Bound i) =
Bound (if i < l orelse i > u then i else if i = u then l else i + 1)
| renumber l u (s $ t) = renumber l u s $ renumber l u t
| renumber l u (Abs (x, T, t)) = Abs (x, T, renumber (l + 1) (u + 1) t)
| renumber _ _ atom = atom;
fun quantify qC x T xs P =
let
fun quant [] P = P
| quant ((qC, x, T) :: xs) P = quant xs (qC $ Abs (x, T, P));
val n = length xs;
val Q = if n = 0 then P else renumber 0 n P;
in quant xs (qC $ Abs (x, T, Q)) end;
fun rearrange_all ctxt ct =
(case Thm.term_of ct of
F as (all as Const (q, _)) $ Abs (x, T, P) =>
(case extract_quant ctxt extract_implies q P of
NONE => NONE
| SOME (xs, eq, Q) =>
let val R = quantify all x T xs (Logic.implies $ eq $ Q)
in SOME (prove_conv ctxt (F, R) prove_one_point_all_tac) end)
| _ => NONE);
fun rearrange_All ctxt ct =
(case Thm.term_of ct of
F as (all as Const (q, _)) $ Abs (x, T, P) =>
(case extract_quant ctxt (K extract_imp) q P of
NONE => NONE
| SOME (xs, eq, Q) =>
let val R = quantify all x T xs (Data.imp $ eq $ Q)
in SOME (prove_conv ctxt (F, R) (iff_reflection_tac THEN' prove_one_point_All_tac)) end)
| _ => NONE);
fun rearrange_Ball tac ctxt ct =
(case Thm.term_of ct of
F as Ball $ A $ Abs (x, T, P) =>
(case extract_imp true [] P of
NONE => NONE
| SOME (xs, eq, Q) =>
if not (null xs) then NONE
else
let val R = Data.imp $ eq $ Q
in SOME (prove_conv ctxt (F, Ball $ A $ Abs (x, T, R))
(iff_reflection_tac THEN' tac THEN' prove_one_point_All_tac)) end)
| _ => NONE);
fun rearrange_Ex ctxt ct =
(case Thm.term_of ct of
F as (ex as Const (q, _)) $ Abs (x, T, P) =>
(case extract_quant ctxt (K extract_conj) q P of
NONE => NONE
| SOME (xs, eq, Q) =>
let val R = quantify ex x T xs (Data.conj $ eq $ Q)
in SOME (prove_conv ctxt (F, R) (iff_reflection_tac THEN' prove_one_point_Ex_tac)) end)
| _ => NONE);
fun rearrange_Bex tac ctxt ct =
(case Thm.term_of ct of
F as Bex $ A $ Abs (x, T, P) =>
(case extract_conj true [] P of
NONE => NONE
| SOME (xs, eq, Q) =>
if not (null xs) then NONE
else SOME (prove_conv ctxt (F, Bex $ A $ Abs (x, T, Data.conj $ eq $ Q))
(iff_reflection_tac THEN' tac THEN' prove_one_point_Ex_tac)))
| _ => NONE);
fun rearrange_Collect tac ctxt ct =
(case Thm.term_of ct of
F as Collect $ Abs (x, T, P) =>
(case extract_conj true [] P of
NONE => NONE
| SOME (_, eq, Q) =>
let val R = Collect $ Abs (x, T, Data.conj $ eq $ Q)
in SOME (prove_conv ctxt (F, R) (iff_reflection_tac THEN' tac)) end)
| _ => NONE);
end;