| author | wenzelm | 
| Thu, 15 Feb 2024 10:15:28 +0100 | |
| changeset 79614 | 58c0636e0ef5 | 
| parent 72004 | 913162a47d9f | 
| permissions | -rw-r--r-- | 
| 39348 | 1 | (* ========================================================================= *) | 
| 2 | (* DERIVED RULES FOR CREATING FIRST ORDER LOGIC THEOREMS *) | |
| 72004 | 3 | (* Copyright (c) 2001 Joe Leslie-Hurd, distributed under the BSD License *) | 
| 39348 | 4 | (* ========================================================================= *) | 
| 5 | ||
| 6 | structure Rule :> Rule = | |
| 7 | struct | |
| 8 | ||
| 9 | open Useful; | |
| 10 | ||
| 11 | (* ------------------------------------------------------------------------- *) | |
| 12 | (* Variable names. *) | |
| 13 | (* ------------------------------------------------------------------------- *) | |
| 14 | ||
| 15 | val xVarName = Name.fromString "x"; | |
| 16 | val xVar = Term.Var xVarName; | |
| 17 | ||
| 18 | val yVarName = Name.fromString "y"; | |
| 19 | val yVar = Term.Var yVarName; | |
| 20 | ||
| 21 | val zVarName = Name.fromString "z"; | |
| 22 | val zVar = Term.Var zVarName; | |
| 23 | ||
| 24 | fun xIVarName i = Name.fromString ("x" ^ Int.toString i);
 | |
| 25 | fun xIVar i = Term.Var (xIVarName i); | |
| 26 | ||
| 27 | fun yIVarName i = Name.fromString ("y" ^ Int.toString i);
 | |
| 28 | fun yIVar i = Term.Var (yIVarName i); | |
| 29 | ||
| 30 | (* ------------------------------------------------------------------------- *) | |
| 31 | (* *) | |
| 32 | (* --------- reflexivity *) | |
| 33 | (* x = x *) | |
| 34 | (* ------------------------------------------------------------------------- *) | |
| 35 | ||
| 36 | fun reflexivityRule x = Thm.refl x; | |
| 37 | ||
| 38 | val reflexivity = reflexivityRule xVar; | |
| 39 | ||
| 40 | (* ------------------------------------------------------------------------- *) | |
| 41 | (* *) | |
| 42 | (* --------------------- symmetry *) | |
| 43 | (* ~(x = y) \/ y = x *) | |
| 44 | (* ------------------------------------------------------------------------- *) | |
| 45 | ||
| 46 | fun symmetryRule x y = | |
| 47 | let | |
| 48 | val reflTh = reflexivityRule x | |
| 49 | val reflLit = Thm.destUnit reflTh | |
| 50 | val eqTh = Thm.equality reflLit [0] y | |
| 51 | in | |
| 52 | Thm.resolve reflLit reflTh eqTh | |
| 53 | end; | |
| 54 | ||
| 55 | val symmetry = symmetryRule xVar yVar; | |
| 56 | ||
| 57 | (* ------------------------------------------------------------------------- *) | |
| 58 | (* *) | |
| 59 | (* --------------------------------- transitivity *) | |
| 60 | (* ~(x = y) \/ ~(y = z) \/ x = z *) | |
| 61 | (* ------------------------------------------------------------------------- *) | |
| 62 | ||
| 63 | val transitivity = | |
| 64 | let | |
| 65 | val eqTh = Thm.equality (Literal.mkEq (yVar,zVar)) [0] xVar | |
| 66 | in | |
| 67 | Thm.resolve (Literal.mkEq (yVar,xVar)) symmetry eqTh | |
| 68 | end; | |
| 69 | ||
| 70 | (* ------------------------------------------------------------------------- *) | |
| 71 | (* x = y \/ C *) | |
| 72 | (* -------------- symEq (x = y) *) | |
| 73 | (* y = x \/ C *) | |
| 74 | (* ------------------------------------------------------------------------- *) | |
| 75 | ||
| 76 | fun symEq lit th = | |
| 77 | let | |
| 78 | val (x,y) = Literal.destEq lit | |
| 79 | in | |
| 80 | if Term.equal x y then th | |
| 81 | else | |
| 82 | let | |
| 83 | val sub = Subst.fromList [(xVarName,x),(yVarName,y)] | |
| 42102 | 84 | |
| 39348 | 85 | val symTh = Thm.subst sub symmetry | 
| 86 | in | |
| 87 | Thm.resolve lit th symTh | |
| 88 | end | |
| 89 | end; | |
| 90 | ||
| 91 | (* ------------------------------------------------------------------------- *) | |
| 92 | (* An equation consists of two terms (t,u) plus a theorem (stronger than) *) | |
| 93 | (* t = u \/ C. *) | |
| 94 | (* ------------------------------------------------------------------------- *) | |
| 95 | ||
| 96 | type equation = (Term.term * Term.term) * Thm.thm; | |
| 97 | ||
| 42102 | 98 | fun ppEquation ((_,th) : equation) = Thm.pp th; | 
| 39348 | 99 | |
| 42102 | 100 | val equationToString = Print.toString ppEquation; | 
| 39348 | 101 | |
| 102 | fun equationLiteral (t_u,th) = | |
| 103 | let | |
| 104 | val lit = Literal.mkEq t_u | |
| 105 | in | |
| 106 | if LiteralSet.member lit (Thm.clause th) then SOME lit else NONE | |
| 107 | end; | |
| 108 | ||
| 109 | fun reflEqn t = ((t,t), Thm.refl t); | |
| 110 | ||
| 111 | fun symEqn (eqn as ((t,u), th)) = | |
| 112 | if Term.equal t u then eqn | |
| 113 | else | |
| 114 | ((u,t), | |
| 115 | case equationLiteral eqn of | |
| 116 | SOME t_u => symEq t_u th | |
| 117 | | NONE => th); | |
| 118 | ||
| 119 | fun transEqn (eqn1 as ((x,y), th1)) (eqn2 as ((_,z), th2)) = | |
| 120 | if Term.equal x y then eqn2 | |
| 121 | else if Term.equal y z then eqn1 | |
| 122 | else if Term.equal x z then reflEqn x | |
| 123 | else | |
| 124 | ((x,z), | |
| 125 | case equationLiteral eqn1 of | |
| 126 | NONE => th1 | |
| 127 | | SOME x_y => | |
| 128 | case equationLiteral eqn2 of | |
| 129 | NONE => th2 | |
| 130 | | SOME y_z => | |
| 131 | let | |
| 132 | val sub = Subst.fromList [(xVarName,x),(yVarName,y),(zVarName,z)] | |
| 133 | val th = Thm.subst sub transitivity | |
| 134 | val th = Thm.resolve x_y th1 th | |
| 135 | val th = Thm.resolve y_z th2 th | |
| 136 | in | |
| 137 | th | |
| 138 | end); | |
| 139 | ||
| 140 | (*MetisDebug | |
| 141 | val transEqn = fn eqn1 => fn eqn2 => | |
| 142 | transEqn eqn1 eqn2 | |
| 143 | handle Error err => | |
| 144 |       raise Error ("Rule.transEqn:\neqn1 = " ^ equationToString eqn1 ^
 | |
| 145 | "\neqn2 = " ^ equationToString eqn2 ^ "\n" ^ err); | |
| 146 | *) | |
| 147 | ||
| 148 | (* ------------------------------------------------------------------------- *) | |
| 149 | (* A conversion takes a term t and either: *) | |
| 150 | (* 1. Returns a term u together with a theorem (stronger than) t = u \/ C. *) | |
| 151 | (* 2. Raises an Error exception. *) | |
| 152 | (* ------------------------------------------------------------------------- *) | |
| 153 | ||
| 154 | type conv = Term.term -> Term.term * Thm.thm; | |
| 155 | ||
| 156 | fun allConv tm = (tm, Thm.refl tm); | |
| 157 | ||
| 158 | val noConv : conv = fn _ => raise Error "noConv"; | |
| 159 | ||
| 39443 
e330437cd22a
copied the unmodified official Metis 2.3 (15 Sept. 2010) sources into Isabelle
 blanchet parents: 
39353diff
changeset | 160 | (*MetisDebug | 
| 39348 | 161 | fun traceConv s conv tm = | 
| 162 | let | |
| 163 | val res as (tm',th) = conv tm | |
| 39443 
e330437cd22a
copied the unmodified official Metis 2.3 (15 Sept. 2010) sources into Isabelle
 blanchet parents: 
39353diff
changeset | 164 | val () = trace (s ^ ": " ^ Term.toString tm ^ " --> " ^ | 
| 39348 | 165 | Term.toString tm' ^ " " ^ Thm.toString th ^ "\n") | 
| 166 | in | |
| 167 | res | |
| 168 | end | |
| 169 | handle Error err => | |
| 39443 
e330437cd22a
copied the unmodified official Metis 2.3 (15 Sept. 2010) sources into Isabelle
 blanchet parents: 
39353diff
changeset | 170 | (trace (s ^ ": " ^ Term.toString tm ^ " --> Error: " ^ err ^ "\n"); | 
| 39348 | 171 | raise Error (s ^ ": " ^ err)); | 
| 39443 
e330437cd22a
copied the unmodified official Metis 2.3 (15 Sept. 2010) sources into Isabelle
 blanchet parents: 
39353diff
changeset | 172 | *) | 
| 39348 | 173 | |
| 174 | fun thenConvTrans tm (tm',th1) (tm'',th2) = | |
| 175 | let | |
| 176 | val eqn1 = ((tm,tm'),th1) | |
| 177 | and eqn2 = ((tm',tm''),th2) | |
| 178 | val (_,th) = transEqn eqn1 eqn2 | |
| 179 | in | |
| 180 | (tm'',th) | |
| 181 | end; | |
| 182 | ||
| 183 | fun thenConv conv1 conv2 tm = | |
| 184 | let | |
| 185 | val res1 as (tm',_) = conv1 tm | |
| 186 | val res2 = conv2 tm' | |
| 187 | in | |
| 188 | thenConvTrans tm res1 res2 | |
| 189 | end; | |
| 190 | ||
| 191 | fun orelseConv (conv1 : conv) conv2 tm = conv1 tm handle Error _ => conv2 tm; | |
| 192 | ||
| 193 | fun tryConv conv = orelseConv conv allConv; | |
| 194 | ||
| 195 | fun changedConv conv tm = | |
| 196 | let | |
| 197 | val res as (tm',_) = conv tm | |
| 198 | in | |
| 199 | if tm = tm' then raise Error "changedConv" else res | |
| 200 | end; | |
| 201 | ||
| 202 | fun repeatConv conv tm = tryConv (thenConv conv (repeatConv conv)) tm; | |
| 203 | ||
| 204 | fun firstConv [] _ = raise Error "firstConv" | |
| 205 | | firstConv [conv] tm = conv tm | |
| 206 | | firstConv (conv :: convs) tm = orelseConv conv (firstConv convs) tm; | |
| 207 | ||
| 208 | fun everyConv [] tm = allConv tm | |
| 209 | | everyConv [conv] tm = conv tm | |
| 210 | | everyConv (conv :: convs) tm = thenConv conv (everyConv convs) tm; | |
| 211 | ||
| 212 | fun rewrConv (eqn as ((x,y), eqTh)) path tm = | |
| 213 | if Term.equal x y then allConv tm | |
| 42102 | 214 | else if List.null path then (y,eqTh) | 
| 39348 | 215 | else | 
| 216 | let | |
| 217 | val reflTh = Thm.refl tm | |
| 218 | val reflLit = Thm.destUnit reflTh | |
| 219 | val th = Thm.equality reflLit (1 :: path) y | |
| 220 | val th = Thm.resolve reflLit reflTh th | |
| 221 | val th = | |
| 222 | case equationLiteral eqn of | |
| 223 | NONE => th | |
| 224 | | SOME x_y => Thm.resolve x_y eqTh th | |
| 225 | val tm' = Term.replace tm (path,y) | |
| 226 | in | |
| 227 | (tm',th) | |
| 228 | end; | |
| 229 | ||
| 230 | (*MetisDebug | |
| 231 | val rewrConv = fn eqn as ((x,y),eqTh) => fn path => fn tm => | |
| 232 | rewrConv eqn path tm | |
| 233 | handle Error err => | |
| 234 |       raise Error ("Rule.rewrConv:\nx = " ^ Term.toString x ^
 | |
| 235 | "\ny = " ^ Term.toString y ^ | |
| 236 | "\neqTh = " ^ Thm.toString eqTh ^ | |
| 237 | "\npath = " ^ Term.pathToString path ^ | |
| 238 | "\ntm = " ^ Term.toString tm ^ "\n" ^ err); | |
| 239 | *) | |
| 240 | ||
| 241 | fun pathConv conv path tm = | |
| 242 | let | |
| 243 | val x = Term.subterm tm path | |
| 244 | val (y,th) = conv x | |
| 245 | in | |
| 246 | rewrConv ((x,y),th) path tm | |
| 247 | end; | |
| 248 | ||
| 249 | fun subtermConv conv i = pathConv conv [i]; | |
| 250 | ||
| 251 | fun subtermsConv _ (tm as Term.Var _) = allConv tm | |
| 252 | | subtermsConv conv (tm as Term.Fn (_,a)) = | |
| 42102 | 253 | everyConv (List.map (subtermConv conv) (interval 0 (length a))) tm; | 
| 39348 | 254 | |
| 255 | (* ------------------------------------------------------------------------- *) | |
| 256 | (* Applying a conversion to every subterm, with some traversal strategy. *) | |
| 257 | (* ------------------------------------------------------------------------- *) | |
| 258 | ||
| 259 | fun bottomUpConv conv tm = | |
| 260 | thenConv (subtermsConv (bottomUpConv conv)) (repeatConv conv) tm; | |
| 261 | ||
| 262 | fun topDownConv conv tm = | |
| 263 | thenConv (repeatConv conv) (subtermsConv (topDownConv conv)) tm; | |
| 264 | ||
| 265 | fun repeatTopDownConv conv = | |
| 266 | let | |
| 267 | fun f tm = thenConv (repeatConv conv) g tm | |
| 268 | and g tm = thenConv (subtermsConv f) h tm | |
| 269 | and h tm = tryConv (thenConv conv f) tm | |
| 270 | in | |
| 271 | f | |
| 272 | end; | |
| 273 | ||
| 274 | (*MetisDebug | |
| 275 | val repeatTopDownConv = fn conv => fn tm => | |
| 276 | repeatTopDownConv conv tm | |
| 277 |     handle Error err => raise Error ("repeatTopDownConv: " ^ err);
 | |
| 278 | *) | |
| 279 | ||
| 280 | (* ------------------------------------------------------------------------- *) | |
| 281 | (* A literule (bad pun) takes a literal L and either: *) | |
| 282 | (* 1. Returns a literal L' with a theorem (stronger than) ~L \/ L' \/ C. *) | |
| 283 | (* 2. Raises an Error exception. *) | |
| 284 | (* ------------------------------------------------------------------------- *) | |
| 285 | ||
| 286 | type literule = Literal.literal -> Literal.literal * Thm.thm; | |
| 287 | ||
| 288 | fun allLiterule lit = (lit, Thm.assume lit); | |
| 289 | ||
| 290 | val noLiterule : literule = fn _ => raise Error "noLiterule"; | |
| 291 | ||
| 292 | fun thenLiterule literule1 literule2 lit = | |
| 293 | let | |
| 294 | val res1 as (lit',th1) = literule1 lit | |
| 295 | val res2 as (lit'',th2) = literule2 lit' | |
| 296 | in | |
| 297 | if Literal.equal lit lit' then res2 | |
| 298 | else if Literal.equal lit' lit'' then res1 | |
| 299 | else if Literal.equal lit lit'' then allLiterule lit | |
| 300 | else | |
| 301 | (lit'', | |
| 302 | if not (Thm.member lit' th1) then th1 | |
| 303 | else if not (Thm.negateMember lit' th2) then th2 | |
| 304 | else Thm.resolve lit' th1 th2) | |
| 305 | end; | |
| 306 | ||
| 307 | fun orelseLiterule (literule1 : literule) literule2 lit = | |
| 308 | literule1 lit handle Error _ => literule2 lit; | |
| 309 | ||
| 310 | fun tryLiterule literule = orelseLiterule literule allLiterule; | |
| 311 | ||
| 312 | fun changedLiterule literule lit = | |
| 313 | let | |
| 314 | val res as (lit',_) = literule lit | |
| 315 | in | |
| 316 | if lit = lit' then raise Error "changedLiterule" else res | |
| 317 | end; | |
| 318 | ||
| 319 | fun repeatLiterule literule lit = | |
| 320 | tryLiterule (thenLiterule literule (repeatLiterule literule)) lit; | |
| 321 | ||
| 322 | fun firstLiterule [] _ = raise Error "firstLiterule" | |
| 323 | | firstLiterule [literule] lit = literule lit | |
| 324 | | firstLiterule (literule :: literules) lit = | |
| 325 | orelseLiterule literule (firstLiterule literules) lit; | |
| 326 | ||
| 327 | fun everyLiterule [] lit = allLiterule lit | |
| 328 | | everyLiterule [literule] lit = literule lit | |
| 329 | | everyLiterule (literule :: literules) lit = | |
| 330 | thenLiterule literule (everyLiterule literules) lit; | |
| 331 | ||
| 332 | fun rewrLiterule (eqn as ((x,y),eqTh)) path lit = | |
| 333 | if Term.equal x y then allLiterule lit | |
| 334 | else | |
| 335 | let | |
| 336 | val th = Thm.equality lit path y | |
| 337 | val th = | |
| 338 | case equationLiteral eqn of | |
| 339 | NONE => th | |
| 340 | | SOME x_y => Thm.resolve x_y eqTh th | |
| 341 | val lit' = Literal.replace lit (path,y) | |
| 342 | in | |
| 343 | (lit',th) | |
| 344 | end; | |
| 345 | ||
| 346 | (*MetisDebug | |
| 347 | val rewrLiterule = fn eqn => fn path => fn lit => | |
| 348 | rewrLiterule eqn path lit | |
| 349 | handle Error err => | |
| 350 |       raise Error ("Rule.rewrLiterule:\neqn = " ^ equationToString eqn ^
 | |
| 351 | "\npath = " ^ Term.pathToString path ^ | |
| 352 | "\nlit = " ^ Literal.toString lit ^ "\n" ^ err); | |
| 353 | *) | |
| 354 | ||
| 355 | fun pathLiterule conv path lit = | |
| 356 | let | |
| 357 | val tm = Literal.subterm lit path | |
| 358 | val (tm',th) = conv tm | |
| 359 | in | |
| 360 | rewrLiterule ((tm,tm'),th) path lit | |
| 361 | end; | |
| 362 | ||
| 363 | fun argumentLiterule conv i = pathLiterule conv [i]; | |
| 364 | ||
| 365 | fun allArgumentsLiterule conv lit = | |
| 366 | everyLiterule | |
| 42102 | 367 | (List.map (argumentLiterule conv) (interval 0 (Literal.arity lit))) lit; | 
| 39348 | 368 | |
| 369 | (* ------------------------------------------------------------------------- *) | |
| 370 | (* A rule takes one theorem and either deduces another or raises an Error *) | |
| 371 | (* exception. *) | |
| 372 | (* ------------------------------------------------------------------------- *) | |
| 373 | ||
| 374 | type rule = Thm.thm -> Thm.thm; | |
| 375 | ||
| 376 | val allRule : rule = fn th => th; | |
| 377 | ||
| 378 | val noRule : rule = fn _ => raise Error "noRule"; | |
| 379 | ||
| 380 | fun thenRule (rule1 : rule) (rule2 : rule) th = rule1 (rule2 th); | |
| 381 | ||
| 382 | fun orelseRule (rule1 : rule) rule2 th = rule1 th handle Error _ => rule2 th; | |
| 383 | ||
| 384 | fun tryRule rule = orelseRule rule allRule; | |
| 385 | ||
| 386 | fun changedRule rule th = | |
| 387 | let | |
| 388 | val th' = rule th | |
| 389 | in | |
| 390 | if not (LiteralSet.equal (Thm.clause th) (Thm.clause th')) then th' | |
| 391 | else raise Error "changedRule" | |
| 392 | end; | |
| 393 | ||
| 394 | fun repeatRule rule lit = tryRule (thenRule rule (repeatRule rule)) lit; | |
| 395 | ||
| 396 | fun firstRule [] _ = raise Error "firstRule" | |
| 397 | | firstRule [rule] th = rule th | |
| 398 | | firstRule (rule :: rules) th = orelseRule rule (firstRule rules) th; | |
| 399 | ||
| 400 | fun everyRule [] th = allRule th | |
| 401 | | everyRule [rule] th = rule th | |
| 402 | | everyRule (rule :: rules) th = thenRule rule (everyRule rules) th; | |
| 403 | ||
| 404 | fun literalRule literule lit th = | |
| 405 | let | |
| 406 | val (lit',litTh) = literule lit | |
| 407 | in | |
| 408 | if Literal.equal lit lit' then th | |
| 409 | else if not (Thm.negateMember lit litTh) then litTh | |
| 410 | else Thm.resolve lit th litTh | |
| 411 | end; | |
| 412 | ||
| 413 | (*MetisDebug | |
| 414 | val literalRule = fn literule => fn lit => fn th => | |
| 415 | literalRule literule lit th | |
| 416 | handle Error err => | |
| 417 |       raise Error ("Rule.literalRule:\nlit = " ^ Literal.toString lit ^
 | |
| 418 | "\nth = " ^ Thm.toString th ^ "\n" ^ err); | |
| 419 | *) | |
| 420 | ||
| 421 | fun rewrRule eqTh lit path = literalRule (rewrLiterule eqTh path) lit; | |
| 422 | ||
| 423 | fun pathRule conv lit path = literalRule (pathLiterule conv path) lit; | |
| 424 | ||
| 425 | fun literalsRule literule = | |
| 426 | let | |
| 427 | fun f (lit,th) = | |
| 428 | if Thm.member lit th then literalRule literule lit th else th | |
| 429 | in | |
| 430 | fn lits => fn th => LiteralSet.foldl f th lits | |
| 431 | end; | |
| 432 | ||
| 433 | fun allLiteralsRule literule th = literalsRule literule (Thm.clause th) th; | |
| 434 | ||
| 435 | fun convRule conv = allLiteralsRule (allArgumentsLiterule conv); | |
| 436 | ||
| 437 | (* ------------------------------------------------------------------------- *) | |
| 438 | (* *) | |
| 439 | (* ---------------------------------------------- functionCongruence (f,n) *) | |
| 440 | (*   ~(x0 = y0) \/ ... \/ ~(x{n-1} = y{n-1}) \/                              *)
 | |
| 441 | (*   f x0 ... x{n-1} = f y0 ... y{n-1}                                       *)
 | |
| 442 | (* ------------------------------------------------------------------------- *) | |
| 443 | ||
| 444 | fun functionCongruence (f,n) = | |
| 445 | let | |
| 446 | val xs = List.tabulate (n,xIVar) | |
| 447 | and ys = List.tabulate (n,yIVar) | |
| 448 | ||
| 449 | fun cong ((i,yi),(th,lit)) = | |
| 450 | let | |
| 451 | val path = [1,i] | |
| 452 | val th = Thm.resolve lit th (Thm.equality lit path yi) | |
| 453 | val lit = Literal.replace lit (path,yi) | |
| 454 | in | |
| 455 | (th,lit) | |
| 456 | end | |
| 457 | ||
| 458 | val reflTh = Thm.refl (Term.Fn (f,xs)) | |
| 459 | val reflLit = Thm.destUnit reflTh | |
| 460 | in | |
| 39443 
e330437cd22a
copied the unmodified official Metis 2.3 (15 Sept. 2010) sources into Isabelle
 blanchet parents: 
39353diff
changeset | 461 | fst (List.foldl cong (reflTh,reflLit) (enumerate ys)) | 
| 39348 | 462 | end; | 
| 463 | ||
| 464 | (* ------------------------------------------------------------------------- *) | |
| 465 | (* *) | |
| 466 | (* ---------------------------------------------- relationCongruence (R,n) *) | |
| 467 | (*   ~(x0 = y0) \/ ... \/ ~(x{n-1} = y{n-1}) \/                              *)
 | |
| 468 | (*   ~R x0 ... x{n-1} \/ R y0 ... y{n-1}                                     *)
 | |
| 469 | (* ------------------------------------------------------------------------- *) | |
| 470 | ||
| 471 | fun relationCongruence (R,n) = | |
| 472 | let | |
| 473 | val xs = List.tabulate (n,xIVar) | |
| 474 | and ys = List.tabulate (n,yIVar) | |
| 475 | ||
| 476 | fun cong ((i,yi),(th,lit)) = | |
| 477 | let | |
| 478 | val path = [i] | |
| 479 | val th = Thm.resolve lit th (Thm.equality lit path yi) | |
| 480 | val lit = Literal.replace lit (path,yi) | |
| 481 | in | |
| 482 | (th,lit) | |
| 483 | end | |
| 484 | ||
| 485 | val assumeLit = (false,(R,xs)) | |
| 486 | val assumeTh = Thm.assume assumeLit | |
| 487 | in | |
| 39443 
e330437cd22a
copied the unmodified official Metis 2.3 (15 Sept. 2010) sources into Isabelle
 blanchet parents: 
39353diff
changeset | 488 | fst (List.foldl cong (assumeTh,assumeLit) (enumerate ys)) | 
| 39348 | 489 | end; | 
| 490 | ||
| 491 | (* ------------------------------------------------------------------------- *) | |
| 492 | (* ~(x = y) \/ C *) | |
| 493 | (* ----------------- symNeq ~(x = y) *) | |
| 494 | (* ~(y = x) \/ C *) | |
| 495 | (* ------------------------------------------------------------------------- *) | |
| 496 | ||
| 497 | fun symNeq lit th = | |
| 498 | let | |
| 499 | val (x,y) = Literal.destNeq lit | |
| 500 | in | |
| 501 | if Term.equal x y then th | |
| 502 | else | |
| 503 | let | |
| 504 | val sub = Subst.fromList [(xVarName,y),(yVarName,x)] | |
| 505 | val symTh = Thm.subst sub symmetry | |
| 506 | in | |
| 507 | Thm.resolve lit th symTh | |
| 508 | end | |
| 509 | end; | |
| 510 | ||
| 511 | (* ------------------------------------------------------------------------- *) | |
| 512 | (* sym (x = y) = symEq (x = y) /\ sym ~(x = y) = symNeq ~(x = y) *) | |
| 513 | (* ------------------------------------------------------------------------- *) | |
| 514 | ||
| 515 | fun sym (lit as (pol,_)) th = if pol then symEq lit th else symNeq lit th; | |
| 516 | ||
| 517 | (* ------------------------------------------------------------------------- *) | |
| 518 | (* ~(x = x) \/ C *) | |
| 519 | (* ----------------- removeIrrefl *) | |
| 520 | (* C *) | |
| 521 | (* *) | |
| 522 | (* where all irreflexive equalities. *) | |
| 523 | (* ------------------------------------------------------------------------- *) | |
| 524 | ||
| 525 | local | |
| 526 | fun irrefl ((true,_),th) = th | |
| 527 | | irrefl (lit as (false,atm), th) = | |
| 528 | case total Atom.destRefl atm of | |
| 529 | SOME x => Thm.resolve lit th (Thm.refl x) | |
| 530 | | NONE => th; | |
| 531 | in | |
| 532 | fun removeIrrefl th = LiteralSet.foldl irrefl th (Thm.clause th); | |
| 533 | end; | |
| 534 | ||
| 535 | (* ------------------------------------------------------------------------- *) | |
| 536 | (* x = y \/ y = x \/ C *) | |
| 537 | (* ----------------------- removeSym *) | |
| 538 | (* x = y \/ C *) | |
| 539 | (* *) | |
| 540 | (* where all duplicate copies of equalities and disequalities are removed. *) | |
| 541 | (* ------------------------------------------------------------------------- *) | |
| 542 | ||
| 543 | local | |
| 544 | fun rem (lit as (pol,atm), eqs_th as (eqs,th)) = | |
| 545 | case total Atom.sym atm of | |
| 546 | NONE => eqs_th | |
| 547 | | SOME atm' => | |
| 548 | if LiteralSet.member lit eqs then | |
| 549 | (eqs, if pol then symEq lit th else symNeq lit th) | |
| 550 | else | |
| 551 | (LiteralSet.add eqs (pol,atm'), th); | |
| 552 | in | |
| 553 | fun removeSym th = | |
| 554 | snd (LiteralSet.foldl rem (LiteralSet.empty,th) (Thm.clause th)); | |
| 555 | end; | |
| 556 | ||
| 557 | (* ------------------------------------------------------------------------- *) | |
| 558 | (* ~(v = t) \/ C *) | |
| 559 | (* ----------------- expandAbbrevs *) | |
| 560 | (* C[t/v] *) | |
| 561 | (* *) | |
| 562 | (* where t must not contain any occurrence of the variable v. *) | |
| 563 | (* ------------------------------------------------------------------------- *) | |
| 564 | ||
| 565 | local | |
| 566 | fun expand lit = | |
| 567 | let | |
| 568 | val (x,y) = Literal.destNeq lit | |
| 569 | val _ = Term.isTypedVar x orelse Term.isTypedVar y orelse | |
| 570 | raise Error "Rule.expandAbbrevs: no vars" | |
| 571 | val _ = not (Term.equal x y) orelse | |
| 572 | raise Error "Rule.expandAbbrevs: equal vars" | |
| 573 | in | |
| 574 | Subst.unify Subst.empty x y | |
| 575 | end; | |
| 576 | in | |
| 577 | fun expandAbbrevs th = | |
| 578 | case LiteralSet.firstl (total expand) (Thm.clause th) of | |
| 579 | NONE => removeIrrefl th | |
| 580 | | SOME sub => expandAbbrevs (Thm.subst sub th); | |
| 581 | end; | |
| 582 | ||
| 583 | (* ------------------------------------------------------------------------- *) | |
| 584 | (* simplify = isTautology + expandAbbrevs + removeSym *) | |
| 585 | (* ------------------------------------------------------------------------- *) | |
| 586 | ||
| 587 | fun simplify th = | |
| 588 | if Thm.isTautology th then NONE | |
| 589 | else | |
| 590 | let | |
| 591 | val th' = th | |
| 592 | val th' = expandAbbrevs th' | |
| 593 | val th' = removeSym th' | |
| 594 | in | |
| 595 | if Thm.equal th th' then SOME th else simplify th' | |
| 596 | end; | |
| 597 | ||
| 598 | (* ------------------------------------------------------------------------- *) | |
| 599 | (* C *) | |
| 600 | (* -------- freshVars *) | |
| 601 | (* C[s] *) | |
| 602 | (* *) | |
| 603 | (* where s is a renaming substitution chosen so that all of the variables in *) | |
| 604 | (* C are replaced by fresh variables. *) | |
| 605 | (* ------------------------------------------------------------------------- *) | |
| 606 | ||
| 607 | fun freshVars th = Thm.subst (Subst.freshVars (Thm.freeVars th)) th; | |
| 608 | ||
| 609 | (* ------------------------------------------------------------------------- *) | |
| 610 | (* C *) | |
| 611 | (* ---------------------------- factor *) | |
| 612 | (* C_s_1, C_s_2, ..., C_s_n *) | |
| 613 | (* *) | |
| 614 | (* where each s_i is a substitution that factors C, meaning that the theorem *) | |
| 615 | (* *) | |
| 616 | (* C_s_i = (removeIrrefl o removeSym o Thm.subst s_i) C *) | |
| 617 | (* *) | |
| 618 | (* has fewer literals than C. *) | |
| 619 | (* *) | |
| 620 | (* Also, if s is any substitution that factors C, then one of the s_i will *) | |
| 621 | (* result in a theorem C_s_i that strictly subsumes the theorem C_s. *) | |
| 622 | (* ------------------------------------------------------------------------- *) | |
| 623 | ||
| 624 | local | |
| 625 | datatype edge = | |
| 626 | FactorEdge of Atom.atom * Atom.atom | |
| 627 | | ReflEdge of Term.term * Term.term; | |
| 628 | ||
| 629 | fun ppEdge (FactorEdge atm_atm') = Print.ppPair Atom.pp Atom.pp atm_atm' | |
| 630 | | ppEdge (ReflEdge tm_tm') = Print.ppPair Term.pp Term.pp tm_tm'; | |
| 631 | ||
| 632 | datatype joinStatus = | |
| 633 | Joined | |
| 634 | | Joinable of Subst.subst | |
| 635 | | Apart; | |
| 636 | ||
| 637 | fun joinEdge sub edge = | |
| 638 | let | |
| 639 | val result = | |
| 640 | case edge of | |
| 641 | FactorEdge (atm,atm') => total (Atom.unify sub atm) atm' | |
| 642 | | ReflEdge (tm,tm') => total (Subst.unify sub tm) tm' | |
| 643 | in | |
| 644 | case result of | |
| 645 | NONE => Apart | |
| 646 | | SOME sub' => | |
| 647 | if Portable.pointerEqual (sub,sub') then Joined else Joinable sub' | |
| 648 | end; | |
| 649 | ||
| 650 | fun updateApart sub = | |
| 651 | let | |
| 652 | fun update acc [] = SOME acc | |
| 653 | | update acc (edge :: edges) = | |
| 654 | case joinEdge sub edge of | |
| 655 | Joined => NONE | |
| 656 | | Joinable _ => update (edge :: acc) edges | |
| 657 | | Apart => update acc edges | |
| 658 | in | |
| 659 | update [] | |
| 660 | end; | |
| 661 | ||
| 662 | fun addFactorEdge (pol,atm) ((pol',atm'),acc) = | |
| 663 | if pol <> pol' then acc | |
| 664 | else | |
| 665 | let | |
| 666 | val edge = FactorEdge (atm,atm') | |
| 667 | in | |
| 668 | case joinEdge Subst.empty edge of | |
| 669 | Joined => raise Bug "addFactorEdge: joined" | |
| 670 | | Joinable sub => (sub,edge) :: acc | |
| 671 | | Apart => acc | |
| 672 | end; | |
| 673 | ||
| 674 | fun addReflEdge (false,_) acc = acc | |
| 675 | | addReflEdge (true,atm) acc = | |
| 676 | let | |
| 677 | val edge = ReflEdge (Atom.destEq atm) | |
| 678 | in | |
| 679 | case joinEdge Subst.empty edge of | |
| 680 | Joined => raise Bug "addRefl: joined" | |
| 681 | | Joinable _ => edge :: acc | |
| 682 | | Apart => acc | |
| 683 | end; | |
| 684 | ||
| 685 | fun addIrreflEdge (true,_) acc = acc | |
| 686 | | addIrreflEdge (false,atm) acc = | |
| 687 | let | |
| 688 | val edge = ReflEdge (Atom.destEq atm) | |
| 689 | in | |
| 690 | case joinEdge Subst.empty edge of | |
| 691 | Joined => raise Bug "addRefl: joined" | |
| 692 | | Joinable sub => (sub,edge) :: acc | |
| 693 | | Apart => acc | |
| 694 | end; | |
| 695 | ||
| 696 | fun init_edges acc _ [] = | |
| 697 | let | |
| 698 | fun init ((apart,sub,edge),(edges,acc)) = | |
| 699 | (edge :: edges, (apart,sub,edges) :: acc) | |
| 700 | in | |
| 701 | snd (List.foldl init ([],[]) acc) | |
| 702 | end | |
| 703 | | init_edges acc apart ((sub,edge) :: sub_edges) = | |
| 704 | let | |
| 705 | (*MetisDebug | |
| 706 | val () = if not (Subst.null sub) then () | |
| 707 | else raise Bug "Rule.factor.init_edges: empty subst" | |
| 708 | *) | |
| 709 | val (acc,apart) = | |
| 710 | case updateApart sub apart of | |
| 711 | SOME apart' => ((apart',sub,edge) :: acc, edge :: apart) | |
| 712 | | NONE => (acc,apart) | |
| 713 | in | |
| 714 | init_edges acc apart sub_edges | |
| 715 | end; | |
| 716 | ||
| 717 | fun mk_edges apart sub_edges [] = init_edges [] apart sub_edges | |
| 718 | | mk_edges apart sub_edges (lit :: lits) = | |
| 719 | let | |
| 720 | val sub_edges = List.foldl (addFactorEdge lit) sub_edges lits | |
| 721 | ||
| 722 | val (apart,sub_edges) = | |
| 723 | case total Literal.sym lit of | |
| 724 | NONE => (apart,sub_edges) | |
| 725 | | SOME lit' => | |
| 726 | let | |
| 727 | val apart = addReflEdge lit apart | |
| 728 | val sub_edges = addIrreflEdge lit sub_edges | |
| 729 | val sub_edges = List.foldl (addFactorEdge lit') sub_edges lits | |
| 730 | in | |
| 731 | (apart,sub_edges) | |
| 732 | end | |
| 733 | in | |
| 734 | mk_edges apart sub_edges lits | |
| 735 | end; | |
| 736 | ||
| 737 | fun fact acc [] = acc | |
| 738 | | fact acc ((_,sub,[]) :: others) = fact (sub :: acc) others | |
| 739 | | fact acc ((apart, sub, edge :: edges) :: others) = | |
| 740 | let | |
| 741 | val others = | |
| 742 | case joinEdge sub edge of | |
| 743 | Joinable sub' => | |
| 744 | let | |
| 745 | val others = (edge :: apart, sub, edges) :: others | |
| 746 | in | |
| 747 | case updateApart sub' apart of | |
| 748 | NONE => others | |
| 749 | | SOME apart' => (apart',sub',edges) :: others | |
| 750 | end | |
| 751 | | _ => (apart,sub,edges) :: others | |
| 752 | in | |
| 753 | fact acc others | |
| 754 | end; | |
| 755 | in | |
| 756 | fun factor' cl = | |
| 757 | let | |
| 758 | (*MetisTrace6 | |
| 759 | val () = Print.trace LiteralSet.pp "Rule.factor': cl" cl | |
| 760 | *) | |
| 761 | val edges = mk_edges [] [] (LiteralSet.toList cl) | |
| 762 | (*MetisTrace6 | |
| 763 | val ppEdgesSize = Print.ppMap length Print.ppInt | |
| 764 | val ppEdgel = Print.ppList ppEdge | |
| 765 | val ppEdges = Print.ppList (Print.ppTriple ppEdgel Subst.pp ppEdgel) | |
| 766 | val () = Print.trace ppEdgesSize "Rule.factor': |edges|" edges | |
| 767 | val () = Print.trace ppEdges "Rule.factor': edges" edges | |
| 768 | *) | |
| 769 | val result = fact [] edges | |
| 770 | (*MetisTrace6 | |
| 771 | val ppResult = Print.ppList Subst.pp | |
| 772 | val () = Print.trace ppResult "Rule.factor': result" result | |
| 773 | *) | |
| 774 | in | |
| 775 | result | |
| 776 | end; | |
| 777 | end; | |
| 778 | ||
| 779 | fun factor th = | |
| 780 | let | |
| 72004 | 781 | fun fact sub = removeIrrefl (removeSym (Thm.subst sub th)) | 
| 39348 | 782 | in | 
| 42102 | 783 | List.map fact (factor' (Thm.clause th)) | 
| 39348 | 784 | end; | 
| 785 | ||
| 786 | end |