added subtract;
authorwenzelm
Wed, 13 Jul 2005 16:07:29 +0200
changeset 16808 644fc45c7292
parent 16807 730cace0ae48
child 16809 8ca51a846576
added subtract; improved interface; tuned;
src/Pure/net.ML
--- a/src/Pure/net.ML	Wed Jul 13 16:07:28 2005 +0200
+++ b/src/Pure/net.ML	Wed Jul 13 16:07:29 2005 +0200
@@ -15,24 +15,26 @@
 *)
 
 signature NET =
-  sig
+sig
   type key
+  val key_of_term: term -> key list
   type 'a net
-  exception DELETE and INSERT
-  val delete: (key list * 'a) * 'b net * ('a * 'b -> bool) -> 'b net
-  val delete_term: (term * 'a) * 'b net * ('a * 'b -> bool) -> 'b net
   val empty: 'a net
-  val insert: (key list * 'a) * 'a net * ('a*'a -> bool) -> 'a net
-  val insert_term:   (term * 'a) * 'a net * ('a*'a -> bool) -> 'a net
-  val lookup: 'a net * key list -> 'a list
+  exception INSERT
+  val insert: ('a * 'a -> bool) -> key list * 'a -> 'a net -> 'a net
+  val insert_term: ('a * 'a -> bool) -> term * 'a -> 'a net -> 'a net
+  exception DELETE
+  val delete: ('b * 'a -> bool) -> key list * 'b -> 'a net -> 'a net
+  val delete_term: ('b * 'a -> bool) -> term * 'b -> 'a net -> 'a net
+  val lookup: 'a net -> key list -> 'a list
   val match_term: 'a net -> term -> 'a list
-  val key_of_term: term -> key list
   val unify_term: 'a net -> term -> 'a list
-  val dest: 'a net -> (key list * 'a) list
-  val merge: 'a net * 'a net * ('a*'a -> bool) -> 'a net
-  end;
+  val entries: 'a net -> 'a list
+  val subtract: ('b * 'a -> bool) -> 'a net -> 'b net -> 'b list
+  val merge: ('a * 'a -> bool) -> 'a net * 'a net -> 'a net
+end;
 
-structure Net : NET =
+structure Net: NET =
 struct
 
 datatype key = CombK | VarK | AtomK of string;
@@ -85,7 +87,7 @@
   eq is the equality test for items.
   The empty list of keys generates a Leaf node, others a Net node.
 *)
-fun insert ((keys,x), net, eq) =
+fun insert eq (keys,x) net =
   let fun ins1 ([], Leaf xs) =
             if member eq xs x then  raise INSERT  else Leaf(x::xs)
         | ins1 (keys, Leaf[]) = ins1 (keys, emptynet)   (*expand empty...*)
@@ -100,7 +102,9 @@
             in  Net{comb=comb, var=var, atoms=atoms'}  end
   in  ins1 (keys,net)  end;
 
-fun insert_term ((t,x), net, eq) = insert((key_of_term t, x), net, eq);
+fun insert_safe eq entry net = insert eq entry net handle INSERT => net;
+fun insert_term eq (t, x) = insert eq (key_of_term t, x);
+
 
 (*** Deletion from a discrimination net ***)
 
@@ -114,7 +118,7 @@
 (*Deletes item x from the list at the node addressed by the keys.
   Raises DELETE if absent.  Collapses the net if possible.
   eq is the equality test for items. *)
-fun delete ((keys, x), net, eq) =
+fun delete eq (keys, x) net =
   let fun del1 ([], Leaf xs) =
             if member eq xs x then Leaf (remove eq x xs)
             else raise DELETE
@@ -134,7 +138,7 @@
             in  newnet{comb=comb, var=var, atoms=atoms'}  end
   in  del1 (keys,net)  end;
 
-fun delete_term ((t,x), net, eq) = delete((key_of_term t, x), net, eq);
+fun delete_term eq (t, x) = delete eq (key_of_term t, x);
 
 
 (*** Retrieval functions for discrimination nets ***)
@@ -147,12 +151,12 @@
   | SOME net => net);
 
 (*Return the list of items at the given node, [] if no such node*)
-fun lookup (Leaf(xs), []) = xs
-  | lookup (Leaf _, _::_) = []  (*non-empty keys and empty net*)
-  | lookup (Net{comb,var,atoms}, CombK :: keys) = lookup(comb,keys)
-  | lookup (Net{comb,var,atoms}, VarK :: keys) = lookup(var,keys)
-  | lookup (Net{comb,var,atoms}, AtomK a :: keys) =
-      lookup (the_atom atoms a, keys) handle ABSENT => [];
+fun lookup (Leaf xs) [] = xs
+  | lookup (Leaf _) (_ :: _) = []  (*non-empty keys and empty net*)
+  | lookup (Net {comb, var, atoms}) (CombK :: keys) = lookup comb keys
+  | lookup (Net {comb, var, atoms}) (VarK :: keys) = lookup var keys
+  | lookup (Net {comb, var, atoms}) (AtomK a :: keys) =
+      lookup (the_atom atoms a) keys handle ABSENT => [];
 
 
 (*Skipping a term in a net.  Recursively skip 2 levels if a combination*)
@@ -160,7 +164,8 @@
   | net_skip (Net{comb,var,atoms}, nets) =
       foldr net_skip (Symtab.fold (cons o #2) atoms (var::nets)) (net_skip (comb,[]));
 
-(** Matching and Unification**)
+
+(** Matching and Unification **)
 
 (*conses the linked net, if present, to nets*)
 fun look1 (atoms, a) nets =
@@ -206,7 +211,27 @@
     extract_leaves (matching true t (net,[]));
 
 
-(** dest **)
+(** operations on nets **)
+
+(*subtraction: collect entries of second net that are NOT present in first net*)
+fun subtract eq net1 net2 =
+  let
+    fun subtr (Net _) (Leaf ys) = append ys
+      | subtr (Leaf xs) (Leaf ys) =
+          fold_rev (fn y => if member eq xs y then I else cons y) ys
+      | subtr (Leaf _) (net as Net _) = subtr emptynet net
+      | subtr (Net {comb = comb1, var = var1, atoms = atoms1})
+            (Net {comb = comb2, var = var2, atoms = atoms2}) =
+          Symtab.fold (fn (a, net) =>
+            subtr (if_none (Symtab.lookup (atoms1, a)) emptynet) net) atoms2 o
+          subtr var1 var2 o
+          subtr comb1 comb2;
+  in subtr net1 net2 [] end;
+
+fun entries net = subtract (K false) empty net;
+
+
+(* merge *)
 
 fun cons_fst x (xs, y) = (x :: xs, y);
 
@@ -214,14 +239,8 @@
   | dest (Net {comb, var, atoms}) =
       map (cons_fst CombK) (dest comb) @
       map (cons_fst VarK) (dest var) @
-      List.concat (map (fn (a, net) => map (cons_fst (AtomK a)) (dest net))
-        (Symtab.dest atoms));
-
+      List.concat (map (fn (a, net) => map (cons_fst (AtomK a)) (dest net)) (Symtab.dest atoms));
 
-(** merge **)
-
-fun add eq keys_x net = insert (keys_x, net, eq) handle INSERT => net;
-fun merge (net1, net2, eq) = fold (add eq) (dest net2) net1;
-
+fun merge eq (net1, net2) = fold (insert_safe eq) (dest net2) net1;
 
 end;