author | wenzelm |
Mon, 11 Sep 2023 19:30:48 +0200 | |
changeset 78659 | b5f3d1051b13 |
parent 77879 | dd222e2af01a |
child 78812 | d769a183d51d |
permissions | -rw-r--r-- |
29269
5c25a2012975
moved term order operations to structure TermOrd (cf. Pure/term_ord.ML);
wenzelm
parents:
29064
diff
changeset
|
1 |
(* Title: HOL/Statespace/distinct_tree_prover.ML |
74588
3cc363e8bfb2
cleanup; add Apple reference
Norbert Schirmer <nschirmer@apple.com>
parents:
74587
diff
changeset
|
2 |
Author: Norbert Schirmer, TU Muenchen, 2007 |
3cc363e8bfb2
cleanup; add Apple reference
Norbert Schirmer <nschirmer@apple.com>
parents:
74587
diff
changeset
|
3 |
Author: Norbert Schirmer, Apple, 2021 |
25171 | 4 |
*) |
5 |
||
25408 | 6 |
signature DISTINCT_TREE_PROVER = |
7 |
sig |
|
45355 | 8 |
datatype direction = Left | Right |
29302 | 9 |
val mk_tree : ('a -> term) -> typ -> 'a list -> term |
10 |
val dest_tree : term -> term list |
|
45355 | 11 |
val find_tree : term -> term -> direction list option |
25408 | 12 |
|
74587 | 13 |
val in_set: Proof.context -> direction list -> cterm -> thm |
14 |
val find_in_set: Proof.context -> term -> cterm -> thm |
|
29302 | 15 |
val neq_to_eq_False : thm |
60327 | 16 |
val distinctTreeProver : Proof.context -> thm -> direction list -> direction list -> thm |
45355 | 17 |
val neq_x_y : Proof.context -> term -> term -> string -> thm option |
29302 | 18 |
val distinctFieldSolver : string list -> solver |
42368
3b8498ac2314
proper subgoal addressing via SUBGOAL/CSUBGOAL -- assuming these tactics did not handle Subscript in any special way;
wenzelm
parents:
42361
diff
changeset
|
19 |
val distinctTree_tac : string list -> Proof.context -> int -> tactic |
60327 | 20 |
val distinct_implProver : Proof.context -> thm -> cterm -> thm |
21 |
val subtractProver : Proof.context -> term -> cterm -> thm -> thm |
|
29302 | 22 |
val distinct_simproc : string list -> simproc |
45355 | 23 |
|
60639 | 24 |
val discharge : Proof.context -> thm list -> thm -> thm |
25408 | 25 |
end; |
26 |
||
27 |
structure DistinctTreeProver : DISTINCT_TREE_PROVER = |
|
25171 | 28 |
struct |
39159 | 29 |
|
45356 | 30 |
val neq_to_eq_False = @{thm neq_to_eq_False}; |
25171 | 31 |
|
45355 | 32 |
datatype direction = Left | Right; |
25408 | 33 |
|
69597 | 34 |
fun treeT T = Type (\<^type_name>\<open>tree\<close>, [T]); |
45740 | 35 |
|
69597 | 36 |
fun mk_tree' e T n [] = Const (\<^const_name>\<open>Tip\<close>, treeT T) |
25171 | 37 |
| mk_tree' e T n xs = |
38 |
let |
|
39 |
val m = (n - 1) div 2; |
|
40 |
val (xsl,x::xsr) = chop m xs; |
|
41 |
val l = mk_tree' e T m xsl; |
|
42 |
val r = mk_tree' e T (n-(m+1)) xsr; |
|
45355 | 43 |
in |
69597 | 44 |
Const (\<^const_name>\<open>Node\<close>, treeT T --> T --> HOLogic.boolT--> treeT T --> treeT T) $ |
45 |
l $ e x $ \<^term>\<open>False\<close> $ r |
|
25171 | 46 |
end |
47 |
||
45355 | 48 |
fun mk_tree e T xs = mk_tree' e T (length xs) xs; |
25171 | 49 |
|
69597 | 50 |
fun dest_tree (Const (\<^const_name>\<open>Tip\<close>, _)) = [] |
51 |
| dest_tree (Const (\<^const_name>\<open>Node\<close>, _) $ l $ e $ _ $ r) = dest_tree l @ e :: dest_tree r |
|
45355 | 52 |
| dest_tree t = raise TERM ("dest_tree", [t]); |
25171 | 53 |
|
25408 | 54 |
|
25171 | 55 |
|
69597 | 56 |
fun lin_find_tree e (Const (\<^const_name>\<open>Tip\<close>, _)) = NONE |
57 |
| lin_find_tree e (Const (\<^const_name>\<open>Node\<close>, _) $ l $ x $ _ $ r) = |
|
45355 | 58 |
if e aconv x |
25171 | 59 |
then SOME [] |
45355 | 60 |
else |
61 |
(case lin_find_tree e l of |
|
62 |
SOME path => SOME (Left :: path) |
|
63 |
| NONE => |
|
64 |
(case lin_find_tree e r of |
|
65 |
SOME path => SOME (Right :: path) |
|
66 |
| NONE => NONE)) |
|
67 |
| lin_find_tree e t = raise TERM ("find_tree: input not a tree", [t]) |
|
25171 | 68 |
|
69597 | 69 |
fun bin_find_tree order e (Const (\<^const_name>\<open>Tip\<close>, _)) = NONE |
70 |
| bin_find_tree order e (Const (\<^const_name>\<open>Node\<close>, _) $ l $ x $ _ $ r) = |
|
45355 | 71 |
(case order (e, x) of |
72 |
EQUAL => SOME [] |
|
73 |
| LESS => Option.map (cons Left) (bin_find_tree order e l) |
|
74 |
| GREATER => Option.map (cons Right) (bin_find_tree order e r)) |
|
75 |
| bin_find_tree order e t = raise TERM ("find_tree: input not a tree", [t]) |
|
25171 | 76 |
|
77 |
fun find_tree e t = |
|
35408 | 78 |
(case bin_find_tree Term_Ord.fast_term_ord e t of |
45355 | 79 |
NONE => lin_find_tree e t |
80 |
| x => x); |
|
81 |
||
25171 | 82 |
|
45355 | 83 |
fun split_common_prefix xs [] = ([], xs, []) |
84 |
| split_common_prefix [] ys = ([], [], ys) |
|
85 |
| split_common_prefix (xs as (x :: xs')) (ys as (y :: ys')) = |
|
86 |
if x = y |
|
87 |
then let val (ps, xs'', ys'') = split_common_prefix xs' ys' in (x :: ps, xs'', ys'') end |
|
88 |
else ([], xs, ys) |
|
25171 | 89 |
|
90 |
||
91 |
(* Wrapper around Thm.instantiate. The type instiations of instTs are applied to |
|
92 |
* the right hand sides of insts |
|
93 |
*) |
|
60327 | 94 |
fun instantiate ctxt instTs insts = |
25171 | 95 |
let |
59582 | 96 |
val instTs' = map (fn (T, U) => (dest_TVar (Thm.typ_of T), Thm.typ_of U)) instTs; |
25171 | 97 |
fun substT x = (case AList.lookup (op =) instTs' x of NONE => TVar x | SOME T' => T'); |
98 |
fun mapT_and_recertify ct = |
|
60327 | 99 |
(Thm.cterm_of ctxt (Term.map_types (Term.map_type_tvar substT) (Thm.term_of ct))); |
25171 | 100 |
val insts' = map (apfst mapT_and_recertify) insts; |
60642
48dd1cefb4ae
simplified Thm.instantiate and derivatives: the LHS refers to non-certified variables -- this merely serves as index into already certified structures (or is ignored);
wenzelm
parents:
60639
diff
changeset
|
101 |
in |
48dd1cefb4ae
simplified Thm.instantiate and derivatives: the LHS refers to non-certified variables -- this merely serves as index into already certified structures (or is ignored);
wenzelm
parents:
60639
diff
changeset
|
102 |
Thm.instantiate |
74282 | 103 |
(TVars.make (map (apfst (dest_TVar o Thm.typ_of)) instTs), |
104 |
Vars.make (map (apfst (dest_Var o Thm.term_of)) insts')) |
|
60642
48dd1cefb4ae
simplified Thm.instantiate and derivatives: the LHS refers to non-certified variables -- this merely serves as index into already certified structures (or is ignored);
wenzelm
parents:
60639
diff
changeset
|
105 |
end; |
25171 | 106 |
|
51701
1e29891759c4
tuned exceptions -- avoid composing error messages in low-level situations;
wenzelm
parents:
45740
diff
changeset
|
107 |
fun tvar_clash ixn S S' = |
1e29891759c4
tuned exceptions -- avoid composing error messages in low-level situations;
wenzelm
parents:
45740
diff
changeset
|
108 |
raise TYPE ("Type variable has two distinct sorts", [TVar (ixn, S), TVar (ixn, S')], []); |
25171 | 109 |
|
110 |
fun lookup (tye, (ixn, S)) = |
|
111 |
(case AList.lookup (op =) tye ixn of |
|
112 |
NONE => NONE |
|
113 |
| SOME (S', T) => if S = S' then SOME T else tvar_clash ixn S S'); |
|
114 |
||
115 |
val naive_typ_match = |
|
116 |
let |
|
117 |
fun match (TVar (v, S), T) subs = |
|
118 |
(case lookup (subs, (v, S)) of |
|
119 |
NONE => ((v, (S, T))::subs) |
|
120 |
| SOME _ => subs) |
|
121 |
| match (Type (a, Ts), Type (b, Us)) subs = |
|
122 |
if a <> b then raise Type.TYPE_MATCH |
|
123 |
else matches (Ts, Us) subs |
|
124 |
| match (TFree x, TFree y) subs = |
|
125 |
if x = y then subs else raise Type.TYPE_MATCH |
|
126 |
| match _ _ = raise Type.TYPE_MATCH |
|
127 |
and matches (T :: Ts, U :: Us) subs = matches (Ts, Us) (match (T, U) subs) |
|
128 |
| matches _ subs = subs; |
|
129 |
in match end; |
|
130 |
||
131 |
||
45355 | 132 |
(* expects that relevant type variables are already contained in |
25171 | 133 |
* term variables. First instantiation of variables is returned without further |
134 |
* checking. |
|
135 |
*) |
|
45355 | 136 |
fun naive_cterm_first_order_match (t, ct) env = |
25171 | 137 |
let |
45355 | 138 |
fun mtch (env as (tyinsts, insts)) = |
139 |
fn (Var (ixn, T), ct) => |
|
140 |
(case AList.lookup (op =) insts ixn of |
|
59586 | 141 |
NONE => (naive_typ_match (T, Thm.typ_of_cterm ct) tyinsts, (ixn, ct) :: insts) |
45355 | 142 |
| SOME _ => env) |
143 |
| (f $ t, ct) => |
|
144 |
let val (cf, ct') = Thm.dest_comb ct; |
|
145 |
in mtch (mtch env (f, cf)) (t, ct') end |
|
146 |
| _ => env; |
|
147 |
in mtch env (t, ct) end; |
|
25171 | 148 |
|
149 |
||
60639 | 150 |
fun discharge ctxt prems rule = |
25171 | 151 |
let |
45355 | 152 |
val (tyinsts,insts) = |
59582 | 153 |
fold naive_cterm_first_order_match (Thm.prems_of rule ~~ map Thm.cprop_of prems) ([], []); |
45355 | 154 |
val tyinsts' = |
60642
48dd1cefb4ae
simplified Thm.instantiate and derivatives: the LHS refers to non-certified variables -- this merely serves as index into already certified structures (or is ignored);
wenzelm
parents:
60639
diff
changeset
|
155 |
map (fn (v, (S, U)) => ((v, S), Thm.ctyp_of ctxt U)) tyinsts; |
45355 | 156 |
val insts' = |
60642
48dd1cefb4ae
simplified Thm.instantiate and derivatives: the LHS refers to non-certified variables -- this merely serves as index into already certified structures (or is ignored);
wenzelm
parents:
60639
diff
changeset
|
157 |
map (fn (idxn, ct) => ((idxn, Thm.typ_of_cterm ct), ct)) insts; |
74282 | 158 |
val rule' = Thm.instantiate (TVars.make tyinsts', Vars.make insts') rule; |
45355 | 159 |
in fold Thm.elim_implies prems rule' end; |
25171 | 160 |
|
161 |
local |
|
162 |
||
45355 | 163 |
val (l_in_set_root, x_in_set_root, r_in_set_root) = |
164 |
let |
|
165 |
val (Node_l_x_d, r) = |
|
59582 | 166 |
Thm.cprop_of @{thm in_set_root} |
45355 | 167 |
|> Thm.dest_comb |> #2 |
168 |
|> Thm.dest_comb |> #2 |> Thm.dest_comb |> #2 |> Thm.dest_comb; |
|
169 |
val (Node_l, x) = Node_l_x_d |> Thm.dest_comb |> #1 |> Thm.dest_comb; |
|
170 |
val l = Node_l |> Thm.dest_comb |> #2; |
|
171 |
in (l,x,r) end; |
|
25171 | 172 |
|
45355 | 173 |
val (x_in_set_left, r_in_set_left) = |
174 |
let |
|
175 |
val (Node_l_x_d, r) = |
|
59582 | 176 |
Thm.cprop_of @{thm in_set_left} |
45355 | 177 |
|> Thm.dest_comb |> #2 |> Thm.dest_comb |> #2 |
178 |
|> Thm.dest_comb |> #2 |> Thm.dest_comb |> #2 |> Thm.dest_comb; |
|
179 |
val x = Node_l_x_d |> Thm.dest_comb |> #1 |> Thm.dest_comb |> #2; |
|
180 |
in (x, r) end; |
|
181 |
||
182 |
val (x_in_set_right, l_in_set_right) = |
|
183 |
let |
|
184 |
val (Node_l, x) = |
|
59582 | 185 |
Thm.cprop_of @{thm in_set_right} |
45355 | 186 |
|> Thm.dest_comb |> #2 |> Thm.dest_comb |> #2 |
187 |
|> Thm.dest_comb |> #2 |> Thm.dest_comb |> #2 |
|
188 |
|> Thm.dest_comb |> #1 |> Thm.dest_comb |> #1 |
|
189 |
|> Thm.dest_comb; |
|
190 |
val l = Node_l |> Thm.dest_comb |> #2; |
|
191 |
in (x, l) end; |
|
25171 | 192 |
|
193 |
in |
|
74587 | 194 |
|
195 |
fun in_set ctxt ps tree = |
|
196 |
let |
|
197 |
val in_set = in_set ctxt |
|
198 |
val (_, [l, x, _, r]) = Drule.strip_comb tree; |
|
199 |
val xT = Thm.ctyp_of_cterm x; |
|
200 |
in |
|
201 |
(case ps of |
|
202 |
[] => |
|
203 |
instantiate ctxt |
|
204 |
[(Thm.ctyp_of_cterm x_in_set_root, xT)] |
|
205 |
[(l_in_set_root, l), (x_in_set_root, x), (r_in_set_root, r)] @{thm in_set_root} |
|
206 |
| Left :: ps' => |
|
207 |
let |
|
208 |
val in_set_l = in_set ps' l; |
|
209 |
val in_set_left' = |
|
210 |
instantiate ctxt |
|
211 |
[(Thm.ctyp_of_cterm x_in_set_left, xT)] |
|
212 |
[(x_in_set_left, x), (r_in_set_left, r)] @{thm in_set_left}; |
|
213 |
in discharge ctxt [in_set_l] in_set_left' end |
|
214 |
| Right :: ps' => |
|
215 |
let |
|
216 |
val in_set_r = in_set ps' r; |
|
217 |
val in_set_right' = |
|
218 |
instantiate ctxt |
|
219 |
[(Thm.ctyp_of_cterm x_in_set_right, xT)] |
|
220 |
[(x_in_set_right, x), (l_in_set_right, l)] @{thm in_set_right}; |
|
221 |
in discharge ctxt [in_set_r] in_set_right' end) |
|
222 |
end; |
|
223 |
||
224 |
fun find_in_set ctxt t ct = |
|
225 |
case find_tree t (Thm.term_of ct) of |
|
226 |
SOME ps => in_set ctxt ps ct |
|
227 |
| NONE => raise TERM ("find_in_set", [t, Thm.term_of ct]) |
|
228 |
||
25171 | 229 |
(* |
230 |
1. First get paths x_path y_path of x and y in the tree. |
|
231 |
2. For the common prefix descend into the tree according to the path |
|
232 |
and lemmas all_distinct_left/right |
|
233 |
3. If one restpath is empty use distinct_left/right, |
|
234 |
otherwise all_distinct_left_right |
|
235 |
*) |
|
236 |
||
60327 | 237 |
fun distinctTreeProver ctxt dist_thm x_path y_path = |
25171 | 238 |
let |
239 |
fun dist_subtree [] thm = thm |
|
45355 | 240 |
| dist_subtree (p :: ps) thm = |
241 |
let |
|
45356 | 242 |
val rule = |
243 |
(case p of Left => @{thm all_distinct_left} | Right => @{thm all_distinct_right}) |
|
60639 | 244 |
in dist_subtree ps (discharge ctxt [thm] rule) end; |
25171 | 245 |
|
45355 | 246 |
val (ps, x_rest, y_rest) = split_common_prefix x_path y_path; |
25171 | 247 |
val dist_subtree_thm = dist_subtree ps dist_thm; |
59582 | 248 |
val subtree = Thm.cprop_of dist_subtree_thm |> Thm.dest_comb |> #2 |> Thm.dest_comb |> #2; |
45355 | 249 |
val (_, [l, _, _, r]) = Drule.strip_comb subtree; |
250 |
||
74587 | 251 |
val in_set = in_set ctxt |
45355 | 252 |
fun in_set' [] = raise TERM ("distinctTreeProver", []) |
253 |
| in_set' (Left :: ps) = in_set ps l |
|
254 |
| in_set' (Right :: ps) = in_set ps r; |
|
255 |
||
60639 | 256 |
fun distinct_lr node_in_set Left = |
257 |
discharge ctxt [dist_subtree_thm, node_in_set] @{thm distinct_left} |
|
258 |
| distinct_lr node_in_set Right = |
|
259 |
discharge ctxt [dist_subtree_thm, node_in_set] @{thm distinct_right} |
|
25171 | 260 |
|
45355 | 261 |
val (swap, neq) = |
262 |
(case x_rest of |
|
263 |
[] => |
|
264 |
let val y_in_set = in_set' y_rest; |
|
265 |
in (false, distinct_lr y_in_set (hd y_rest)) end |
|
266 |
| xr :: xrs => |
|
267 |
(case y_rest of |
|
268 |
[] => |
|
269 |
let val x_in_set = in_set' x_rest; |
|
270 |
in (true, distinct_lr x_in_set (hd x_rest)) end |
|
271 |
| yr :: yrs => |
|
272 |
let |
|
273 |
val x_in_set = in_set' x_rest; |
|
274 |
val y_in_set = in_set' y_rest; |
|
275 |
in |
|
276 |
(case xr of |
|
45356 | 277 |
Left => |
60639 | 278 |
(false, |
279 |
discharge ctxt [dist_subtree_thm, x_in_set, y_in_set] @{thm distinct_left_right}) |
|
45356 | 280 |
| Right => |
60639 | 281 |
(true, |
282 |
discharge ctxt [dist_subtree_thm, y_in_set, x_in_set] @{thm distinct_left_right})) |
|
45355 | 283 |
end)); |
60639 | 284 |
in if swap then discharge ctxt [neq] @{thm swap_neq} else neq end; |
25171 | 285 |
|
286 |
||
60639 | 287 |
fun deleteProver _ dist_thm [] = @{thm delete_root} OF [dist_thm] |
288 |
| deleteProver ctxt dist_thm (p::ps) = |
|
45355 | 289 |
let |
45356 | 290 |
val dist_rule = |
291 |
(case p of Left => @{thm all_distinct_left} | Right => @{thm all_distinct_right}); |
|
60639 | 292 |
val dist_thm' = discharge ctxt [dist_thm] dist_rule; |
45356 | 293 |
val del_rule = (case p of Left => @{thm delete_left} | Right => @{thm delete_right}); |
60639 | 294 |
val del = deleteProver ctxt dist_thm' ps; |
295 |
in discharge ctxt [dist_thm, del] del_rule end; |
|
25171 | 296 |
|
297 |
local |
|
45355 | 298 |
val (alpha, v) = |
25171 | 299 |
let |
45355 | 300 |
val ct = |
45356 | 301 |
@{thm subtract_Tip} |> Thm.cprop_of |> Thm.dest_comb |> #2 |> Thm.dest_comb |> #2 |
45355 | 302 |
|> Thm.dest_comb |> #2; |
59586 | 303 |
val [alpha] = ct |> Thm.ctyp_of_cterm |> Thm.dest_ctyp; |
60642
48dd1cefb4ae
simplified Thm.instantiate and derivatives: the LHS refers to non-certified variables -- this merely serves as index into already certified structures (or is ignored);
wenzelm
parents:
60639
diff
changeset
|
304 |
in (dest_TVar (Thm.typ_of alpha), #1 (dest_Var (Thm.term_of ct))) end; |
25171 | 305 |
in |
306 |
||
69597 | 307 |
fun subtractProver ctxt (Const (\<^const_name>\<open>Tip\<close>, T)) ct dist_thm = |
45355 | 308 |
let |
309 |
val ct' = dist_thm |> Thm.cprop_of |> Thm.dest_comb |> #2 |> Thm.dest_comb |> #2; |
|
310 |
val [alphaI] = #2 (dest_Type T); |
|
311 |
in |
|
312 |
Thm.instantiate |
|
77879 | 313 |
(TVars.make1 (alpha, Thm.ctyp_of ctxt alphaI), |
314 |
Vars.make1 ((v, treeT alphaI), ct')) @{thm subtract_Tip} |
|
45355 | 315 |
end |
69597 | 316 |
| subtractProver ctxt (Const (\<^const_name>\<open>Node\<close>, nT) $ l $ x $ d $ r) ct dist_thm = |
45355 | 317 |
let |
318 |
val ct' = dist_thm |> Thm.cprop_of |> Thm.dest_comb |> #2 |> Thm.dest_comb |> #2; |
|
319 |
val (_, [cl, _, _, cr]) = Drule.strip_comb ct; |
|
59582 | 320 |
val ps = the (find_tree x (Thm.term_of ct')); |
60639 | 321 |
val del_tree = deleteProver ctxt dist_thm ps; |
322 |
val dist_thm' = discharge ctxt [del_tree, dist_thm] @{thm delete_Some_all_distinct}; |
|
60327 | 323 |
val sub_l = subtractProver ctxt (Thm.term_of cl) cl (dist_thm'); |
45355 | 324 |
val sub_r = |
60327 | 325 |
subtractProver ctxt (Thm.term_of cr) cr |
60639 | 326 |
(discharge ctxt [sub_l, dist_thm'] @{thm subtract_Some_all_distinct_res}); |
327 |
in discharge ctxt [del_tree, sub_l, sub_r] @{thm subtract_Node} end; |
|
45355 | 328 |
|
329 |
end; |
|
330 |
||
60327 | 331 |
fun distinct_implProver ctxt dist_thm ct = |
25171 | 332 |
let |
333 |
val ctree = ct |> Thm.dest_comb |> #2 |> Thm.dest_comb |> #2; |
|
60327 | 334 |
val sub = subtractProver ctxt (Thm.term_of ctree) ctree dist_thm; |
45356 | 335 |
in @{thm subtract_Some_all_distinct} OF [sub, dist_thm] end; |
25171 | 336 |
|
337 |
fun get_fst_success f [] = NONE |
|
45355 | 338 |
| get_fst_success f (x :: xs) = |
339 |
(case f x of |
|
340 |
NONE => get_fst_success f xs |
|
341 |
| SOME v => SOME v); |
|
25171 | 342 |
|
343 |
fun neq_x_y ctxt x y name = |
|
344 |
(let |
|
42361 | 345 |
val dist_thm = the (try (Proof_Context.get_thm ctxt) name); |
59582 | 346 |
val ctree = Thm.cprop_of dist_thm |> Thm.dest_comb |> #2 |> Thm.dest_comb |> #2; |
347 |
val tree = Thm.term_of ctree; |
|
25171 | 348 |
val x_path = the (find_tree x tree); |
349 |
val y_path = the (find_tree y tree); |
|
60327 | 350 |
val thm = distinctTreeProver ctxt dist_thm x_path y_path; |
45355 | 351 |
in SOME thm |
352 |
end handle Option.Option => NONE); |
|
25171 | 353 |
|
42368
3b8498ac2314
proper subgoal addressing via SUBGOAL/CSUBGOAL -- assuming these tactics did not handle Subscript in any special way;
wenzelm
parents:
42361
diff
changeset
|
354 |
fun distinctTree_tac names ctxt = SUBGOAL (fn (goal, i) => |
3b8498ac2314
proper subgoal addressing via SUBGOAL/CSUBGOAL -- assuming these tactics did not handle Subscript in any special way;
wenzelm
parents:
42361
diff
changeset
|
355 |
(case goal of |
69597 | 356 |
Const (\<^const_name>\<open>Trueprop\<close>, _) $ |
357 |
(Const (\<^const_name>\<open>Not\<close>, _) $ (Const (\<^const_name>\<open>HOL.eq\<close>, _) $ x $ y)) => |
|
42368
3b8498ac2314
proper subgoal addressing via SUBGOAL/CSUBGOAL -- assuming these tactics did not handle Subscript in any special way;
wenzelm
parents:
42361
diff
changeset
|
358 |
(case get_fst_success (neq_x_y ctxt x y) names of |
60754 | 359 |
SOME neq => resolve_tac ctxt [neq] i |
42368
3b8498ac2314
proper subgoal addressing via SUBGOAL/CSUBGOAL -- assuming these tactics did not handle Subscript in any special way;
wenzelm
parents:
42361
diff
changeset
|
360 |
| NONE => no_tac) |
3b8498ac2314
proper subgoal addressing via SUBGOAL/CSUBGOAL -- assuming these tactics did not handle Subscript in any special way;
wenzelm
parents:
42361
diff
changeset
|
361 |
| _ => no_tac)) |
25171 | 362 |
|
45355 | 363 |
fun distinctFieldSolver names = |
51717
9e7d1c139569
simplifier uses proper Proof.context instead of historic type simpset;
wenzelm
parents:
51701
diff
changeset
|
364 |
mk_solver "distinctFieldSolver" (distinctTree_tac names); |
25171 | 365 |
|
366 |
fun distinct_simproc names = |
|
69597 | 367 |
Simplifier.make_simproc \<^context> "DistinctTreeProver.distinct_simproc" |
368 |
{lhss = [\<^term>\<open>x = y\<close>], |
|
61144 | 369 |
proc = fn _ => fn ctxt => fn ct => |
370 |
(case Thm.term_of ct of |
|
69597 | 371 |
Const (\<^const_name>\<open>HOL.eq\<close>, _) $ x $ y => |
45356 | 372 |
Option.map (fn neq => @{thm neq_to_eq_False} OF [neq]) |
45355 | 373 |
(get_fst_success (neq_x_y ctxt x y) names) |
62913 | 374 |
| _ => NONE)}; |
25171 | 375 |
|
45355 | 376 |
end; |
377 |
||
62391 | 378 |
end; |