D graph library

w0rp devw0rp at gmail.com
Wed May 15 00:29:42 PDT 2013


On Wednesday, 8 May 2013 at 16:14:05 UTC, H. S. Teoh wrote:
> Does it make sense to have a common interface between, say, 
> directed and
> non-directed graphs? That is, are there algorithms that can 
> operate on
> both, or do most of the interesting algorithms only work on one 
> or the
> other? I'm just wondering if it's worth the trouble of doing
> compile-time (or runtime) checks if we could just have two 
> unrelated
> graph types.

I suggest building the graphs as structs with policy based 
design, possibly having separate policies for how the graphs are 
stored in memory, possibly not. So the basic graph structure 
would be like this.

// Struct so stack allocation becomes possible later.
struct GraphImplementation(GraphPolicy)
if (isGraphPolicy!GraphPolicy){
     GraphPolicy graphPolicy = GraphPolicy();
}

The graph policies could look like this.

struct DigraphPolicy(Node, Weight) {
     // This could be the first naive policy to get the ball 
rolling.
     // unit test to verify a few basic algorithms first, optimise 
later.
     Weight[Node][Node] edgeMap;

     ...
}

The policies can then offer methods for accessing and mutating 
the graphs. So that would be stuff like bool addNode(Node), bool 
removeNode(Node), bool addEdge(Node, Node), NodeRange!Node 
neighbors(Node), etc. All of the internals of GraphImplementation 
could then access the very basic things through these methods, 
and then expose a few to the users by wrapping/aliasing the 
functions. Perhaps encapsluation + alias this is the way to go 
here.

{
    ... alias graphPolicy this; // Now we expose addNode(Node), 
etc.
}

Then for your final trick, you could throw in a few templates to 
bring it all together.

template isGraphPolicy(T) { ... }
template isSomeGraph(T) { ... }
template NodeType(SomeGraph) { ... }
template EdgeType(SomeGraph) { ... }

Most importantly...

template Digraph(Node, Weight = int) {
     auto Digraph = GraphImplementation!(DigraphPolicy!(Node, 
Weight));
}

Then we are back to basics:

auto graph = Digraph!char;
graph.addEdge('a', 'b'); // bla, bla, bla

I think doing things in this way makes it easy to get the ball 
rolling, but also easy to add in optimisations later. ("Aha, this 
is an undirected graph, I can assume this... static if") I think 
the most important thing is to get the graph basics right, then 
to worry about how storage works, etc. later.


More information about the Digitalmars-d mailing list