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.

Reply via email to