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