| author | wenzelm | 
| Thu, 28 Dec 2017 12:36:11 +0100 | |
| changeset 67287 | 7ef1c5dada12 | 
| parent 60793 | bbcd4ab6d26e | 
| child 67721 | 5348bea4accd | 
| permissions | -rw-r--r-- | 
| 10805 | 1  | 
(* Title: Pure/tactic.ML  | 
2  | 
Author: Lawrence C Paulson, Cambridge University Computer Laboratory  | 
|
| 0 | 3  | 
|
| 29276 | 4  | 
Fundamental tactics.  | 
| 0 | 5  | 
*)  | 
6  | 
||
| 11774 | 7  | 
signature BASIC_TACTIC =  | 
8  | 
sig  | 
|
| 23223 | 9  | 
val trace_goalno_tac: (int -> tactic) -> int -> tactic  | 
| 36546 | 10  | 
val rule_by_tactic: Proof.context -> tactic -> thm -> thm  | 
| 
58963
 
26bf09b95dda
proper context for assume_tac (atac remains as fall-back without context);
 
wenzelm 
parents: 
58957 
diff
changeset
 | 
11  | 
val assume_tac: Proof.context -> int -> tactic  | 
| 23223 | 12  | 
val eq_assume_tac: int -> tactic  | 
| 
58956
 
a816aa3ff391
proper context for compose_tac, Splitter.split_tac (relevant for unify trace options);
 
wenzelm 
parents: 
58950 
diff
changeset
 | 
13  | 
val compose_tac: Proof.context -> (bool * thm * int) -> int -> tactic  | 
| 23223 | 14  | 
val make_elim: thm -> thm  | 
| 
59498
 
50b60f501b05
proper context for resolve_tac, eresolve_tac, dresolve_tac, forward_tac etc.;
 
wenzelm 
parents: 
59164 
diff
changeset
 | 
15  | 
val biresolve0_tac: (bool * thm) list -> int -> tactic  | 
| 
 
50b60f501b05
proper context for resolve_tac, eresolve_tac, dresolve_tac, forward_tac etc.;
 
wenzelm 
parents: 
59164 
diff
changeset
 | 
16  | 
val biresolve_tac: Proof.context -> (bool * thm) list -> int -> tactic  | 
| 
 
50b60f501b05
proper context for resolve_tac, eresolve_tac, dresolve_tac, forward_tac etc.;
 
wenzelm 
parents: 
59164 
diff
changeset
 | 
17  | 
val resolve0_tac: thm list -> int -> tactic  | 
| 
 
50b60f501b05
proper context for resolve_tac, eresolve_tac, dresolve_tac, forward_tac etc.;
 
wenzelm 
parents: 
59164 
diff
changeset
 | 
18  | 
val resolve_tac: Proof.context -> thm list -> int -> tactic  | 
| 
 
50b60f501b05
proper context for resolve_tac, eresolve_tac, dresolve_tac, forward_tac etc.;
 
wenzelm 
parents: 
59164 
diff
changeset
 | 
19  | 
val eresolve0_tac: thm list -> int -> tactic  | 
| 
 
50b60f501b05
proper context for resolve_tac, eresolve_tac, dresolve_tac, forward_tac etc.;
 
wenzelm 
parents: 
59164 
diff
changeset
 | 
20  | 
val eresolve_tac: Proof.context -> thm list -> int -> tactic  | 
| 
 
50b60f501b05
proper context for resolve_tac, eresolve_tac, dresolve_tac, forward_tac etc.;
 
wenzelm 
parents: 
59164 
diff
changeset
 | 
21  | 
val forward_tac: Proof.context -> thm list -> int -> tactic  | 
| 
 
50b60f501b05
proper context for resolve_tac, eresolve_tac, dresolve_tac, forward_tac etc.;
 
wenzelm 
parents: 
59164 
diff
changeset
 | 
22  | 
val dresolve0_tac: thm list -> int -> tactic  | 
| 
 
50b60f501b05
proper context for resolve_tac, eresolve_tac, dresolve_tac, forward_tac etc.;
 
wenzelm 
parents: 
59164 
diff
changeset
 | 
23  | 
val dresolve_tac: Proof.context -> thm list -> int -> tactic  | 
| 60774 | 24  | 
val ares_tac: Proof.context -> thm list -> int -> tactic  | 
| 
59498
 
50b60f501b05
proper context for resolve_tac, eresolve_tac, dresolve_tac, forward_tac etc.;
 
wenzelm 
parents: 
59164 
diff
changeset
 | 
25  | 
val solve_tac: Proof.context -> thm list -> int -> tactic  | 
| 58957 | 26  | 
val bimatch_tac: Proof.context -> (bool * thm) list -> int -> tactic  | 
27  | 
val match_tac: Proof.context -> thm list -> int -> tactic  | 
|
28  | 
val ematch_tac: Proof.context -> thm list -> int -> tactic  | 
|
29  | 
val dmatch_tac: Proof.context -> thm list -> int -> tactic  | 
|
| 
58950
 
d07464875dd4
optional proof context for unify operations, for the sake of proper local options;
 
wenzelm 
parents: 
58837 
diff
changeset
 | 
30  | 
val flexflex_tac: Proof.context -> tactic  | 
| 23223 | 31  | 
val distinct_subgoal_tac: int -> tactic  | 
32  | 
val distinct_subgoals_tac: tactic  | 
|
| 46704 | 33  | 
val cut_tac: thm -> int -> tactic  | 
| 23223 | 34  | 
val cut_rules_tac: thm list -> int -> tactic  | 
35  | 
val cut_facts_tac: thm list -> int -> tactic  | 
|
36  | 
val filter_thms: (term * term -> bool) -> int * term * thm list -> thm list  | 
|
| 59164 | 37  | 
val biresolution_from_nets_tac: Proof.context ->  | 
38  | 
    ('a list -> (bool * thm) list) -> bool -> 'a Net.net * 'a Net.net -> int -> tactic
 | 
|
39  | 
val biresolve_from_nets_tac: Proof.context ->  | 
|
40  | 
(int * (bool * thm)) Net.net * (int * (bool * thm)) Net.net -> int -> tactic  | 
|
41  | 
val bimatch_from_nets_tac: Proof.context ->  | 
|
42  | 
(int * (bool * thm)) Net.net * (int * (bool * thm)) Net.net -> int -> tactic  | 
|
43  | 
val filt_resolve_from_net_tac: Proof.context -> int -> (int * thm) Net.net -> int -> tactic  | 
|
44  | 
val resolve_from_net_tac: Proof.context -> (int * thm) Net.net -> int -> tactic  | 
|
45  | 
val match_from_net_tac: Proof.context -> (int * thm) Net.net -> int -> tactic  | 
|
| 23223 | 46  | 
val subgoals_of_brl: bool * thm -> int  | 
47  | 
val lessb: (bool * thm) * (bool * thm) -> bool  | 
|
| 
27243
 
d549b5b0f344
removed obsolete global instantiation tactics (cf. Isar/rule_insts.ML);
 
wenzelm 
parents: 
27209 
diff
changeset
 | 
48  | 
val rename_tac: string list -> int -> tactic  | 
| 23223 | 49  | 
val rotate_tac: int -> int -> tactic  | 
50  | 
val defer_tac: int -> tactic  | 
|
| 49865 | 51  | 
val prefer_tac: int -> tactic  | 
| 
59498
 
50b60f501b05
proper context for resolve_tac, eresolve_tac, dresolve_tac, forward_tac etc.;
 
wenzelm 
parents: 
59164 
diff
changeset
 | 
52  | 
val filter_prems_tac: Proof.context -> (term -> bool) -> int -> tactic  | 
| 11774 | 53  | 
end;  | 
| 0 | 54  | 
|
| 11774 | 55  | 
signature TACTIC =  | 
56  | 
sig  | 
|
57  | 
include BASIC_TACTIC  | 
|
| 23223 | 58  | 
val insert_tagged_brl: 'a * (bool * thm) ->  | 
59  | 
    ('a * (bool * thm)) Net.net * ('a * (bool * thm)) Net.net ->
 | 
|
60  | 
      ('a * (bool * thm)) Net.net * ('a * (bool * thm)) Net.net
 | 
|
61  | 
val delete_tagged_brl: bool * thm ->  | 
|
62  | 
    ('a * (bool * thm)) Net.net * ('a * (bool * thm)) Net.net ->
 | 
|
63  | 
      ('a * (bool * thm)) Net.net * ('a * (bool * thm)) Net.net
 | 
|
64  | 
  val eq_kbrl: ('a * (bool * thm)) * ('a * (bool * thm)) -> bool
 | 
|
| 32971 | 65  | 
val build_net: thm list -> (int * thm) Net.net  | 
| 11774 | 66  | 
end;  | 
| 0 | 67  | 
|
| 11774 | 68  | 
structure Tactic: TACTIC =  | 
| 0 | 69  | 
struct  | 
70  | 
||
| 1501 | 71  | 
(*Discover which goal is chosen: SOMEGOAL(trace_goalno_tac tac) *)  | 
| 10817 | 72  | 
fun trace_goalno_tac tac i st =  | 
| 4270 | 73  | 
case Seq.pull(tac i st) of  | 
| 15531 | 74  | 
NONE => Seq.empty  | 
| 12262 | 75  | 
      | seqcell => (tracing ("Subgoal " ^ string_of_int i ^ " selected");
 | 
| 10805 | 76  | 
Seq.make(fn()=> seqcell));  | 
| 0 | 77  | 
|
78  | 
(*Makes a rule by applying a tactic to an existing rule*)  | 
|
| 36546 | 79  | 
fun rule_by_tactic ctxt tac rl =  | 
| 
19925
 
3f9341831812
eliminated freeze/varify in favour of Variable.import/export/trade;
 
wenzelm 
parents: 
19743 
diff
changeset
 | 
80  | 
let  | 
| 
52087
 
f3075fc4f5f6
more precise treatment of theory vs. Proof.context;
 
wenzelm 
parents: 
51602 
diff
changeset
 | 
81  | 
val thy = Proof_Context.theory_of ctxt;  | 
| 36546 | 82  | 
val ctxt' = Variable.declare_thm rl ctxt;  | 
| 
52087
 
f3075fc4f5f6
more precise treatment of theory vs. Proof.context;
 
wenzelm 
parents: 
51602 
diff
changeset
 | 
83  | 
val ((_, [st]), ctxt'') = Variable.import true [Thm.transfer thy rl] ctxt';  | 
| 
19925
 
3f9341831812
eliminated freeze/varify in favour of Variable.import/export/trade;
 
wenzelm 
parents: 
19743 
diff
changeset
 | 
84  | 
in  | 
| 
 
3f9341831812
eliminated freeze/varify in favour of Variable.import/export/trade;
 
wenzelm 
parents: 
19743 
diff
changeset
 | 
85  | 
(case Seq.pull (tac st) of  | 
| 
 
3f9341831812
eliminated freeze/varify in favour of Variable.import/export/trade;
 
wenzelm 
parents: 
19743 
diff
changeset
 | 
86  | 
      NONE => raise THM ("rule_by_tactic", 0, [rl])
 | 
| 36546 | 87  | 
| SOME (st', _) => zero_var_indexes (singleton (Variable.export ctxt'' ctxt') st'))  | 
| 2688 | 88  | 
end;  | 
| 10817 | 89  | 
|
| 
19925
 
3f9341831812
eliminated freeze/varify in favour of Variable.import/export/trade;
 
wenzelm 
parents: 
19743 
diff
changeset
 | 
90  | 
|
| 0 | 91  | 
(*** Basic tactics ***)  | 
92  | 
||
93  | 
(*** The following fail if the goal number is out of range:  | 
|
94  | 
thus (REPEAT (resolve_tac rules i)) stops once subgoal i disappears. *)  | 
|
95  | 
||
96  | 
(*Solve subgoal i by assumption*)  | 
|
| 
58963
 
26bf09b95dda
proper context for assume_tac (atac remains as fall-back without context);
 
wenzelm 
parents: 
58957 
diff
changeset
 | 
97  | 
fun assume_tac ctxt i = PRIMSEQ (Thm.assumption (SOME ctxt) i);  | 
| 0 | 98  | 
|
99  | 
(*Solve subgoal i by assumption, using no unification*)  | 
|
| 31945 | 100  | 
fun eq_assume_tac i = PRIMITIVE (Thm.eq_assumption i);  | 
| 0 | 101  | 
|
| 23223 | 102  | 
|
| 0 | 103  | 
(** Resolution/matching tactics **)  | 
104  | 
||
105  | 
(*The composition rule/state: no lifting or var renaming.  | 
|
| 31945 | 106  | 
The arg = (bires_flg, orule, m); see Thm.bicompose for explanation.*)  | 
| 
58956
 
a816aa3ff391
proper context for compose_tac, Splitter.split_tac (relevant for unify trace options);
 
wenzelm 
parents: 
58950 
diff
changeset
 | 
107  | 
fun compose_tac ctxt arg i =  | 
| 
 
a816aa3ff391
proper context for compose_tac, Splitter.split_tac (relevant for unify trace options);
 
wenzelm 
parents: 
58950 
diff
changeset
 | 
108  | 
  PRIMSEQ (Thm.bicompose (SOME ctxt) {flatten = true, match = false, incremented = false} arg i);
 | 
| 0 | 109  | 
|
110  | 
(*Converts a "destruct" rule like P&Q==>P to an "elimination" rule  | 
|
111  | 
like [| P&Q; P==>R |] ==> R *)  | 
|
112  | 
fun make_elim rl = zero_var_indexes (rl RS revcut_rl);  | 
|
113  | 
||
114  | 
(*Attack subgoal i by resolution, using flags to indicate elimination rules*)  | 
|
| 
59498
 
50b60f501b05
proper context for resolve_tac, eresolve_tac, dresolve_tac, forward_tac etc.;
 
wenzelm 
parents: 
59164 
diff
changeset
 | 
115  | 
fun biresolve0_tac brules i = PRIMSEQ (Thm.biresolution NONE false brules i);  | 
| 
 
50b60f501b05
proper context for resolve_tac, eresolve_tac, dresolve_tac, forward_tac etc.;
 
wenzelm 
parents: 
59164 
diff
changeset
 | 
116  | 
fun biresolve_tac ctxt brules i = PRIMSEQ (Thm.biresolution (SOME ctxt) false brules i);  | 
| 0 | 117  | 
|
118  | 
(*Resolution: the simple case, works for introduction rules*)  | 
|
| 
59498
 
50b60f501b05
proper context for resolve_tac, eresolve_tac, dresolve_tac, forward_tac etc.;
 
wenzelm 
parents: 
59164 
diff
changeset
 | 
119  | 
fun resolve0_tac rules = biresolve0_tac (map (pair false) rules);  | 
| 
 
50b60f501b05
proper context for resolve_tac, eresolve_tac, dresolve_tac, forward_tac etc.;
 
wenzelm 
parents: 
59164 
diff
changeset
 | 
120  | 
fun resolve_tac ctxt rules = biresolve_tac ctxt (map (pair false) rules);  | 
| 0 | 121  | 
|
122  | 
(*Resolution with elimination rules only*)  | 
|
| 
59498
 
50b60f501b05
proper context for resolve_tac, eresolve_tac, dresolve_tac, forward_tac etc.;
 
wenzelm 
parents: 
59164 
diff
changeset
 | 
123  | 
fun eresolve0_tac rules = biresolve0_tac (map (pair true) rules);  | 
| 
 
50b60f501b05
proper context for resolve_tac, eresolve_tac, dresolve_tac, forward_tac etc.;
 
wenzelm 
parents: 
59164 
diff
changeset
 | 
124  | 
fun eresolve_tac ctxt rules = biresolve_tac ctxt (map (pair true) rules);  | 
| 0 | 125  | 
|
126  | 
(*Forward reasoning using destruction rules.*)  | 
|
| 60776 | 127  | 
fun forward_tac ctxt rls = resolve_tac ctxt (map make_elim rls) THEN' assume_tac ctxt;  | 
| 0 | 128  | 
|
129  | 
(*Like forward_tac, but deletes the assumption after use.*)  | 
|
| 
59498
 
50b60f501b05
proper context for resolve_tac, eresolve_tac, dresolve_tac, forward_tac etc.;
 
wenzelm 
parents: 
59164 
diff
changeset
 | 
130  | 
fun dresolve0_tac rls = eresolve0_tac (map make_elim rls);  | 
| 
 
50b60f501b05
proper context for resolve_tac, eresolve_tac, dresolve_tac, forward_tac etc.;
 
wenzelm 
parents: 
59164 
diff
changeset
 | 
131  | 
fun dresolve_tac ctxt rls = eresolve_tac ctxt (map make_elim rls);  | 
| 0 | 132  | 
|
| 60774 | 133  | 
(*Use an assumption or some rules*)  | 
134  | 
fun ares_tac ctxt rules = assume_tac ctxt ORELSE' resolve_tac ctxt rules;  | 
|
| 0 | 135  | 
|
| 
59498
 
50b60f501b05
proper context for resolve_tac, eresolve_tac, dresolve_tac, forward_tac etc.;
 
wenzelm 
parents: 
59164 
diff
changeset
 | 
136  | 
fun solve_tac ctxt rules = resolve_tac ctxt rules THEN_ALL_NEW assume_tac ctxt;  | 
| 5263 | 137  | 
|
| 0 | 138  | 
(*Matching tactics -- as above, but forbid updating of state*)  | 
| 58957 | 139  | 
fun bimatch_tac ctxt brules i = PRIMSEQ (Thm.biresolution (SOME ctxt) true brules i);  | 
140  | 
fun match_tac ctxt rules = bimatch_tac ctxt (map (pair false) rules);  | 
|
141  | 
fun ematch_tac ctxt rules = bimatch_tac ctxt (map (pair true) rules);  | 
|
142  | 
fun dmatch_tac ctxt rls = ematch_tac ctxt (map make_elim rls);  | 
|
| 0 | 143  | 
|
144  | 
(*Smash all flex-flex disagreement pairs in the proof state.*)  | 
|
| 
58950
 
d07464875dd4
optional proof context for unify operations, for the sake of proper local options;
 
wenzelm 
parents: 
58837 
diff
changeset
 | 
145  | 
fun flexflex_tac ctxt = PRIMSEQ (Thm.flexflex_rule (SOME ctxt));  | 
| 0 | 146  | 
|
| 
19056
 
6ac9dfe98e54
sane version of distinct_subgoals_tac, based on composition with Drule.distinct_prems_rl;
 
wenzelm 
parents: 
18977 
diff
changeset
 | 
147  | 
(*Remove duplicate subgoals.*)  | 
| 50081 | 148  | 
val permute_tac = PRIMITIVE oo Thm.permute_prems;  | 
| 
22560
 
f19ddf96c323
now exports distinct_subgoal_tac (needed by MetisAPI)
 
paulson 
parents: 
22360 
diff
changeset
 | 
149  | 
fun distinct_tac (i, k) =  | 
| 50081 | 150  | 
permute_tac 0 (i - 1) THEN  | 
151  | 
permute_tac 1 (k - 1) THEN  | 
|
| 
51602
 
4c7fdc00bd59
tuned -- Drule.comp_no_flatten includes Drule.incr_indexes already (NB: result should be deterministic by construction);
 
wenzelm 
parents: 
50239 
diff
changeset
 | 
152  | 
PRIMITIVE (fn st => Drule.comp_no_flatten (st, 0) 1 Drule.distinct_prems_rl) THEN  | 
| 50081 | 153  | 
permute_tac 1 (1 - k) THEN  | 
154  | 
permute_tac 0 (1 - i);  | 
|
| 
22560
 
f19ddf96c323
now exports distinct_subgoal_tac (needed by MetisAPI)
 
paulson 
parents: 
22360 
diff
changeset
 | 
155  | 
|
| 
 
f19ddf96c323
now exports distinct_subgoal_tac (needed by MetisAPI)
 
paulson 
parents: 
22360 
diff
changeset
 | 
156  | 
fun distinct_subgoal_tac i st =  | 
| 33957 | 157  | 
(case drop (i - 1) (Thm.prems_of st) of  | 
| 
22560
 
f19ddf96c323
now exports distinct_subgoal_tac (needed by MetisAPI)
 
paulson 
parents: 
22360 
diff
changeset
 | 
158  | 
[] => no_tac st  | 
| 
 
f19ddf96c323
now exports distinct_subgoal_tac (needed by MetisAPI)
 
paulson 
parents: 
22360 
diff
changeset
 | 
159  | 
| A :: Bs =>  | 
| 
 
f19ddf96c323
now exports distinct_subgoal_tac (needed by MetisAPI)
 
paulson 
parents: 
22360 
diff
changeset
 | 
160  | 
st |> EVERY (fold (fn (B, k) =>  | 
| 23223 | 161  | 
if A aconv B then cons (distinct_tac (i, k)) else I) (Bs ~~ (1 upto length Bs)) []));  | 
| 
22560
 
f19ddf96c323
now exports distinct_subgoal_tac (needed by MetisAPI)
 
paulson 
parents: 
22360 
diff
changeset
 | 
162  | 
|
| 10817 | 163  | 
fun distinct_subgoals_tac state =  | 
| 
19056
 
6ac9dfe98e54
sane version of distinct_subgoals_tac, based on composition with Drule.distinct_prems_rl;
 
wenzelm 
parents: 
18977 
diff
changeset
 | 
164  | 
let  | 
| 
 
6ac9dfe98e54
sane version of distinct_subgoals_tac, based on composition with Drule.distinct_prems_rl;
 
wenzelm 
parents: 
18977 
diff
changeset
 | 
165  | 
val goals = Thm.prems_of state;  | 
| 
 
6ac9dfe98e54
sane version of distinct_subgoals_tac, based on composition with Drule.distinct_prems_rl;
 
wenzelm 
parents: 
18977 
diff
changeset
 | 
166  | 
val dups = distinct (eq_fst (op aconv)) (goals ~~ (1 upto length goals));  | 
| 
 
6ac9dfe98e54
sane version of distinct_subgoals_tac, based on composition with Drule.distinct_prems_rl;
 
wenzelm 
parents: 
18977 
diff
changeset
 | 
167  | 
in EVERY (rev (map (distinct_subgoal_tac o snd) dups)) state end;  | 
| 
3409
 
c0466958df5d
Tidying of signature.  More robust renaming in freeze_thaw.
 
paulson 
parents: 
2814 
diff
changeset
 | 
168  | 
|
| 1951 | 169  | 
|
| 
270
 
d506ea00c825
tactic/make_elim_preserve: recoded to avoid using lift_inst_rule.  Instead
 
lcp 
parents: 
230 
diff
changeset
 | 
170  | 
(*** Applications of cut_rl ***)  | 
| 0 | 171  | 
|
172  | 
(*The conclusion of the rule gets assumed in subgoal i,  | 
|
173  | 
while subgoal i+1,... are the premises of the rule.*)  | 
|
| 
59498
 
50b60f501b05
proper context for resolve_tac, eresolve_tac, dresolve_tac, forward_tac etc.;
 
wenzelm 
parents: 
59164 
diff
changeset
 | 
174  | 
fun cut_tac rule i = resolve0_tac [cut_rl] i THEN resolve0_tac [rule] (i + 1);  | 
| 0 | 175  | 
|
| 
13650
 
31bd2a8cdbe2
fixing the cut_tac method to work when there are no instantiations and the
 
paulson 
parents: 
13559 
diff
changeset
 | 
176  | 
(*"Cut" a list of rules into the goal. Their premises will become new  | 
| 
 
31bd2a8cdbe2
fixing the cut_tac method to work when there are no instantiations and the
 
paulson 
parents: 
13559 
diff
changeset
 | 
177  | 
subgoals.*)  | 
| 46704 | 178  | 
fun cut_rules_tac ths i = EVERY (map (fn th => cut_tac th i) ths);  | 
| 
13650
 
31bd2a8cdbe2
fixing the cut_tac method to work when there are no instantiations and the
 
paulson 
parents: 
13559 
diff
changeset
 | 
179  | 
|
| 
 
31bd2a8cdbe2
fixing the cut_tac method to work when there are no instantiations and the
 
paulson 
parents: 
13559 
diff
changeset
 | 
180  | 
(*As above, but inserts only facts (unconditional theorems);  | 
| 
 
31bd2a8cdbe2
fixing the cut_tac method to work when there are no instantiations and the
 
paulson 
parents: 
13559 
diff
changeset
 | 
181  | 
generates no additional subgoals. *)  | 
| 20232 | 182  | 
fun cut_facts_tac ths = cut_rules_tac (filter Thm.no_prems ths);  | 
| 0 | 183  | 
|
184  | 
||
185  | 
(**** Indexing and filtering of theorems ****)  | 
|
186  | 
||
187  | 
(*Returns the list of potentially resolvable theorems for the goal "prem",  | 
|
| 10805 | 188  | 
using the predicate could(subgoal,concl).  | 
| 0 | 189  | 
Resulting list is no longer than "limit"*)  | 
190  | 
fun filter_thms could (limit, prem, ths) =  | 
|
191  | 
let val pb = Logic.strip_assums_concl prem; (*delete assumptions*)  | 
|
192  | 
fun filtr (limit, []) = []  | 
|
| 10805 | 193  | 
| filtr (limit, th::ths) =  | 
194  | 
if limit=0 then []  | 
|
| 59582 | 195  | 
else if could(pb, Thm.concl_of th) then th :: filtr(limit-1, ths)  | 
| 10805 | 196  | 
else filtr(limit,ths)  | 
| 0 | 197  | 
in filtr(limit,ths) end;  | 
198  | 
||
199  | 
||
200  | 
(*** biresolution and resolution using nets ***)  | 
|
201  | 
||
202  | 
(** To preserve the order of the rules, tag them with increasing integers **)  | 
|
203  | 
||
204  | 
(*insert one tagged brl into the pair of nets*)  | 
|
| 23178 | 205  | 
fun insert_tagged_brl (kbrl as (k, (eres, th))) (inet, enet) =  | 
| 12320 | 206  | 
if eres then  | 
207  | 
(case try Thm.major_prem_of th of  | 
|
| 16809 | 208  | 
SOME prem => (inet, Net.insert_term (K false) (prem, kbrl) enet)  | 
| 15531 | 209  | 
| NONE => error "insert_tagged_brl: elimination rule with no premises")  | 
| 59582 | 210  | 
else (Net.insert_term (K false) (Thm.concl_of th, kbrl) inet, enet);  | 
| 0 | 211  | 
|
| 12320 | 212  | 
(*delete one kbrl from the pair of nets*)  | 
| 
22360
 
26ead7ed4f4b
moved eq_thm etc. to structure Thm in Pure/more_thm.ML;
 
wenzelm 
parents: 
21708 
diff
changeset
 | 
213  | 
fun eq_kbrl ((_, (_, th)), (_, (_, th'))) = Thm.eq_thm_prop (th, th')  | 
| 16809 | 214  | 
|
| 23178 | 215  | 
fun delete_tagged_brl (brl as (eres, th)) (inet, enet) =  | 
| 13925 | 216  | 
(if eres then  | 
| 12320 | 217  | 
(case try Thm.major_prem_of th of  | 
| 16809 | 218  | 
SOME prem => (inet, Net.delete_term eq_kbrl (prem, ((), brl)) enet)  | 
| 15531 | 219  | 
| NONE => (inet, enet)) (*no major premise: ignore*)  | 
| 16809 | 220  | 
else (Net.delete_term eq_kbrl (Thm.concl_of th, ((), brl)) inet, enet))  | 
| 13925 | 221  | 
handle Net.DELETE => (inet,enet);  | 
| 1801 | 222  | 
|
223  | 
||
| 10817 | 224  | 
(*biresolution using a pair of nets rather than rules.  | 
| 
3706
 
e57b5902822f
Generalized and exported biresolution_from_nets_tac to allow the declaration
 
paulson 
parents: 
3575 
diff
changeset
 | 
225  | 
function "order" must sort and possibly filter the list of brls.  | 
| 
 
e57b5902822f
Generalized and exported biresolution_from_nets_tac to allow the declaration
 
paulson 
parents: 
3575 
diff
changeset
 | 
226  | 
boolean "match" indicates matching or unification.*)  | 
| 59164 | 227  | 
fun biresolution_from_nets_tac ctxt order match (inet, enet) =  | 
| 0 | 228  | 
SUBGOAL  | 
| 59164 | 229  | 
(fn (prem, i) =>  | 
230  | 
let  | 
|
231  | 
val hyps = Logic.strip_assums_hyp prem;  | 
|
232  | 
val concl = Logic.strip_assums_concl prem;  | 
|
233  | 
val kbrls = Net.unify_term inet concl @ maps (Net.unify_term enet) hyps;  | 
|
234  | 
in PRIMSEQ (Thm.biresolution (SOME ctxt) match (order kbrls) i) end);  | 
|
| 0 | 235  | 
|
| 
3706
 
e57b5902822f
Generalized and exported biresolution_from_nets_tac to allow the declaration
 
paulson 
parents: 
3575 
diff
changeset
 | 
236  | 
(*versions taking pre-built nets. No filtering of brls*)  | 
| 59164 | 237  | 
fun biresolve_from_nets_tac ctxt = biresolution_from_nets_tac ctxt order_list false;  | 
238  | 
fun bimatch_from_nets_tac ctxt = biresolution_from_nets_tac ctxt order_list true;  | 
|
| 0 | 239  | 
|
240  | 
||
241  | 
(*** Simpler version for resolve_tac -- only one net, and no hyps ***)  | 
|
242  | 
||
243  | 
(*insert one tagged rl into the net*)  | 
|
| 23178 | 244  | 
fun insert_krl (krl as (k,th)) =  | 
| 59582 | 245  | 
Net.insert_term (K false) (Thm.concl_of th, krl);  | 
| 0 | 246  | 
|
247  | 
(*build a net of rules for resolution*)  | 
|
| 10817 | 248  | 
fun build_net rls =  | 
| 
30558
 
2ef9892114fd
renamed Tactic.taglist/untaglist/orderlist to tag_list/untag_list/order_list (in library.ML);
 
wenzelm 
parents: 
29276 
diff
changeset
 | 
249  | 
fold_rev insert_krl (tag_list 1 rls) Net.empty;  | 
| 0 | 250  | 
|
251  | 
(*resolution using a net rather than rules; pred supports filt_resolve_tac*)  | 
|
| 59164 | 252  | 
fun filt_resolution_from_net_tac ctxt match pred net =  | 
253  | 
SUBGOAL (fn (prem, i) =>  | 
|
| 
58950
 
d07464875dd4
optional proof context for unify operations, for the sake of proper local options;
 
wenzelm 
parents: 
58837 
diff
changeset
 | 
254  | 
let val krls = Net.unify_term net (Logic.strip_assums_concl prem) in  | 
| 
 
d07464875dd4
optional proof context for unify operations, for the sake of proper local options;
 
wenzelm 
parents: 
58837 
diff
changeset
 | 
255  | 
if pred krls then  | 
| 59164 | 256  | 
PRIMSEQ (Thm.biresolution (SOME ctxt) match (map (pair false) (order_list krls)) i)  | 
| 
58950
 
d07464875dd4
optional proof context for unify operations, for the sake of proper local options;
 
wenzelm 
parents: 
58837 
diff
changeset
 | 
257  | 
else no_tac  | 
| 
 
d07464875dd4
optional proof context for unify operations, for the sake of proper local options;
 
wenzelm 
parents: 
58837 
diff
changeset
 | 
258  | 
end);  | 
| 0 | 259  | 
|
260  | 
(*Resolve the subgoal using the rules (making a net) unless too flexible,  | 
|
261  | 
which means more than maxr rules are unifiable. *)  | 
|
| 59164 | 262  | 
fun filt_resolve_from_net_tac ctxt maxr net =  | 
263  | 
let fun pred krls = length krls <= maxr  | 
|
264  | 
in filt_resolution_from_net_tac ctxt false pred net end;  | 
|
| 0 | 265  | 
|
266  | 
(*versions taking pre-built nets*)  | 
|
| 59164 | 267  | 
fun resolve_from_net_tac ctxt = filt_resolution_from_net_tac ctxt false (K true);  | 
268  | 
fun match_from_net_tac ctxt = filt_resolution_from_net_tac ctxt true (K true);  | 
|
| 0 | 269  | 
|
270  | 
||
271  | 
(*** For Natural Deduction using (bires_flg, rule) pairs ***)  | 
|
272  | 
||
273  | 
(*The number of new subgoals produced by the brule*)  | 
|
| 59582 | 274  | 
fun subgoals_of_brl (true, rule) = Thm.nprems_of rule - 1  | 
275  | 
| subgoals_of_brl (false, rule) = Thm.nprems_of rule;  | 
|
| 0 | 276  | 
|
277  | 
(*Less-than test: for sorting to minimize number of new subgoals*)  | 
|
278  | 
fun lessb (brl1,brl2) = subgoals_of_brl brl1 < subgoals_of_brl brl2;  | 
|
279  | 
||
280  | 
||
| 
27243
 
d549b5b0f344
removed obsolete global instantiation tactics (cf. Isar/rule_insts.ML);
 
wenzelm 
parents: 
27209 
diff
changeset
 | 
281  | 
(*Renaming of parameters in a subgoal*)  | 
| 
 
d549b5b0f344
removed obsolete global instantiation tactics (cf. Isar/rule_insts.ML);
 
wenzelm 
parents: 
27209 
diff
changeset
 | 
282  | 
fun rename_tac xs i =  | 
| 59584 | 283  | 
case find_first (not o Symbol_Pos.is_identifier) xs of  | 
| 15531 | 284  | 
      SOME x => error ("Not an identifier: " ^ x)
 | 
| 31945 | 285  | 
| NONE => PRIMITIVE (Thm.rename_params_rule (xs, i));  | 
| 9535 | 286  | 
|
| 1501 | 287  | 
(*rotate_tac n i: rotate the assumptions of subgoal i by n positions, from  | 
288  | 
right to left if n is positive, and from left to right if n is negative.*)  | 
|
| 
2672
 
85d7e800d754
Replaced "flat" by the Basis Library function List.concat
 
paulson 
parents: 
2580 
diff
changeset
 | 
289  | 
fun rotate_tac 0 i = all_tac  | 
| 31945 | 290  | 
| rotate_tac k i = PRIMITIVE (Thm.rotate_rule k i);  | 
| 1209 | 291  | 
|
| 59749 | 292  | 
(*Rotate the given subgoal to be the last.*)  | 
| 31945 | 293  | 
fun defer_tac i = PRIMITIVE (Thm.permute_prems (i - 1) 1);  | 
| 
7248
 
322151fe6f02
new primitive rule permute_prems to underlie defer_tac and rotate_prems
 
paulson 
parents: 
6979 
diff
changeset
 | 
294  | 
|
| 59749 | 295  | 
(*Rotate the given subgoal to be the first.*)  | 
| 49865 | 296  | 
fun prefer_tac i = PRIMITIVE (Thm.permute_prems (i - 1) 1 #> Thm.permute_prems 0 ~1);  | 
297  | 
||
| 59749 | 298  | 
(*Remove premises that do not satisfy pred; fails if all prems satisfy pred.*)  | 
299  | 
fun filter_prems_tac ctxt pred =  | 
|
300  | 
let  | 
|
301  | 
fun Then NONE tac = SOME tac  | 
|
302  | 
| Then (SOME tac) tac' = SOME (tac THEN' tac');  | 
|
303  | 
fun thins H (tac, n) =  | 
|
304  | 
if pred H then (tac, n + 1)  | 
|
305  | 
else (Then tac (rotate_tac n THEN' eresolve_tac ctxt [thin_rl]), 0);  | 
|
306  | 
in  | 
|
307  | 
SUBGOAL (fn (goal, i) =>  | 
|
308  | 
let val Hs = Logic.strip_assums_hyp goal in  | 
|
309  | 
(case fst (fold thins Hs (NONE, 0)) of  | 
|
310  | 
NONE => no_tac  | 
|
311  | 
| SOME tac => tac i)  | 
|
312  | 
end)  | 
|
| 5974 | 313  | 
end;  | 
314  | 
||
| 0 | 315  | 
end;  | 
| 1501 | 316  | 
|
| 32971 | 317  | 
structure Basic_Tactic: BASIC_TACTIC = Tactic;  | 
318  | 
open Basic_Tactic;  |