src/Tools/Metis/src/Clause.sml
changeset 39348 6f9c9899f99f
child 39349 2d0a4361c3ef
equal deleted inserted replaced
39347:50dec19e682b 39348:6f9c9899f99f
       
     1 (* ========================================================================= *)
       
     2 (* CLAUSE = ID + THEOREM                                                     *)
       
     3 (* Copyright (c) 2002-2004 Joe Hurd, distributed under the GNU GPL version 2 *)
       
     4 (* ========================================================================= *)
       
     5 
       
     6 structure Clause :> Clause =
       
     7 struct
       
     8 
       
     9 open Useful;
       
    10 
       
    11 (* ------------------------------------------------------------------------- *)
       
    12 (* Helper functions.                                                         *)
       
    13 (* ------------------------------------------------------------------------- *)
       
    14 
       
    15 val newId =
       
    16     let
       
    17       val r = ref 0
       
    18     in
       
    19       fn () => case r of ref n => let val () = r := n + 1 in n end
       
    20     end;
       
    21 
       
    22 (* ------------------------------------------------------------------------- *)
       
    23 (* A type of clause.                                                         *)
       
    24 (* ------------------------------------------------------------------------- *)
       
    25 
       
    26 datatype literalOrder =
       
    27     NoLiteralOrder
       
    28   | UnsignedLiteralOrder
       
    29   | PositiveLiteralOrder;
       
    30 
       
    31 type parameters =
       
    32      {ordering : KnuthBendixOrder.kbo,
       
    33       orderLiterals : literalOrder,
       
    34       orderTerms : bool};
       
    35 
       
    36 type clauseId = int;
       
    37 
       
    38 type clauseInfo = {parameters : parameters, id : clauseId, thm : Thm.thm};
       
    39 
       
    40 datatype clause = Clause of clauseInfo;
       
    41 
       
    42 (* ------------------------------------------------------------------------- *)
       
    43 (* Pretty printing.                                                          *)
       
    44 (* ------------------------------------------------------------------------- *)
       
    45 
       
    46 val showId = ref false;
       
    47 
       
    48 local
       
    49   val ppIdThm = Print.ppPair Print.ppInt Thm.pp;
       
    50 in
       
    51   fun pp (Clause {id,thm,...}) =
       
    52       if !showId then ppIdThm (id,thm) else Thm.pp thm;
       
    53 end;
       
    54 
       
    55 fun toString cl = Print.toString pp cl;
       
    56 
       
    57 (* ------------------------------------------------------------------------- *)
       
    58 (* Basic operations.                                                         *)
       
    59 (* ------------------------------------------------------------------------- *)
       
    60 
       
    61 val default : parameters =
       
    62     {ordering = KnuthBendixOrder.default,
       
    63      orderLiterals = PositiveLiteralOrder,
       
    64      orderTerms = true};
       
    65 
       
    66 fun mk info = Clause info
       
    67 
       
    68 fun dest (Clause info) = info;
       
    69 
       
    70 fun id (Clause {id = i, ...}) = i;
       
    71 
       
    72 fun thm (Clause {thm = th, ...}) = th;
       
    73 
       
    74 fun equalThms cl cl' = Thm.equal (thm cl) (thm cl');
       
    75 
       
    76 fun new parameters thm =
       
    77     Clause {parameters = parameters, id = newId (), thm = thm};
       
    78 
       
    79 fun literals cl = Thm.clause (thm cl);
       
    80 
       
    81 fun isTautology (Clause {thm,...}) = Thm.isTautology thm;
       
    82 
       
    83 fun isContradiction (Clause {thm,...}) = Thm.isContradiction thm;
       
    84 
       
    85 (* ------------------------------------------------------------------------- *)
       
    86 (* The term ordering is used to cut down inferences.                         *)
       
    87 (* ------------------------------------------------------------------------- *)
       
    88 
       
    89 fun strictlyLess ordering x_y =
       
    90     case KnuthBendixOrder.compare ordering x_y of
       
    91       SOME LESS => true
       
    92     | _ => false;
       
    93 
       
    94 fun isLargerTerm ({ordering,orderTerms,...} : parameters) l_r =
       
    95     not orderTerms orelse not (strictlyLess ordering l_r);
       
    96 
       
    97 local
       
    98   fun atomToTerms atm =
       
    99       case total Atom.destEq atm of
       
   100         NONE => [Term.Fn atm]
       
   101       | SOME (l,r) => [l,r];
       
   102 
       
   103   fun notStrictlyLess ordering (xs,ys) =
       
   104       let
       
   105         fun less x = List.exists (fn y => strictlyLess ordering (x,y)) ys
       
   106       in
       
   107         not (List.all less xs)
       
   108       end;
       
   109 in
       
   110   fun isLargerLiteral ({ordering,orderLiterals,...} : parameters) lits =
       
   111       case orderLiterals of
       
   112         NoLiteralOrder => K true
       
   113       | UnsignedLiteralOrder =>
       
   114         let
       
   115           fun addLit ((_,atm),acc) = atomToTerms atm @ acc
       
   116 
       
   117           val tms = LiteralSet.foldl addLit [] lits
       
   118         in
       
   119           fn (_,atm') => notStrictlyLess ordering (atomToTerms atm', tms)
       
   120         end
       
   121       | PositiveLiteralOrder =>
       
   122         case LiteralSet.findl (K true) lits of
       
   123           NONE => K true
       
   124         | SOME (pol,_) =>
       
   125           let
       
   126             fun addLit ((p,atm),acc) =
       
   127                 if p = pol then atomToTerms atm @ acc else acc
       
   128 
       
   129             val tms = LiteralSet.foldl addLit [] lits
       
   130           in
       
   131             fn (pol',atm') =>
       
   132                if pol <> pol' then pol
       
   133                else notStrictlyLess ordering (atomToTerms atm', tms)
       
   134           end;
       
   135 end;
       
   136 
       
   137 fun largestLiterals (Clause {parameters,thm,...}) =
       
   138     let
       
   139       val litSet = Thm.clause thm
       
   140       val isLarger = isLargerLiteral parameters litSet
       
   141       fun addLit (lit,s) = if isLarger lit then LiteralSet.add s lit else s
       
   142     in
       
   143       LiteralSet.foldr addLit LiteralSet.empty litSet
       
   144     end;
       
   145 
       
   146 (*MetisTrace6
       
   147 val largestLiterals = fn cl =>
       
   148     let
       
   149       val ppResult = LiteralSet.pp
       
   150       val () = Print.trace pp "Clause.largestLiterals: cl" cl
       
   151       val result = largestLiterals cl
       
   152       val () = Print.trace ppResult "Clause.largestLiterals: result" result
       
   153     in
       
   154       result
       
   155     end;
       
   156 *)
       
   157 
       
   158 fun largestEquations (cl as Clause {parameters,...}) =
       
   159     let
       
   160       fun addEq lit ort (l_r as (l,_)) acc =
       
   161           if isLargerTerm parameters l_r then (lit,ort,l) :: acc else acc
       
   162 
       
   163       fun addLit (lit,acc) =
       
   164           case total Literal.destEq lit of
       
   165             NONE => acc
       
   166           | SOME (l,r) =>
       
   167             let
       
   168               val acc = addEq lit Rewrite.RightToLeft (r,l) acc
       
   169               val acc = addEq lit Rewrite.LeftToRight (l,r) acc
       
   170             in
       
   171               acc
       
   172             end
       
   173     in
       
   174       LiteralSet.foldr addLit [] (largestLiterals cl)
       
   175     end;
       
   176 
       
   177 local
       
   178   fun addLit (lit,acc) =
       
   179       let
       
   180         fun addTm ((path,tm),acc) = (lit,path,tm) :: acc
       
   181       in
       
   182         foldl addTm acc (Literal.nonVarTypedSubterms lit)
       
   183       end;
       
   184 in
       
   185   fun largestSubterms cl = LiteralSet.foldl addLit [] (largestLiterals cl);
       
   186 
       
   187   fun allSubterms cl = LiteralSet.foldl addLit [] (literals cl);
       
   188 end;
       
   189 
       
   190 (* ------------------------------------------------------------------------- *)
       
   191 (* Subsumption.                                                              *)
       
   192 (* ------------------------------------------------------------------------- *)
       
   193 
       
   194 fun subsumes (subs : clause Subsume.subsume) cl =
       
   195     Subsume.isStrictlySubsumed subs (literals cl);
       
   196 
       
   197 (* ------------------------------------------------------------------------- *)
       
   198 (* Simplifying rules: these preserve the clause id.                          *)
       
   199 (* ------------------------------------------------------------------------- *)
       
   200 
       
   201 fun freshVars (Clause {parameters,id,thm}) =
       
   202     Clause {parameters = parameters, id = id, thm = Rule.freshVars thm};
       
   203 
       
   204 fun simplify (Clause {parameters,id,thm}) =
       
   205     case Rule.simplify thm of
       
   206       NONE => NONE
       
   207     | SOME thm => SOME (Clause {parameters = parameters, id = id, thm = thm});
       
   208 
       
   209 fun reduce units (Clause {parameters,id,thm}) =
       
   210     Clause {parameters = parameters, id = id, thm = Units.reduce units thm};
       
   211 
       
   212 fun rewrite rewr (cl as Clause {parameters,id,thm}) =
       
   213     let
       
   214       fun simp th =
       
   215           let
       
   216             val {ordering,...} = parameters
       
   217             val cmp = KnuthBendixOrder.compare ordering
       
   218           in
       
   219             Rewrite.rewriteIdRule rewr cmp id th
       
   220           end
       
   221 
       
   222 (*MetisTrace4
       
   223       val () = Print.trace Rewrite.pp "Clause.rewrite: rewr" rewr
       
   224       val () = Print.trace Print.ppInt "Clause.rewrite: id" id
       
   225       val () = Print.trace pp "Clause.rewrite: cl" cl
       
   226 *)
       
   227 
       
   228       val thm =
       
   229           case Rewrite.peek rewr id of
       
   230             NONE => simp thm
       
   231           | SOME ((_,thm),_) => if Rewrite.isReduced rewr then thm else simp thm
       
   232 
       
   233       val result = Clause {parameters = parameters, id = id, thm = thm}
       
   234 
       
   235 (*MetisTrace4
       
   236       val () = Print.trace pp "Clause.rewrite: result" result
       
   237 *)
       
   238     in
       
   239       result
       
   240     end
       
   241 (*MetisDebug
       
   242     handle Error err => raise Error ("Clause.rewrite:\n" ^ err);
       
   243 *)
       
   244 
       
   245 (* ------------------------------------------------------------------------- *)
       
   246 (* Inference rules: these generate new clause ids.                           *)
       
   247 (* ------------------------------------------------------------------------- *)
       
   248 
       
   249 fun factor (cl as Clause {parameters,thm,...}) =
       
   250     let
       
   251       val lits = largestLiterals cl
       
   252 
       
   253       fun apply sub = new parameters (Thm.subst sub thm)
       
   254     in
       
   255       map apply (Rule.factor' lits)
       
   256     end;
       
   257 
       
   258 (*MetisTrace5
       
   259 val factor = fn cl =>
       
   260     let
       
   261       val () = Print.trace pp "Clause.factor: cl" cl
       
   262       val result = factor cl
       
   263       val () = Print.trace (Print.ppList pp) "Clause.factor: result" result
       
   264     in
       
   265       result
       
   266     end;
       
   267 *)
       
   268 
       
   269 fun resolve (cl1,lit1) (cl2,lit2) =
       
   270     let
       
   271 (*MetisTrace5
       
   272       val () = Print.trace pp "Clause.resolve: cl1" cl1
       
   273       val () = Print.trace Literal.pp "Clause.resolve: lit1" lit1
       
   274       val () = Print.trace pp "Clause.resolve: cl2" cl2
       
   275       val () = Print.trace Literal.pp "Clause.resolve: lit2" lit2
       
   276 *)
       
   277       val Clause {parameters, thm = th1, ...} = cl1
       
   278       and Clause {thm = th2, ...} = cl2
       
   279       val sub = Literal.unify Subst.empty lit1 (Literal.negate lit2)
       
   280 (*MetisTrace5
       
   281       val () = Print.trace Subst.pp "Clause.resolve: sub" sub
       
   282 *)
       
   283       val lit1 = Literal.subst sub lit1
       
   284       val lit2 = Literal.negate lit1
       
   285       val th1 = Thm.subst sub th1
       
   286       and th2 = Thm.subst sub th2
       
   287       val _ = isLargerLiteral parameters (Thm.clause th1) lit1 orelse
       
   288 (*MetisTrace5
       
   289               (trace "Clause.resolve: th1 violates ordering\n"; false) orelse
       
   290 *)
       
   291               raise Error "resolve: clause1: ordering constraints"
       
   292       val _ = isLargerLiteral parameters (Thm.clause th2) lit2 orelse
       
   293 (*MetisTrace5
       
   294               (trace "Clause.resolve: th2 violates ordering\n"; false) orelse
       
   295 *)
       
   296               raise Error "resolve: clause2: ordering constraints"
       
   297       val th = Thm.resolve lit1 th1 th2
       
   298 (*MetisTrace5
       
   299       val () = Print.trace Thm.pp "Clause.resolve: th" th
       
   300 *)
       
   301       val cl = Clause {parameters = parameters, id = newId (), thm = th}
       
   302 (*MetisTrace5
       
   303       val () = Print.trace pp "Clause.resolve: cl" cl
       
   304 *)
       
   305     in
       
   306       cl
       
   307     end;
       
   308 
       
   309 fun paramodulate (cl1,lit1,ort1,tm1) (cl2,lit2,path2,tm2) =
       
   310     let
       
   311 (*MetisTrace5
       
   312       val () = Print.trace pp "Clause.paramodulate: cl1" cl1
       
   313       val () = Print.trace Literal.pp "Clause.paramodulate: lit1" lit1
       
   314       val () = Print.trace Rewrite.ppOrient "Clause.paramodulate: ort1" ort1
       
   315       val () = Print.trace Term.pp "Clause.paramodulate: tm1" tm1
       
   316       val () = Print.trace pp "Clause.paramodulate: cl2" cl2
       
   317       val () = Print.trace Literal.pp "Clause.paramodulate: lit2" lit2
       
   318       val () = Print.trace Term.ppPath "Clause.paramodulate: path2" path2
       
   319       val () = Print.trace Term.pp "Clause.paramodulate: tm2" tm2
       
   320 *)
       
   321       val Clause {parameters, thm = th1, ...} = cl1
       
   322       and Clause {thm = th2, ...} = cl2
       
   323       val sub = Subst.unify Subst.empty tm1 tm2
       
   324       val lit1 = Literal.subst sub lit1
       
   325       and lit2 = Literal.subst sub lit2
       
   326       and th1 = Thm.subst sub th1
       
   327       and th2 = Thm.subst sub th2
       
   328 
       
   329       val _ = isLargerLiteral parameters (Thm.clause th1) lit1 orelse
       
   330               raise Error "Clause.paramodulate: with clause: ordering"
       
   331       val _ = isLargerLiteral parameters (Thm.clause th2) lit2 orelse
       
   332               raise Error "Clause.paramodulate: into clause: ordering"
       
   333 
       
   334       val eqn = (Literal.destEq lit1, th1)
       
   335       val eqn as (l_r,_) =
       
   336           case ort1 of
       
   337             Rewrite.LeftToRight => eqn
       
   338           | Rewrite.RightToLeft => Rule.symEqn eqn
       
   339 (*MetisTrace6
       
   340       val () = Print.trace Rule.ppEquation "Clause.paramodulate: eqn" eqn
       
   341 *)
       
   342       val _ = isLargerTerm parameters l_r orelse
       
   343               raise Error "Clause.paramodulate: equation: ordering constraints"
       
   344       val th = Rule.rewrRule eqn lit2 path2 th2
       
   345 (*MetisTrace5
       
   346       val () = Print.trace Thm.pp "Clause.paramodulate: th" th
       
   347 *)
       
   348     in
       
   349       Clause {parameters = parameters, id = newId (), thm = th}
       
   350     end
       
   351 (*MetisTrace5
       
   352     handle Error err =>
       
   353       let
       
   354         val () = trace ("Clause.paramodulate: failed: " ^ err ^ "\n")
       
   355       in
       
   356         raise Error err
       
   357       end;
       
   358 *)
       
   359 
       
   360 end