Representing cyclic data structures efficiently in Haskell
Sarah Thompson
sarah@telergy.com
Mon, 07 Jul 2003 16:37:46 +0100
>>From reading your message, it seems you want a graph library of sorts.
>
The important bit is 'of sorts', unfortunately! Most graph libraries
I've seen to date (although I must admit that they have been written in
C and C++, including one I perpetrated personally) don't really work
that well for circuits because, for anything other than trivially simple
components, the connections between nodes need to be labelled.
A component representing something simple like (say) an 'and' gate would
be easy enough to represent as a node of an ordinary directed graph. In
such a case, an incoming arrow would always be an input of the gate, and
an outgoing arrow would always be the output. I need to be able to
represent more complex components, up to and including the complexity of
things like CPUs, where you might have lots and lots of inputs and
outputs with substantially different meanings. In the case of a CPU, it
would never be acceptable to (for example) swap a chip select output for
an address or data line.
This makes me think that an off-the-shelf graph library won't quite be
what I'm after, so I will almost certainly need to write the code. What
I'm more interested in at the moment is a view on the best kinds of
approach that might be appropriate.
I'd considered something like embedding the type in the IO monad, with
links between components implemented as IORefs, but I'd really prefer
something cleaner (pure functional). If the code ends up horribly
complicated in order to get decent performance, I might as well fold and
use C++ instead.
I'm currently wondering about going for an adjacency list approach (as
used by most graph libraries), with the tuples in the adjacency list
extended to include input/output labels, resulting in a 4-ary tuple
rather than the usual 2-ary. But, I don't want to be stuck with
representing this as a list -- I really need log N lookups or
performance will stink horribly as circuits get big. Maybe a pair of
finite maps, allowing the edges to be traversed in either direction?
>If FGL seems like overkill to you, I have my own little mini graph
>library which basically looks like:
>
> - An ADT, Node: newtype Node = Node Int deriving ...
> - The 'Graph n e' data structure, containing:
> - a FiniteMap from n -> Node
> - an (growable?) array of type IOArray (Node,Node) e
>
>the array represents the edges in the top half (i do some index fiddling
>to get this efficient) and the finitemap represents the node labellings.
>It's a pretty stupid interface and works a lot better when the graphs
>are fixed size (that way you don't need to grow the array). But it
>works.
>
>
The finite map from n to Node seems like a good idea. Does representing the adjacency list as a flat array cause any problems?
Sarah
--
----------------------------------------------
/ __ + / Sarah Thompson **** /
/ (_ _ _ _ |_ / * /
/ __)(_|| (_|| ) / sarah@telergy.com * /
/ + / http://findatlantis.com/ /
----------------------------------------------
--
----------------------------------------------
/ __ + / Sarah Thompson **** /
/ (_ _ _ _ |_ / * /
/ __)(_|| (_|| ) / sarah@telergy.com * /
/ + / http://findatlantis.com/ /
----------------------------------------------