src/Tools/Metis/src/Rewrite.sml
changeset 39353 7f11d833d65b
parent 23510 4521fead5609
parent 39349 2d0a4361c3ef
child 39443 e330437cd22a
equal deleted inserted replaced
39313:41ce0b56d858 39353:7f11d833d65b
     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 
   189         val waiting = IntSet.add waiting id
   198         val waiting = IntSet.add waiting id
   190         val rw =
   199         val rw =
   191             Rewrite
   200             Rewrite
   192               {order = order, known = known, redexes = redexes,
   201               {order = order, known = known, redexes = redexes,
   193                subterms = subterms, waiting = waiting}
   202                subterms = subterms, waiting = waiting}
   194 (*TRACE5
   203 (*MetisTrace5
   195         val () = Parser.ppTrace pp "Rewrite.add: result" rw
   204         val () = Print.trace pp "Rewrite.add: result" rw
   196 *)
   205 *)
   197       in
   206       in
   198         rw
   207         rw
   199       end;
   208       end;
   200 
   209 
   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
   541 
   557 
   542           fun addReds (id,reds) =
   558           fun addReds (id,reds) =
   543               case IntMap.peek known id of
   559               case IntMap.peek known id of
   544                 NONE => reds
   560                 NONE => reds
   545               | SOME eqn_ort => addRedexes id eqn_ort reds
   561               | SOME eqn_ort => addRedexes id eqn_ort reds
   546                                
   562 
   547           val redexes = TermNet.filter filt redexes
   563           val redexes = TermNet.filter filt redexes
   548           val redexes = IntSet.foldl addReds redexes rpl
   564           val redexes = IntSet.foldl addReds redexes rpl
   549         in
   565         in
   550           redexes
   566           redexes
   551         end;
   567         end;
   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"