376 in if 1 <= i andalso i <= n |
376 in if 1 <= i andalso i <= n |
377 then Thm.permute_prems (i-1) 1 th |
377 then Thm.permute_prems (i-1) 1 th |
378 else raise THM("select_literal", i, [th]) |
378 else raise THM("select_literal", i, [th]) |
379 end; |
379 end; |
380 |
380 |
381 val neg_neg_imp = @{lemma "~ ~ Q ==> Q" by blast} |
|
382 |
|
383 val not_atomize = |
|
384 @{lemma "(~ A ==> False) == Trueprop A" |
|
385 by (cut_tac atomize_not [of "~ A"]) simp} |
|
386 |
|
387 (* Maps a rule that ends "... ==> P ==> False" to "... ==> ~ P" while avoiding |
381 (* Maps a rule that ends "... ==> P ==> False" to "... ==> ~ P" while avoiding |
388 to create double negations. *) |
382 to create double negations. The "select" wrapper is a trick to ensure that |
389 val negate_head = fold (rewrite_rule o single) [not_atomize, atomize_not] |
383 "P ==> ~ False ==> False" is rewritten to "P ==> False", not to "~ P". We |
|
384 don't use this trick in general because it makes the proof object uglier than |
|
385 necessary. FIXME. *) |
|
386 fun negate_head th = |
|
387 if exists (fn t => t aconv @{prop "~ False"}) (prems_of th) then |
|
388 (th RS @{thm select_FalseI}) |
|
389 |> fold (rewrite_rule o single) |
|
390 @{thms not_atomize_select atomize_not_select} |
|
391 else |
|
392 th |> fold (rewrite_rule o single) @{thms not_atomize atomize_not} |
390 |
393 |
391 (* Maps the clause [P1,...Pn]==>False to [P1,...,P(i-1),P(i+1),...Pn] ==> ~P *) |
394 (* Maps the clause [P1,...Pn]==>False to [P1,...,P(i-1),P(i+1),...Pn] ==> ~P *) |
392 val select_literal = negate_head oo make_last |
395 val select_literal = negate_head oo make_last |
393 |
396 |
394 fun resolve_inf ctxt mode skolem_params thpairs atm th1 th2 = |
397 fun resolve_inf ctxt mode skolem_params thpairs atm th1 th2 = |