2 (******************************************************************************)
3 (* FILE : terms_and_clauses.ml *)
4 (* DESCRIPTION : Rewriting terms and simplifying clauses. *)
6 (* READS FILES : <none> *)
7 (* WRITES FILES : <none> *)
9 (* AUTHOR : R.J.Boulton *)
10 (* DATE : 7th June 1991 *)
12 (* MODIFIED : R.J.Boulton *)
13 (* DATE : 16th October 1992 *)
15 (* LAST MODIFIED : P. Papapanagiotou (University of Edinburgh) *)
16 (* DATE : July 2009 *)
17 (******************************************************************************)
19 let SUBST_CONV thvars template tm =
20 let thms,vars = unzip thvars in
21 let gvs = map (genvar o type_of) vars in
22 let gtemplate = subst (zip gvs vars) template in
23 SUBST (zip thms gvs) (mk_eq(template,gtemplate)) (REFL tm);;
27 let check = let boolty = `:bool` in check (fun tm -> type_of tm = boolty) in
28 let clist = map (GEN `b:bool`)
29 (CONJUNCTS(SPEC `b:bool` EQ_CLAUSES)) in
30 let tb = hd clist and bt = hd(tl clist) in
31 let T = `T` and F = `F` in
33 try let l,r = (I F_F check) (dest_eq tm) in
34 if l = r then EQT_INTRO (REFL l) else
35 if l = T then SPEC r tb else
36 if r = T then SPEC l bt else fail()
37 with Failure _ -> failwith "bool_EQ_CONV";;
39 (*----------------------------------------------------------------------------*)
40 (* rewrite_with_lemmas : (term list -> term list -> conv) -> *)
41 (* term list -> term list -> conv *)
43 (* Function to rewrite with known lemmas (rewrite rules) in the reverse order *)
44 (* in which they were introduced. Applies the first applicable lemma, or if *)
45 (* none are applicable it leaves the term unchanged. *)
47 (* A rule is applicable if its LHS matches the term, and it does not violate *)
48 (* the `alphabetical' ordering rule if it is a permutative rule. To be *)
49 (* applicable, the hypotheses of the rules must be satisfied. The function *)
50 (* takes a general rewrite rule, a chain of hypotheses and a list of *)
51 (* assumptions as arguments. It uses these to try to satisfy the hypotheses. *)
52 (* If a hypotheses is in the assumption list, it is assumed. Otherwise a *)
53 (* check is made that the hypothesis is not already a goal of the proof *)
54 (* procedure. This is to prevent looping. If it's not already a goal, the *)
55 (* function attempts to rewrite the hypotheses, with it added to the chain of *)
58 (* Before trying to establish the hypotheses of a rewrite rule, it is *)
59 (* necessary to instantiate any free variables in the hypotheses. This is *)
60 (* done by trying to find an instantiation that makes one of the hypotheses *)
61 (* equal to a term in the assumption list. *)
62 (*----------------------------------------------------------------------------*)
64 let rewrite_with_lemmas rewrite hyp_chain assumps tm =
66 try (EQT_INTRO (ASSUME (find (fun tm -> tm = h) assumps))) with Failure _ ->
69 else rewrite (h::hyp_chain) assumps h)
71 let rec try_rewrites assumps ths =
73 then failwith "try_rewrites"
74 else (try (let th = inst_frees_in_hyps assumps (hd ths)
75 in let hyp_ths = map (EQT_ELIM o rewrite_hyp) (hyp th)
76 in itlist PROVE_HYP hyp_ths th)
77 with Failure _ -> (try_rewrites assumps (tl ths))
79 in try (try_rewrites assumps (applicable_rewrites tm)) with Failure _ -> ALL_CONV tm;;
81 (*----------------------------------------------------------------------------*)
82 (* rewrite_explicit_value : conv *)
84 (* Explicit values are normally unchanged by rewriting, but in the case of a *)
85 (* numeric constant, it is expanded out into SUC form. *)
86 (*----------------------------------------------------------------------------*)
88 let rec rewrite_explicit_value tm =
89 let rec conv tm = (num_CONV THENC TRY_CONV (RAND_CONV conv)) tm
90 in ((TRY_CONV conv) THENC
91 (TRY_CONV (ARGS_CONV rewrite_explicit_value))) tm;;
93 (*----------------------------------------------------------------------------*)
94 (* COND_T = |- (T => t1 | t2) = t1 *)
95 (* COND_F = |- (F => t1 | t2) = t2 *)
96 (*----------------------------------------------------------------------------*)
98 let [COND_T;COND_F] = CONJUNCTS (SPEC_ALL COND_CLAUSES);;
100 (*----------------------------------------------------------------------------*)
102 (* |- !b x x' y. (b ==> (x = x')) ==> ((b => x | y) = (b => x' | y)) *)
103 (*----------------------------------------------------------------------------*)
107 (`!b x x' (y:'a). (b ==> (x = x')) ==> ((if b then x else y) = (if b then x' else y))`,
109 BOOL_CASES_TAC `b:bool` THEN
112 (*----------------------------------------------------------------------------*)
114 (* |- !b y y' x. (~b ==> (y = y')) ==> ((b => x | y) = (b => x | y')) *)
115 (*----------------------------------------------------------------------------*)
119 (`!b y y' (x:'a). (~b ==> (y = y')) ==> ((if b then x else y) = (if b then x else y'))`,
121 BOOL_CASES_TAC `b:bool` THEN
124 (*----------------------------------------------------------------------------*)
125 (* COND_ID = |- !b t. (b => t | t) = t *)
126 (*----------------------------------------------------------------------------*)
128 (* Already defined in HOL *)
130 (*----------------------------------------------------------------------------*)
131 (* COND_RIGHT_F = |- (b => b | F) = b *)
132 (*----------------------------------------------------------------------------*)
136 (`(if b then b else F) = b`,
137 BOOL_CASES_TAC `b:bool` THEN
140 (*----------------------------------------------------------------------------*)
141 (* COND_T_F = |- (b => T | F) = b *)
142 (*----------------------------------------------------------------------------*)
146 (`(if b then T else F) = b`,
147 BOOL_CASES_TAC `b:bool` THEN
150 (*----------------------------------------------------------------------------*)
151 (* rewrite_conditional : (term list -> conv) -> term list -> conv *)
153 (* Rewriting conditionals. Takes a general rewrite function and a list of *)
154 (* assumptions as arguments. *)
156 (* The function assumes that the term it is given is of the form "b => x | y" *)
157 (* First it recursively rewrites b to b'. If b' is T or F, the conditional is *)
158 (* reduced to x or y, respectively. The result is then rewritten recursively. *)
159 (* If b' is not T or F, both x and y are rewritten, under suitable additional *)
160 (* assumptions about b'. An attempt is then made to rewrite the new *)
161 (* conditional with one of the following: *)
163 (* (b => x | x) ---> x *)
164 (* (b => b | F) ---> b *)
165 (* (b => T | F) ---> b *)
167 (* The three rules are tried in the order shown above. *)
168 (*----------------------------------------------------------------------------*)
170 let rewrite_conditional rewrite assumps tm =
171 try (let th1 = RATOR_CONV (RATOR_CONV (RAND_CONV (rewrite assumps))) tm
172 in let tm1 = rhs (concl th1)
173 in let (b',(x,y)) = dest_cond tm1
175 TRANS th1 (((REWR_CONV COND_T) THENC (rewrite assumps)) tm1)
176 else if (is_F b') then
177 TRANS th1 (((REWR_CONV COND_F) THENC (rewrite assumps)) tm1)
178 else let th2 = DISCH b' (rewrite (b'::assumps) x)
179 in let x' = rand (rand (concl th2))
180 in let th3 = MP (ISPECL [b';x;x';y] COND_LEFT) th2
181 in let tm3 = rhs (concl th3)
182 in let notb' = mk_neg b'
183 in let th4 = DISCH notb' (rewrite (notb'::assumps) y)
184 in let y' = rand (rand (concl th4))
185 in let th5 = MP (ISPECL [b';y;y';x'] COND_RIGHT) th4
186 in let th6 = ((REWR_CONV COND_ID) ORELSEC
187 (REWR_CONV COND_RIGHT_F) ORELSEC
188 (TRY_CONV (REWR_CONV COND_T_F))) (rhs (concl th5))
189 in TRANS (TRANS (TRANS th1 th3) th5) th6
190 ) with Failure _ -> failwith "rewrite_conditional";;
192 (*----------------------------------------------------------------------------*)
193 (* EQ_T = |- (x = T) = x *)
194 (*----------------------------------------------------------------------------*)
199 BOOL_CASES_TAC `x:bool` THEN
202 (*----------------------------------------------------------------------------*)
203 (* EQ_EQ = |- (x = (y = z)) = ((y = z) => (x = T) | (x = F)) *)
204 (*----------------------------------------------------------------------------*)
208 (`(x = ((y:'a) = z)) = (if (y = z) then (x = T) else (x = F))`,
209 BOOL_CASES_TAC `x:bool` THEN
210 BOOL_CASES_TAC `(y:'a) = z` THEN
213 (*----------------------------------------------------------------------------*)
214 (* EQ_F = |- (x = F) = (x => F | T) *)
215 (*----------------------------------------------------------------------------*)
219 (`(x = F) = (if x then F else T)`,
220 BOOL_CASES_TAC `x:bool` THEN
223 (*----------------------------------------------------------------------------*)
224 (* prove_terms_not_eq : term -> term -> thm *)
226 (* Function to prove that the left-hand and right-hand sides of an equation *)
227 (* are not equal. Works with Boolean constants, explicit values, and terms *)
228 (* involving constructors and variables. *)
229 (*----------------------------------------------------------------------------*)
231 let prove_terms_not_eq l r =
232 let rec STRUCT_CONV tm =
233 (bool_EQ_CONV ORELSEC
235 (fun tm -> let (l,r) = dest_eq tm
236 in let ty_name = (fst o dest_type) (type_of l)
237 in let (ty_info:shell_info) = sys_shell_info ty_name
238 in let ty_conv = ty_info.struct_conv
239 in ty_conv STRUCT_CONV tm) ORELSEC
240 (* REFL_CONV ORELSEC Omitted because it cannot generate false *)
242 in try(let th = STRUCT_CONV (mk_eq (l,r))
243 in if (is_F (rhs (concl th))) then th else failwith ""
244 ) with Failure _ -> failwith "prove_terms_not_eq";;
246 (*----------------------------------------------------------------------------*)
247 (* rewrite_equality : (term list -> term list -> conv) -> *)
248 (* term list -> term list -> conv *)
250 (* Function for rewriting equalities. Takes a general rewrite function, a *)
251 (* chain of hypotheses and a list of assumptions as arguments. *)
253 (* The left-hand and right-hand sides of the equality are rewritten *)
254 (* recursively. If the two sides are then identical, the term is rewritten to *)
255 (* T. If it can be shown that the two sides are not equal, the term is *)
256 (* rewritten to F. Otherwise, the function rewrites with the first of the *)
257 (* following rules that is applicable (or it leaves the term unchanged if *)
258 (* none are applicable): *)
261 (* (x = (y = z)) ---> ((y = z) => (x = T) | (x = F)) *)
262 (* (x = F) ---> (x => F | T) *)
264 (* The result is then rewritten using the known lemmas (rewrite rules). *)
265 (*----------------------------------------------------------------------------*)
267 let rewrite_equality rewrite hyp_chain assumps tm =
268 try (let th1 = ((RATOR_CONV (RAND_CONV (rewrite hyp_chain assumps))) THENC
269 (RAND_CONV (rewrite hyp_chain assumps))) tm
270 in let tm1 = rhs (concl th1)
271 in let (l,r) = dest_eq tm1
273 then TRANS th1 (EQT_INTRO (ISPEC l EQ_REFL))
274 else try(TRANS th1 (prove_terms_not_eq l r))
275 with Failure _ -> (let th2 = ((REWR_CONV EQ_T) ORELSEC
276 (REWR_CONV EQ_EQ) ORELSEC
277 (TRY_CONV (REWR_CONV EQ_F))) tm1
278 in let th3 = rewrite_with_lemmas
279 rewrite hyp_chain assumps (rhs (concl th2))
280 in TRANS (TRANS th1 th2) th3)
281 ) with Failure _ -> failwith "rewrite_equality";;
283 (*----------------------------------------------------------------------------*)
284 (* rewrite_application : *)
285 (* (term -> string list -> term list -> term list -> conv) -> *)
286 (* term -> string list -> term list -> term list -> conv *)
288 (* Function for rewriting applications. It takes a general rewriting function,*)
289 (* a literal (the literal containing the function call), a list of names of *)
290 (* functions that are tentatively being opened up, a chain of hypotheses, and *)
291 (* a list of assumptions as arguments. *)
293 (* The function begins by rewriting the arguments. It then determines the *)
294 (* name of the function being applied. If this is a constructor, no further *)
295 (* rewriting is done. Otherwise, from the function name, the number of the *)
296 (* argument used for recursion (or zero if the definition is not recursive) *)
297 (* and expansion theorems for each possible constructor are obtained. If the *)
298 (* function is not recursive the call is opened up and the body is rewritten. *)
299 (* If the function has no definition, the application is rewritten using the *)
302 (* If the definition is recursive, but this function has already been *)
303 (* tentatively opened up, the version of the application with the arguments *)
304 (* rewritten is returned. *)
306 (* Otherwise, the application is rewritten with the known lemmas. If any of *)
307 (* the lemmas are applicable the result of the rewrite is returned. Otherwise *)
308 (* the function determines the name of the constructor appearing in the *)
309 (* recursive argument, and looks up its details. If this process fails due to *)
310 (* either the recursive argument not being an application of a constructor, *)
311 (* or because the constructor is not known, the function call cannot be *)
312 (* expanded, so the original call (with arguments rewritten) is returned. *)
314 (* Provided a valid constructor is present in the recursive argument position *)
315 (* the call is tentatively opened up. The body is rewritten with the name of *)
316 (* the function added to the `tentative openings' list. (Actually, the name *)
317 (* is not added to the list if the recursive argument of the call was an *)
318 (* explicit value). The result is compared with the unopened call to see if *)
319 (* it has good properties. If it does, the simplified body is returned. *)
320 (* Otherwise the unopened call is returned. *)
321 (*----------------------------------------------------------------------------*)
323 let rewrite_application rewrite lit funcs hyp_chain assumps tm =
324 try (let th1 = ARGS_CONV (rewrite lit funcs hyp_chain assumps) tm
325 in let tm1 = rhs (concl th1)
326 in let (f,args) = strip_comb tm1
327 in let name = fst (dest_const f)
329 if (mem name (all_constructors ()))
332 (let (i,constructors) = get_def name
334 (let th2 = REWR_CONV (snd (hd constructors)) tm1
335 in let th3 = rewrite lit funcs hyp_chain assumps (rhs (concl th2))
336 in TRANS (TRANS th1 th2) th3)
337 else if (mem name funcs) then th1
339 rewrite_with_lemmas (rewrite lit funcs) hyp_chain assumps tm1
340 in let tm2 = rhs (concl th2)
342 then try (let argi = el (i-1) args
344 (try (fst (dest_const (fst (strip_comb argi)))) with Failure _ -> "")
345 in (let th = assoc constructor constructors
346 in let th3 = REWR_CONV th tm1
347 in let tm3 = rhs (concl th3)
349 if (is_explicit_value argi)
353 rewrite lit funcs' hyp_chain assumps tm3
354 in let tm4 = rhs (concl th4)
355 in if (good_properties assumps tm1 tm4 lit)
356 then TRANS (TRANS th1 th3) th4
358 ) with Failure _ -> th1
360 with Failure "get_def" ->
361 (TRANS th1 (rewrite_with_lemmas (rewrite lit funcs) hyp_chain assumps tm1))
362 ) with Failure _ -> failwith "rewrite_application";;
364 (*----------------------------------------------------------------------------*)
365 (* rewrite_term : term -> string list -> term list -> term list -> conv *)
367 (* Function for rewriting a term. Arguments are as follows: *)
369 (* lit : the literal containing the term to be rewritten. *)
370 (* funcs : names of functions that have been tentatively opened up. *)
371 (* hyp_chain : hypotheses that we are trying to satisfy by parent calls. *)
372 (* assumps : a list of assumptions. *)
373 (* tm : the term to be rewritten. *)
374 (*----------------------------------------------------------------------------*)
376 let rec rewrite_term lit funcs hyp_chain assumps tm =
377 try (EQT_INTRO (ASSUME (find (fun t -> t = tm) assumps))) with Failure _ ->
378 try (EQF_INTRO (ASSUME (find (fun t -> t = mk_neg tm) assumps))) with Failure _ ->
379 try (let rewrite = rewrite_term lit funcs
380 in if (is_var tm) then ALL_CONV tm
381 else if (is_explicit_value tm) then rewrite_explicit_value tm
382 else if (is_cond tm) then rewrite_conditional (rewrite hyp_chain) assumps tm
383 else if (is_eq tm) then rewrite_equality rewrite hyp_chain assumps tm
384 else rewrite_application rewrite_term lit funcs hyp_chain assumps tm
385 ) with Failure _ -> failwith "rewrite_term";;
387 (*----------------------------------------------------------------------------*)
388 (* COND_RAND = |- !f b x y. f (b => x | y) = (b => f x | f y) *)
389 (*----------------------------------------------------------------------------*)
391 (* Already defined in HOL *)
393 (*----------------------------------------------------------------------------*)
394 (* COND_RATOR = |- !b f g x. (b => f | g) x = (b => f x | g x) *)
395 (*----------------------------------------------------------------------------*)
397 (* Already defined in HOL *)
399 (*----------------------------------------------------------------------------*)
400 (* MOVE_COND_UP_CONV : conv *)
402 (* Moves all conditionals in a term up to the top-level. Checks to see if the *)
403 (* term contains any conditionals before it starts to do inference. This *)
404 (* improves the performance significantly. Alternatively, failure could be *)
405 (* used to avoid rebuilding unchanged sub-terms. This would be even more *)
407 (*----------------------------------------------------------------------------*)
409 let rec MOVE_COND_UP_CONV tm =
410 try(if (not (can (find_term is_cond) tm)) then ALL_CONV tm
411 else if (is_cond tm) then
412 ((RATOR_CONV (RATOR_CONV (RAND_CONV MOVE_COND_UP_CONV))) THENC
413 (RATOR_CONV (RAND_CONV MOVE_COND_UP_CONV)) THENC
414 (RAND_CONV MOVE_COND_UP_CONV)) tm
415 else if (is_comb tm) then
416 (let (op,arg) = dest_comb tm
417 in if (is_cond op) then
418 ((REWR_CONV COND_RATOR) THENC MOVE_COND_UP_CONV) tm
419 else if (is_cond arg) then
420 ((REWR_CONV COND_RAND) THENC MOVE_COND_UP_CONV) tm
421 else (let th = ((RATOR_CONV MOVE_COND_UP_CONV) THENC
422 (RAND_CONV MOVE_COND_UP_CONV)) tm
423 in let tm' = rhs (concl th)
426 else TRANS th (MOVE_COND_UP_CONV tm')))
428 ) with Failure _ -> failwith "MOVE_COND_UP_CONV";;
430 (*----------------------------------------------------------------------------*)
431 (* COND_OR = |- (b => x | y) \/ z = (~b \/ x \/ z) /\ (b \/ y \/ z) *)
432 (*----------------------------------------------------------------------------*)
436 (`(if b then x else y) \/ z <=> ((~b \/ x \/ z) /\ (b \/ y \/ z))`,
437 BOOL_CASES_TAC `b:bool` THEN
440 (*----------------------------------------------------------------------------*)
441 (* COND_EXPAND = |- (x => y | z) = ((~x \/ y) /\ (x \/ z)) *)
442 (*----------------------------------------------------------------------------*)
446 (*----------------------------------------------------------------------------*)
447 (* NOT_NOT_NORM = |- ~~x = x *)
448 (*----------------------------------------------------------------------------*)
452 (*----------------------------------------------------------------------------*)
453 (* LEFT_OR_OVER_AND = |- !t1 t2 t3. t1 \/ t2 /\ t3 = (t1 \/ t2) /\ (t1 \/ t3) *)
454 (*----------------------------------------------------------------------------*)
456 (* Already available in HOL *)
458 (*----------------------------------------------------------------------------*)
459 (* MOVE_NOT_THRU_CONDS_CONV : conv *)
461 (* Function to push a negation down through (possibly) nested conditionals. *)
462 (* Eliminates any double-negations that may be introduced. *)
463 (*----------------------------------------------------------------------------*)
465 let rec MOVE_NOT_THRU_CONDS_CONV tm =
467 then if (is_cond (rand tm))
468 then ((REWR_CONV COND_RAND) THENC
469 (RATOR_CONV (RAND_CONV MOVE_NOT_THRU_CONDS_CONV)) THENC
470 (RAND_CONV MOVE_NOT_THRU_CONDS_CONV)) tm
471 else TRY_CONV (REWR_CONV NOT_NOT_NORM) tm
473 ) with Failure _ -> failwith "MOVE_NOT_THRU_CONDS_CONV";;
475 (*----------------------------------------------------------------------------*)
476 (* EXPAND_ONE_COND_CONV : conv *)
478 (* The function takes a term which it assumes to be either a conditional or *)
479 (* the disjunction of a conditional and some other term, and applies one of *)
480 (* the following rewrites as appropriate: *)
482 (* |- (b => x | y) = (~b \/ x) /\ (b \/ y) *)
484 (* |- (b => x | y) \/ z = (~b \/ x \/ z) /\ (b \/ y \/ z) *)
486 (* If b happens to be a conditional, the negation of ~b is moved down through *)
487 (* the conditional (and any nested conditionals). *)
488 (*----------------------------------------------------------------------------*)
490 let EXPAND_ONE_COND_CONV tm =
491 try (((REWR_CONV COND_OR) ORELSEC (REWR_CONV COND_EXPAND)) THENC
492 (RATOR_CONV (RAND_CONV (RATOR_CONV (RAND_CONV MOVE_NOT_THRU_CONDS_CONV)))))
493 tm with Failure _ -> failwith "EXPAND_ONE_COND_CONV";;
495 (*----------------------------------------------------------------------------*)
496 (* OR_OVER_ANDS_CONV : conv -> conv *)
498 (* Distributes an OR over an arbitrary tree of conjunctions and applies a *)
499 (* conversion to each of the disjunctions that make up the new conjunction. *)
500 (*----------------------------------------------------------------------------*)
502 let rec OR_OVER_ANDS_CONV conv tm =
504 then if (is_conj (rand tm))
505 then ((REWR_CONV LEFT_OR_OVER_AND) THENC
506 (RATOR_CONV (RAND_CONV (OR_OVER_ANDS_CONV conv))) THENC
507 (RAND_CONV (OR_OVER_ANDS_CONV conv))) tm
511 (*----------------------------------------------------------------------------*)
512 (* EXPAND_COND_CONV : conv *)
514 (* The function takes a term which it assumes to be either a conditional or *)
515 (* the disjunction of a conditional and some other term, and expands the *)
516 (* conditional into a disjunction using one of: *)
518 (* |- (b => x | y) = (~b \/ x) /\ (b \/ y) *)
520 (* |- (b => x | y) \/ z = (~b \/ x \/ z) /\ (b \/ y \/ z) *)
522 (* The b, x and y may themselves be conditionals. If so, the function expands *)
523 (* these as well, and so on, until there are no more conditionals. At each *)
524 (* stage disjunctions are distributed over conjunctions so that the final *)
525 (* result is a conjunction `tree' where each of the conjuncts is a *)
526 (* disjunction. The depth of a disjunction in the conjunction tree indicates *)
527 (* the number of literals that have been added to the disjunction compared to *)
528 (* the original term. *)
529 (*----------------------------------------------------------------------------*)
531 let rec EXPAND_COND_CONV tm =
532 try (EXPAND_ONE_COND_CONV THENC
533 (RATOR_CONV (RAND_CONV ((RAND_CONV EXPAND_COND_CONV) THENC
534 (OR_OVER_ANDS_CONV EXPAND_COND_CONV)))) THENC
535 (RAND_CONV ((RAND_CONV EXPAND_COND_CONV) THENC
536 (OR_OVER_ANDS_CONV EXPAND_COND_CONV)))) tm
537 with Failure _ -> ALL_CONV tm;;
539 (*----------------------------------------------------------------------------*)
540 (* SPLIT_CLAUSE_ON_COND_CONV : int -> conv *)
542 (* The function takes a number n and a term which it assumes to be a *)
543 (* disjunction of literals in which the (n-1)th argument has had all *)
544 (* conditionals moved to the top level. *)
546 (* The function dives down to the (n-1)th literal (disjunct) and expands the *)
547 (* conditionals into disjunctions, resulting in a conjunction `tree' in which *)
548 (* each conjunct is a disjunction. *)
550 (* As the function `backs out' from the (n-1)th literal it distributes the *)
551 (* ORs over the conjunction tree. *)
552 (*----------------------------------------------------------------------------*)
554 let SPLIT_CLAUSE_ON_COND_CONV n tm =
555 try (funpow n (fun conv -> (RAND_CONV conv) THENC (OR_OVER_ANDS_CONV ALL_CONV))
557 ) with Failure _ -> failwith "SPLIT_CLAUSE_ON_COND_CONV";;
559 (*----------------------------------------------------------------------------*)
560 (* simplify_one_literal : int -> term -> (thm # int) *)
562 (* Attempts to simplify one literal of a clause assuming the negations of the *)
563 (* other literals. The number n specifies which literal to rewrite. If n = 0, *)
564 (* the first literal is rewritten. The function fails if n is out of range. *)
566 (* If the literal to be simplified is negative, the function simplifies the *)
567 (* corresponding atom, and negates the result. If this new result is T or F, *)
568 (* the clause is rebuilt by discharging the assumptions. This process may *)
569 (* reduce the number of literals in the clause, so the theorem returned is *)
570 (* paired with -1 (except when processing the last literal of a clause in *)
571 (* which case returning 0 will, like -1, cause a failure when an attempt is *)
572 (* made to simplify the next literal, but is safer because it can't cause *)
573 (* looping if the literal has not been removed. This is the case when the *)
574 (* last literal has been rewritten to F. In this situation, the discharging *)
575 (* function does not eliminate the literal). *)
577 (* If the simplified literal contains conditionals, these are brought up to *)
578 (* the top-level. The clause is then rebuilt by discharging. If no *)
579 (* conditionals were present the theorem is returned with 0, indicating that *)
580 (* the number of literals has not changed. Otherwise the clause is split into *)
581 (* a conjunction of clauses, so that the conditionals are eliminated, and the *)
582 (* result is returned with the number 1 to indicate that the number of *)
583 (* literals has increased. *)
584 (*----------------------------------------------------------------------------*)
586 let simplify_one_literal n tm =
587 try (let negate tm = if (is_neg tm) then (rand tm) else (mk_neg tm)
589 let tm = rhs (concl th)
590 and th' = AP_TERM `(~)` th
591 in if (is_T tm) then TRANS th' (el 1 (CONJUNCTS NOT_CLAUSES))
592 else if (is_F tm) then TRANS th' (el 2 (CONJUNCTS NOT_CLAUSES))
594 in let (overs,y,unders) = match (chop_list n (disj_list tm)) with
595 | (overs,y::unders) -> (overs,y,unders)
597 (* ) with Failure _ -> failwith "" *)
598 in let overs' = map negate overs
599 and unders' = map negate unders
602 then NEGATE (rewrite_term y [] [] (overs' @ unders') (rand y))
603 else rewrite_term y [] [] (overs' @ unders') y
604 in let tm1 = rhs (concl th1)
605 in if ((is_T tm1) or (is_F tm1))
606 then (MULTI_DISJ_DISCH (overs',unders') th1,
607 if (unders = []) then 0 else (-1))
608 else let th2 = TRANS th1 (MOVE_COND_UP_CONV tm1)
609 in let tm2 = rhs (concl th2)
610 in let th3 = MULTI_DISJ_DISCH (overs',unders') th2
612 then (CONV_RULE (RAND_CONV (SPLIT_CLAUSE_ON_COND_CONV n)) th3,1)
614 ) with Failure _ -> failwith "simplify_one_literal";;
616 (*----------------------------------------------------------------------------*)
617 (* simplify_clause : int -> term -> (term list # proof) *)
618 (* simplify_clauses : int -> term -> (term list # proof) *)
620 (* Functions for simplifying a clause by rewriting each literal in turn *)
621 (* assuming the negations of the others. *)
623 (* The integer argument to simplify_clause should be zero initially. It will *)
624 (* then attempt to simplify the first literal. If the result is true, no new *)
625 (* clauses are produced. Otherwise, the function proceeds to simplify the *)
626 (* next literal. This has to be done differently according to the changes *)
627 (* that took place when simplifying the first literal. *)
629 (* If there was a reduction in the number of literals, this must have been *)
630 (* due to the literal being shown to be false, because the true case has *)
631 (* already been eliminated. So, there must be one less literal, and so n is *)
632 (* unchanged on the recursive call. If there was no change in the number of *)
633 (* literals, n is incremented by 1. Otherwise, not only have new literals *)
634 (* been introduced, but also the clause has been split into a conjunction of *)
635 (* clauses. simplify_clauses is called to handle this case. *)
637 (* When all the literals have been processed, n will become out of range and *)
638 (* cause a failure. This is trapped, and the simplified clause is returned. *)
640 (* When the clause has been split into a conjunction of clauses, the depth of *)
641 (* a clause in the tree of conjunctions indicates how many literals have been *)
642 (* added to that clause. simplify_clauses recursively splits conjunctions, *)
643 (* incrementing n as it proceeds, until it reaches a clause. It then calls *)
644 (* simplify_clause to deal with the clause. *)
645 (*----------------------------------------------------------------------------*)
647 let rec simplify_clause n tm =
648 try (let (th,change_flag) = simplify_one_literal n tm
649 in let tm' = rhs (concl th)
651 then ([],apply_proof ( fun ths -> EQT_ELIM th) [])
652 else let (tms,proof) =
653 if (change_flag < 0) then simplify_clause n tm'
654 else if (change_flag = 0) then simplify_clause (n + 1) tm'
655 else simplify_clauses (n + 1) tm'
656 in (tms,(fun ths -> EQ_MP (SYM th) (proof ths))))
657 with Failure _ -> ([tm],apply_proof hd [tm])
659 and simplify_clauses n tm =
660 try (let (tm1,tm2) = dest_conj tm
661 in let (tms1,proof1) = simplify_clauses (n + 1) tm1
662 and (tms2,proof2) = simplify_clauses (n + 1) tm2
664 fun ths -> let (ths1,ths2) = chop_list (length tms1) ths
665 in CONJ (proof1 ths1) (proof2 ths2)))
666 with Failure _ -> (simplify_clause n tm);;
669 let HL_simplify_clause tm =
671 let rules = itlist union [rewrite_rules();flat (defs());all_accessor_thms()] [] in
672 let th = SIMP_CONV rules tm
673 in let tm' = rhs (concl th)
674 in let tmc = try (rand o concl o COND_ELIM_CONV) tm' with Failure _ -> tm' in
676 then ([],apply_proof ( fun ths -> EQT_ELIM th ) [])
677 else ([tm'],apply_proof ((EQ_MP (SYM th)) o hd) [tm'])
679 with Failure _ -> ([tm],apply_proof hd [tm])
681 (*----------------------------------------------------------------------------*)
682 (* simplify_heuristic : (term # bool) -> ((term # bool) list # proof) *)
684 (* Wrapper for simplify_clause. This function has the correct type and *)
685 (* properties to be used as a `heuristic'. In particular, if the result of *)
686 (* simplify_clause is a single clause identical to the input clause, *)
687 (* a failure is generated. *)
688 (*----------------------------------------------------------------------------*)
690 let simplify_heuristic (tm,(ind:bool)) =
691 try (let (tms,proof) = simplify_clause 0 tm
694 else (proof_print_string_l "-> Simplify Heuristic" () ; (map (fun tm -> (tm,ind)) tms,proof))
695 ) with Failure _ -> failwith "simplify_heuristic";;
697 let HL_simplify_heuristic (tm,(ind:bool)) =
698 try (let (tms,proof) = HL_simplify_clause tm
701 else (proof_print_string_l "-> HL Simplify Heuristic" () ; (map (fun tm -> (tm,ind)) tms,proof))
702 ) with Failure _ -> failwith "HL_simplify_heuristic";;
704 (*----------------------------------------------------------------------------*)
705 (* NOT_EQ_F = |- !x. ~(x = x) = F *)
706 (*----------------------------------------------------------------------------*)
710 (TRANS (AP_TERM `(~)` (SPEC_ALL REFL_CLAUSE))
711 (el 1 (CONJUNCTS NOT_CLAUSES)));;
713 (*----------------------------------------------------------------------------*)
714 (* subst_heuristic : (term # bool) -> ((term # bool) list # proof) *)
716 (* `Heuristic' for eliminating from a clause, a negated equality between a *)
717 (* variable and another term not containing the variable. For example, given *)
720 (* x1 \/ ~(x = t) \/ x3 \/ f x \/ x5 *)
722 (* the function returns the clause: *)
724 (* x1 \/ F \/ x3 \/ f t \/ x5 *)
726 (* So, all occurrences of x are replaced by t, and the equality x = t is *)
727 (* `thrown away'. The F could be eliminated, but the simplification heuristic *)
728 (* will deal with it, so there is no point in duplicating the code. *)
730 (* The function fails if there are no equalities that can be eliminated. *)
732 (* The function proves the following three theorems: *)
734 (* ~(x = t) |- x1 \/ ~(x = t) \/ x3 \/ f x \/ x5 *)
736 (* x = t |- x1 \/ ~(x = t) \/ x3 \/ f x \/ x5 = *)
737 (* x1 \/ F \/ x3 \/ f t \/ x5 *)
739 (* |- (x = t) \/ ~(x = t) *)
741 (* and returns the term "x1 \/ F \/ x3 \/ f t \/ x5" to be proved. When given *)
742 (* this term as a theorem, it is possible to prove from the second theorem: *)
744 (* x = t |- x1 \/ ~(x = t) \/ x3 \/ f x \/ x5 *)
746 (* which together with the first and third theorems yields a theorem for the *)
747 (* original clause. *)
748 (*----------------------------------------------------------------------------*)
750 let subst_heuristic (tm,(ind:bool)) =
751 try (let checkx (v,t) = (is_var v) & (not (mem v (frees t)))
752 in let rec split_disjuncts tml =
753 if (can (check (checkx o dest_eq o dest_neg)) (hd tml))
755 else (fun (l1,l2) -> ((hd tml)::l1,l2)) (split_disjuncts (tl tml))
756 in let (overs,neq::unders) = split_disjuncts (disj_list tm)
757 in let eq = dest_neg neq
758 in let (v,t) = dest_eq eq
759 in let ass = ASSUME neq
760 in let th1 = itlist DISJ2 overs (try DISJ1 ass (list_mk_disj unders) with Failure _ -> ass)
761 and th2 = SUBS [ISPEC t NOT_EQ_F] (SUBST_CONV [(ASSUME eq,v)] tm tm)
762 and th3 = SPEC eq EXCLUDED_MIDDLE
763 in let tm' = rhs (concl th2)
764 in let proof th = DISJ_CASES th3 (EQ_MP (SYM th2) th) th1
765 in (proof_print_string_l "-> Subst Heuristic" () ; ([(tm',ind)],apply_proof (proof o hd) [tm']))
766 ) with Failure _ -> failwith "subst_heuristic";;