1 (* ========================================================================= *) |
1 (* ========================================================================= *) |
2 (* ORDERED REWRITING FOR FIRST ORDER TERMS *) |
2 (* ORDERED REWRITING FOR FIRST ORDER TERMS *) |
3 (* Copyright (c) 2003-2006 Joe Hurd, distributed under the BSD License *) |
3 (* Copyright (c) 2003-2006 Joe Hurd, distributed under the BSD License *) |
4 (* ========================================================================= *) |
4 (* ========================================================================= *) |
5 |
5 |
6 structure Rewrite :> Rewrite = |
6 structure Rewrite :> Rewrite = |
7 struct |
7 struct |
8 |
8 |
9 open Useful; |
9 open Useful; |
10 |
10 |
11 (* ------------------------------------------------------------------------- *) |
11 (* ------------------------------------------------------------------------- *) |
|
12 (* Orientations of equations. *) |
|
13 (* ------------------------------------------------------------------------- *) |
|
14 |
|
15 datatype orient = LeftToRight | RightToLeft; |
|
16 |
|
17 fun toStringOrient ort = |
|
18 case ort of |
|
19 LeftToRight => "-->" |
|
20 | RightToLeft => "<--"; |
|
21 |
|
22 val ppOrient = Print.ppMap toStringOrient Print.ppString; |
|
23 |
|
24 fun toStringOrientOption orto = |
|
25 case orto of |
|
26 SOME ort => toStringOrient ort |
|
27 | NONE => "<->"; |
|
28 |
|
29 val ppOrientOption = Print.ppMap toStringOrientOption Print.ppString; |
|
30 |
|
31 (* ------------------------------------------------------------------------- *) |
12 (* A type of rewrite systems. *) |
32 (* A type of rewrite systems. *) |
13 (* ------------------------------------------------------------------------- *) |
33 (* ------------------------------------------------------------------------- *) |
14 |
|
15 datatype orient = LeftToRight | RightToLeft; |
|
16 |
34 |
17 type reductionOrder = Term.term * Term.term -> order option; |
35 type reductionOrder = Term.term * Term.term -> order option; |
18 |
36 |
19 type equationId = int; |
37 type equationId = int; |
20 |
38 |
57 fun size (Rewrite {known,...}) = IntMap.size known; |
75 fun size (Rewrite {known,...}) = IntMap.size known; |
58 |
76 |
59 fun equations (Rewrite {known,...}) = |
77 fun equations (Rewrite {known,...}) = |
60 IntMap.foldr (fn (_,(eqn,_),eqns) => eqn :: eqns) [] known; |
78 IntMap.foldr (fn (_,(eqn,_),eqns) => eqn :: eqns) [] known; |
61 |
79 |
62 val pp = Parser.ppMap equations (Parser.ppList Rule.ppEquation); |
80 val pp = Print.ppMap equations (Print.ppList Rule.ppEquation); |
63 |
81 |
64 (*DEBUG |
82 (*MetisTrace1 |
65 local |
83 local |
66 fun orientOptionToString ort = |
84 fun ppEq ((x_y,_),ort) = |
67 case ort of |
85 Print.ppOp2 (" " ^ toStringOrientOption ort) Term.pp Term.pp x_y; |
68 SOME LeftToRight => "-->" |
86 |
69 | SOME RightToLeft => "<--" |
87 fun ppField f ppA a = |
70 | NONE => "<->"; |
88 Print.blockProgram Print.Inconsistent 2 |
71 |
89 [Print.addString (f ^ " ="), |
72 open Parser; |
90 Print.addBreak 1, |
73 |
91 ppA a]; |
74 fun ppEq p ((x_y,_),ort) = |
|
75 ppBinop (" " ^ orientOptionToString ort) Term.pp Term.pp p x_y; |
|
76 |
|
77 fun ppField f ppA p a = |
|
78 (beginBlock p Inconsistent 2; |
|
79 addString p (f ^ " ="); |
|
80 addBreak p (1,0); |
|
81 ppA p a; |
|
82 endBlock p); |
|
83 |
92 |
84 val ppKnown = |
93 val ppKnown = |
85 ppField "known" (ppMap IntMap.toList (ppList (ppPair ppInt ppEq))); |
94 ppField "known" |
|
95 (Print.ppMap IntMap.toList |
|
96 (Print.ppList (Print.ppPair Print.ppInt ppEq))); |
86 |
97 |
87 val ppRedexes = |
98 val ppRedexes = |
88 ppField |
99 ppField "redexes" |
89 "redexes" |
100 (TermNet.pp (Print.ppPair Print.ppInt ppOrient)); |
|
101 |
|
102 val ppSubterms = |
|
103 ppField "subterms" |
90 (TermNet.pp |
104 (TermNet.pp |
91 (ppPair ppInt (ppMap (orientOptionToString o SOME) ppString))); |
105 (Print.ppMap |
92 |
|
93 val ppSubterms = |
|
94 ppField |
|
95 "subterms" |
|
96 (TermNet.pp |
|
97 (ppMap |
|
98 (fn (i,l,p) => (i, (if l then 0 else 1) :: p)) |
106 (fn (i,l,p) => (i, (if l then 0 else 1) :: p)) |
99 (ppPair ppInt Term.ppPath))); |
107 (Print.ppPair Print.ppInt Term.ppPath))); |
100 |
108 |
101 val ppWaiting = ppField "waiting" (ppMap (IntSet.toList) (ppList ppInt)); |
109 val ppWaiting = |
|
110 ppField "waiting" |
|
111 (Print.ppMap (IntSet.toList) (Print.ppList Print.ppInt)); |
102 in |
112 in |
103 fun pp p (Rewrite {known,redexes,subterms,waiting,...}) = |
113 fun pp (Rewrite {known,redexes,subterms,waiting,...}) = |
104 (beginBlock p Inconsistent 2; |
114 Print.blockProgram Print.Inconsistent 2 |
105 addString p "Rewrite"; |
115 [Print.addString "Rewrite", |
106 addBreak p (1,0); |
116 Print.addBreak 1, |
107 beginBlock p Inconsistent 1; |
117 Print.blockProgram Print.Inconsistent 1 |
108 addString p "{"; |
118 [Print.addString "{", |
109 ppKnown p known; |
119 ppKnown known, |
110 (*TRACE5 |
120 (*MetisTrace5 |
111 addString p ","; |
121 Print.addString ",", |
112 addBreak p (1,0); |
122 Print.addBreak 1, |
113 ppRedexes p redexes; |
123 ppRedexes redexes, |
114 addString p ","; |
124 Print.addString ",", |
115 addBreak p (1,0); |
125 Print.addBreak 1, |
116 ppSubterms p subterms; |
126 ppSubterms subterms, |
117 addString p ","; |
127 Print.addString ",", |
118 addBreak p (1,0); |
128 Print.addBreak 1, |
119 ppWaiting p waiting; |
129 ppWaiting waiting, |
120 *) |
130 *) |
121 endBlock p; |
131 Print.skip], |
122 addString p "}"; |
132 Print.addString "}"] |
123 endBlock p); |
|
124 end; |
133 end; |
125 *) |
134 *) |
126 |
135 |
127 val toString = Parser.toString pp; |
136 val toString = Print.toString pp; |
128 |
137 |
129 (* ------------------------------------------------------------------------- *) |
138 (* ------------------------------------------------------------------------- *) |
130 (* Debug functions. *) |
139 (* Debug functions. *) |
131 (* ------------------------------------------------------------------------- *) |
140 (* ------------------------------------------------------------------------- *) |
132 |
141 |
135 fun eqnRed ((l,r),_) tm = |
144 fun eqnRed ((l,r),_) tm = |
136 case total (Subst.match Subst.empty l) tm of |
145 case total (Subst.match Subst.empty l) tm of |
137 NONE => false |
146 NONE => false |
138 | SOME sub => |
147 | SOME sub => |
139 order (tm, Subst.subst (Subst.normalize sub) r) = SOME GREATER |
148 order (tm, Subst.subst (Subst.normalize sub) r) = SOME GREATER |
140 |
149 |
141 fun knownRed tm (eqnId,(eqn,ort)) = |
150 fun knownRed tm (eqnId,(eqn,ort)) = |
142 eqnId <> id andalso |
151 eqnId <> id andalso |
143 ((ort <> SOME RightToLeft andalso eqnRed eqn tm) orelse |
152 ((ort <> SOME RightToLeft andalso eqnRed eqn tm) orelse |
144 (ort <> SOME LeftToRight andalso eqnRed (Rule.symEqn eqn) tm)) |
153 (ort <> SOME LeftToRight andalso eqnRed (Rule.symEqn eqn) tm)) |
145 |
154 |
254 in |
263 in |
255 case order (l,r) of |
264 case order (l,r) of |
256 NONE => raise Error "incomparable" |
265 NONE => raise Error "incomparable" |
257 | SOME LESS => |
266 | SOME LESS => |
258 let |
267 let |
259 val sub = Subst.fromList [("x",l),("y",r)] |
268 val th = Rule.symmetryRule l r |
260 val th = Thm.subst sub Rule.symmetry |
|
261 in |
269 in |
262 fn tm => if tm = r then (l,th) else raise Error "mkNeqConv: RL" |
270 fn tm => |
|
271 if Term.equal tm r then (l,th) else raise Error "mkNeqConv: RL" |
263 end |
272 end |
264 | SOME EQUAL => raise Error "irreflexive" |
273 | SOME EQUAL => raise Error "irreflexive" |
265 | SOME GREATER => |
274 | SOME GREATER => |
266 let |
275 let |
267 val th = Thm.assume lit |
276 val th = Thm.assume lit |
268 in |
277 in |
269 fn tm => if tm = l then (r,th) else raise Error "mkNeqConv: LR" |
278 fn tm => |
|
279 if Term.equal tm l then (r,th) else raise Error "mkNeqConv: LR" |
270 end |
280 end |
271 end; |
281 end; |
272 |
282 |
273 datatype neqConvs = NeqConvs of Rule.conv LiteralMap.map; |
283 datatype neqConvs = NeqConvs of Rule.conv LiteralMap.map; |
274 |
284 |
319 case Rule.equationLiteral eqn of |
329 case Rule.equationLiteral eqn of |
320 NONE => (true, Literal.mkEq l_r) |
330 NONE => (true, Literal.mkEq l_r) |
321 | SOME lit => (false,lit) |
331 | SOME lit => (false,lit) |
322 val (lit',litTh) = literule lit |
332 val (lit',litTh) = literule lit |
323 in |
333 in |
324 if lit = lit' then eqn |
334 if Literal.equal lit lit' then eqn |
325 else |
335 else |
326 (Literal.destEq lit', |
336 (Literal.destEq lit', |
327 if strongEqn then th |
337 if strongEqn then th |
328 else if not (Thm.negateMember lit litTh) then litTh |
338 else if not (Thm.negateMember lit litTh) then litTh |
329 else Thm.resolve lit th litTh) |
339 else Thm.resolve lit th litTh) |
330 end |
340 end |
331 (*DEBUG |
341 (*MetisDebug |
332 handle Error err => raise Error ("Rewrite.rewriteIdEqn':\n" ^ err); |
342 handle Error err => raise Error ("Rewrite.rewriteIdEqn':\n" ^ err); |
333 *) |
343 *) |
334 |
344 |
335 fun rewriteIdLiteralsRule' order known redexes id lits th = |
345 fun rewriteIdLiteralsRule' order known redexes id lits th = |
336 let |
346 let |
339 fun rewr_neq_lit (lit, acc as (changed,neq,lits,th)) = |
349 fun rewr_neq_lit (lit, acc as (changed,neq,lits,th)) = |
340 let |
350 let |
341 val neq = neqConvsDelete neq lit |
351 val neq = neqConvsDelete neq lit |
342 val (lit',litTh) = mk_literule neq lit |
352 val (lit',litTh) = mk_literule neq lit |
343 in |
353 in |
344 if lit = lit' then acc |
354 if Literal.equal lit lit' then acc |
345 else |
355 else |
346 let |
356 let |
347 val th = Thm.resolve lit th litTh |
357 val th = Thm.resolve lit th litTh |
348 in |
358 in |
349 case neqConvsAdd order neq lit' of |
359 case neqConvsAdd order neq lit' of |
375 end; |
385 end; |
376 |
386 |
377 fun rewriteIdRule' order known redexes id th = |
387 fun rewriteIdRule' order known redexes id th = |
378 rewriteIdLiteralsRule' order known redexes id (Thm.clause th) th; |
388 rewriteIdLiteralsRule' order known redexes id (Thm.clause th) th; |
379 |
389 |
380 (*DEBUG |
390 (*MetisDebug |
381 val rewriteIdRule' = fn order => fn known => fn redexes => fn id => fn th => |
391 val rewriteIdRule' = fn order => fn known => fn redexes => fn id => fn th => |
382 let |
392 let |
383 (*TRACE6 |
393 (*MetisTrace6 |
384 val () = Parser.ppTrace Thm.pp "Rewrite.rewriteIdRule': th" th |
394 val () = Print.trace Thm.pp "Rewrite.rewriteIdRule': th" th |
385 *) |
395 *) |
386 val result = rewriteIdRule' order known redexes id th |
396 val result = rewriteIdRule' order known redexes id th |
387 (*TRACE6 |
397 (*MetisTrace6 |
388 val () = Parser.ppTrace Thm.pp "Rewrite.rewriteIdRule': result" result |
398 val () = Print.trace Thm.pp "Rewrite.rewriteIdRule': result" result |
389 *) |
399 *) |
390 val _ = not (thmReducible order known id result) orelse |
400 val _ = not (thmReducible order known id result) orelse |
391 raise Bug "rewriteIdRule: should be normalized" |
401 raise Bug "rewriteIdRule: should be normalized" |
392 in |
402 in |
393 result |
403 result |
429 in |
439 in |
430 subterms |
440 subterms |
431 end; |
441 end; |
432 |
442 |
433 fun sameRedexes NONE _ _ = false |
443 fun sameRedexes NONE _ _ = false |
434 | sameRedexes (SOME LeftToRight) (l0,_) (l,_) = l0 = l |
444 | sameRedexes (SOME LeftToRight) (l0,_) (l,_) = Term.equal l0 l |
435 | sameRedexes (SOME RightToLeft) (_,r0) (_,r) = r0 = r; |
445 | sameRedexes (SOME RightToLeft) (_,r0) (_,r) = Term.equal r0 r; |
436 |
446 |
437 fun redexResidues NONE (l,r) = [(l,r,false),(r,l,false)] |
447 fun redexResidues NONE (l,r) = [(l,r,false),(r,l,false)] |
438 | redexResidues (SOME LeftToRight) (l,r) = [(l,r,true)] |
448 | redexResidues (SOME LeftToRight) (l,r) = [(l,r,true)] |
439 | redexResidues (SOME RightToLeft) (l,r) = [(r,l,true)]; |
449 | redexResidues (SOME RightToLeft) (l,r) = [(r,l,true)]; |
440 |
450 |
453 in |
463 in |
454 if order (tm,tm') = SOME GREATER then () |
464 if order (tm,tm') = SOME GREATER then () |
455 else raise Error "order" |
465 else raise Error "order" |
456 end |
466 end |
457 end |
467 end |
458 |
468 |
459 fun addRed lr ((id',left,path),todo) = |
469 fun addRed lr ((id',left,path),todo) = |
460 if id <> id' andalso not (IntSet.member id' todo) andalso |
470 if id <> id' andalso not (IntSet.member id' todo) andalso |
461 can (checkValidRewr lr id' left) path |
471 can (checkValidRewr lr id' left) path |
462 then IntSet.add todo id' |
472 then IntSet.add todo id' |
463 else todo |
473 else todo |
464 |
474 |
465 fun findRed (lr as (l,_,_), todo) = |
475 fun findRed (lr as (l,_,_), todo) = |
466 List.foldl (addRed lr) todo (TermNet.matched subterms l) |
476 List.foldl (addRed lr) todo (TermNet.matched subterms l) |
467 in |
477 in |
468 List.foldl findRed |
478 List.foldl findRed |
469 end; |
479 end; |
471 fun reduce1 new id (eqn0,ort0) (rpl,spl,todo,rw,changed) = |
481 fun reduce1 new id (eqn0,ort0) (rpl,spl,todo,rw,changed) = |
472 let |
482 let |
473 val (eq0,_) = eqn0 |
483 val (eq0,_) = eqn0 |
474 val Rewrite {order,known,redexes,subterms,waiting} = rw |
484 val Rewrite {order,known,redexes,subterms,waiting} = rw |
475 val eqn as (eq,_) = rewriteIdEqn' order known redexes id eqn0 |
485 val eqn as (eq,_) = rewriteIdEqn' order known redexes id eqn0 |
476 val identical = eq = eq0 |
486 val identical = |
|
487 let |
|
488 val (l0,r0) = eq0 |
|
489 and (l,r) = eq |
|
490 in |
|
491 Term.equal l l0 andalso Term.equal r r0 |
|
492 end |
477 val same_redexes = identical orelse sameRedexes ort0 eq0 eq |
493 val same_redexes = identical orelse sameRedexes ort0 eq0 eq |
478 val rpl = if same_redexes then rpl else IntSet.add rpl id |
494 val rpl = if same_redexes then rpl else IntSet.add rpl id |
479 val spl = if new orelse identical then spl else IntSet.add spl id |
495 val spl = if new orelse identical then spl else IntSet.add spl id |
480 val changed = |
496 val changed = |
481 if not new andalso identical then changed else IntSet.add changed id |
497 if not new andalso identical then changed else IntSet.add changed id |
558 |
574 |
559 fun addSubtms (id,subtms) = |
575 fun addSubtms (id,subtms) = |
560 case IntMap.peek known id of |
576 case IntMap.peek known id of |
561 NONE => subtms |
577 NONE => subtms |
562 | SOME (eqn,_) => addSubterms id eqn subtms |
578 | SOME (eqn,_) => addSubterms id eqn subtms |
563 |
579 |
564 val subterms = TermNet.filter filt subterms |
580 val subterms = TermNet.filter filt subterms |
565 val subterms = IntSet.foldl addSubtms subterms spl |
581 val subterms = IntSet.foldl addSubtms subterms spl |
566 in |
582 in |
567 subterms |
583 subterms |
568 end; |
584 end; |
569 in |
585 in |
570 fun rebuild rpl spl rw = |
586 fun rebuild rpl spl rw = |
571 let |
587 let |
572 (*TRACE5 |
588 (*MetisTrace5 |
573 val ppPl = Parser.ppMap IntSet.toList (Parser.ppList Parser.ppInt) |
589 val ppPl = Print.ppMap IntSet.toList (Print.ppList Print.ppInt) |
574 val () = Parser.ppTrace ppPl "Rewrite.rebuild: rpl" rpl |
590 val () = Print.trace ppPl "Rewrite.rebuild: rpl" rpl |
575 val () = Parser.ppTrace ppPl "Rewrite.rebuild: spl" spl |
591 val () = Print.trace ppPl "Rewrite.rebuild: spl" spl |
576 *) |
592 *) |
577 val Rewrite {order,known,redexes,subterms,waiting} = rw |
593 val Rewrite {order,known,redexes,subterms,waiting} = rw |
578 val redexes = cleanRedexes known redexes rpl |
594 val redexes = cleanRedexes known redexes rpl |
579 val subterms = cleanSubterms known subterms spl |
595 val subterms = cleanSubterms known subterms spl |
580 in |
596 in |
581 Rewrite |
597 Rewrite |
582 {order = order, known = known, redexes = redexes, |
598 {order = order, |
583 subterms = subterms, waiting = waiting} |
599 known = known, |
|
600 redexes = redexes, |
|
601 subterms = subterms, |
|
602 waiting = waiting} |
584 end; |
603 end; |
585 end; |
604 end; |
586 |
605 |
587 fun reduceAcc (rpl, spl, todo, rw as Rewrite {known,waiting,...}, changed) = |
606 fun reduceAcc (rpl, spl, todo, rw as Rewrite {known,waiting,...}, changed) = |
588 case pick known todo of |
607 case pick known todo of |
606 |
625 |
607 fun reduce' rw = |
626 fun reduce' rw = |
608 if isReduced rw then (rw,[]) |
627 if isReduced rw then (rw,[]) |
609 else reduceAcc (IntSet.empty,IntSet.empty,IntSet.empty,rw,IntSet.empty); |
628 else reduceAcc (IntSet.empty,IntSet.empty,IntSet.empty,rw,IntSet.empty); |
610 |
629 |
611 (*DEBUG |
630 (*MetisDebug |
612 val reduce' = fn rw => |
631 val reduce' = fn rw => |
613 let |
632 let |
614 (*TRACE4 |
633 (*MetisTrace4 |
615 val () = Parser.ppTrace pp "Rewrite.reduce': rw" rw |
634 val () = Print.trace pp "Rewrite.reduce': rw" rw |
616 *) |
635 *) |
617 val Rewrite {known,order,...} = rw |
636 val Rewrite {known,order,...} = rw |
618 val result as (Rewrite {known = known', ...}, _) = reduce' rw |
637 val result as (Rewrite {known = known', ...}, _) = reduce' rw |
619 (*TRACE4 |
638 (*MetisTrace4 |
620 val ppResult = Parser.ppPair pp (Parser.ppList Parser.ppInt) |
639 val ppResult = Print.ppPair pp (Print.ppList Print.ppInt) |
621 val () = Parser.ppTrace ppResult "Rewrite.reduce': result" result |
640 val () = Print.trace ppResult "Rewrite.reduce': result" result |
622 *) |
641 *) |
623 val ths = map (fn (id,((_,th),_)) => (id,th)) (IntMap.toList known') |
642 val ths = map (fn (id,((_,th),_)) => (id,th)) (IntMap.toList known') |
624 val _ = |
643 val _ = |
625 not (List.exists (uncurry (thmReducible order known')) ths) orelse |
644 not (List.exists (uncurry (thmReducible order known')) ths) orelse |
626 raise Bug "Rewrite.reduce': not fully reduced" |
645 raise Bug "Rewrite.reduce': not fully reduced" |