Impressum ElementSet.sml
Interaktion und PortierbarkeitSML
(* ========================================================================= *) (* FINITE SETS WITH A FIXED ELEMENT TYPE *) (* Copyright (c) 2004 Joe Leslie-Hurd, distributed under the BSD License *) (* ========================================================================= *)
functor ElementSet (
KM : KeyMap
) :> ElementSet
where type element = KM.key andtype'a map = 'a KM.map = struct
(* ------------------------------------------------------------------------- *) (* A type of set elements. *) (* ------------------------------------------------------------------------- *)
type element = KM.key;
val compareElement = KM.compareKey;
val equalElement = KM.equalKey;
(* ------------------------------------------------------------------------- *) (* A type of finite sets. *) (* ------------------------------------------------------------------------- *)
type'a map = 'a KM.map;
datatypeset = Setof unit map;
(* ------------------------------------------------------------------------- *) (* Converting to and from maps. *) (* ------------------------------------------------------------------------- *)
fun dest (Set m) = m;
fun mapPartial f = let fun mf (elt,()) = f elt in
fn Set m => KM.mapPartial mf m end;
funmap f = let fun mf (elt,()) = f elt in
fn Set m => KM.map mf m end;
fun lift f = let fun inc (elt,set) = union set (f elt) in
foldl inc empty end;
fun closedAdd f = let fun adds acc set = foldl check acc set
and check (elt,acc) = if member elt acc then acc else expand (add acc elt) elt
and expand acc elt = adds acc (f elt) in
adds end;
fun close f = closedAdd f empty;
(* ------------------------------------------------------------------------- *) (* Converting to and from lists. *) (* ------------------------------------------------------------------------- *)
fun transform f = let fun inc (x,l) = f x :: l in
foldr inc [] end;
datatype ordering =
Linear of element list
| Cycle of element list;
fun postOrdered children = let fun check acc elts = case elts of
[] => true
| elt :: elts => not (member elt acc) andalso let val acc = closedAdd children acc (singleton elt) in
check acc elts end in
check empty end;
fun preOrdered children elts = postOrdered children (List.rev elts);
local fun takeStackset elt = let fun notElement (e,_,_) = not (equalElement e elt) in
Useful.takeWhile notElement end;
fun consElement ((e,_,_),el) = e :: el;
fun depthFirstSearch children = let fun traverse (dealt,dealtset) (stack,stackset) work = case work of
[] =>
(case stack of
[] => Linear dealt
| (elt,work,stackset) :: stack => let val dealt = elt :: dealt
val dealtset = add dealtset elt in
traverse (dealt,dealtset) (stack,stackset) work end)
| elt :: work => if member elt dealtset then
traverse (dealt,dealtset) (stack,stackset) work elseif member elt stackset then let val cycle = takeStackset elt stack
val cycle = elt :: List.foldl consElement [elt] cycle in
Cycle cycle end else let val stack = (elt,work,stackset) :: stack
val stackset = add stackset elt
val work = toList (children elt) in
traverse (dealt,dealtset) (stack,stackset) work end
val dealt = [] and dealtset = empty and stack = [] and stackset = empty in
traverse (dealt,dealtset) (stack,stackset) end; in fun preOrder children roots = let val result = depthFirstSearch children (toList roots)
(*BasicDebug val () = case result of Cycle _ => () | Linear l => let val () = if subset roots (fromList l) then () else raise Useful.Bug "ElementSet.preOrder: missing roots"
val () = if preOrdered children l then () else raise Useful.Bug "ElementSet.preOrder: bad ordering" in () end
*) in
result end;
fun postOrder children roots = case depthFirstSearch children (toList roots) of
Linear l => let val l = List.rev l
(*BasicDebug val () = if subset roots (fromList l) then () else raise Useful.Bug "ElementSet.postOrder: missing roots"
val () = if postOrdered children l then () else raise Useful.Bug "ElementSet.postOrder: bad ordering"
*) in
Linear l end
| cycle => cycle; end;
fun postOrderedSCC children = let fun check acc eltsl = case eltsl of
[] => true
| elts :: eltsl => not (null elts) andalso
disjoint elts acc andalso let fun addElt elt = closedAdd children acc (singleton elt)
val (root,elts) = deletePick elts
fun checkElt elt = member root (addElt elt) in all checkElt elts andalso let val acc = addElt root in
subset elts acc andalso
check acc eltsl end end in
check empty end;
fun preOrderedSCC children eltsl = postOrderedSCC children (List.rev eltsl);
fun inStack elt (StackSCC (elts,_)) = member elt elts;
fun popStack root = let fun pop scc eltl = case eltl of
[] => raise Useful.Bug "ElementSet.popStack"
| (elt,elts) :: eltl => let val scc = add scc elt in if equalElement elt root then (scc, StackSCC (elts,eltl)) else pop scc eltl end in
fn sccs => fn StackSCC (_,eltl) => let val (scc,stack) = pop empty eltl in
(scc :: sccs, stack) end end;
fun getIndex indices e : int = case KM.peek indices e of
SOME i => i
| NONE => raise Useful.Bug "ElementSet.getIndex";
fun isRoot indices lows e = getIndex indices e = getIndex lows e;
fun reduceIndex indices (e,i) = let val j = getIndex indices e in if j <= i then indices else KM.insert indices (e,i) end;
fun tarjan children = let fun dfsVertex sccs callstack index indices lows stack elt = let val indices = KM.insert indices (elt,index) and lows = KM.insert lows (elt,index)
val index = index + 1
val stack = pushStack stack elt
val chil = toList (children elt) in
dfsSuccessors sccs callstack index indices lows stack elt chil end
and dfsSuccessors sccs callstack index indices lows stack elt chil = case chil of
[] => let val (sccs,stack) = if isRoot indices lows elt then popStack elt sccs stack else (sccs,stack) in case callstack of
[] => (sccs,index,indices,lows)
| (p,elts) :: callstack => let val lows = reduceIndex lows (p, getIndex lows elt) in
dfsSuccessors sccs callstack index indices lows stack p elts end end
| c :: chil => case KM.peek indices c of
NONE => let val callstack = (elt,chil) :: callstack in
dfsVertex sccs callstack index indices lows stack c end
| SOME cind => let val lows = if inStack c stack then reduceIndex lows (elt,cind) else lows in
dfsSuccessors sccs callstack index indices lows stack elt chil end
fun dfsRoots sccs index indices lows elts = case elts of
[] => sccs
| elt :: elts => if KM.inDomain elt indices then
dfsRoots sccs index indices lows elts else let val callstack = []
val (sccs,index,indices,lows) =
dfsVertex sccs callstack index indices lows emptyStack elt in
dfsRoots sccs index indices lows elts end
val sccs = [] and index = 0 and indices = KM.new () and lows = KM.new () in
dfsRoots sccs index indices lows end; in fun preOrderSCC children roots = let val result = tarjan children (toList roots)
(*BasicDebug val () = if subset roots (unionList result) then () else raise Useful.Bug "ElementSet.preOrderSCC: missing roots"
val () = if preOrderedSCC children result then () else raise Useful.Bug "ElementSet.preOrderSCC: bad ordering"
*) in
result end;
fun postOrderSCC children roots = let val result = List.rev (tarjan children (toList roots))
(*BasicDebug val () = if subset roots (unionList result) then () else raise Useful.Bug "ElementSet.postOrderSCC: missing roots"
val () = if postOrderedSCC children result then () else raise Useful.Bug "ElementSet.postOrderSCC: bad ordering"
*) in
result end; end;
fun readIterator iter = let val (elt,()) = KM.readIterator iter in
elt end;
fun advanceIterator iter = KM.advanceIterator iter;
end
structure IntSet =
ElementSet (IntMap);
structure IntPairSet =
ElementSet (IntPairMap);
structure StringSet =
ElementSet (StringMap);
¤ Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.0.14Bemerkung:
Wie Sie bei der Firma Beratungs- und Dienstleistungen beauftragen können
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung ist noch experimentell.