Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Fluent Interface to Build a Directed Cyclic Graph?

I have created a set of classes to represent a directed cyclic graph for representing BPM processes, based on JUNG's DirectedSparseGraph class, which provides only basic graph manipulation methods to add and find vertices and edges.

The challenge I am facing is to create a builder that provides a fluent interface able to create a graph that includes complex branching, cycles, and multiple end nodes (see examples below).

Parallel Branches

Parallel Branches

Merging Branches

Merging Branches

Cycles

Cycle

Complex

Complex

My current implementation (see example below) is resorting to aliasing the vertex where a fork occurs (e.g., vertex "B" in Parallel Branches), and then I refer to the alias when adding a new branch to that vertex. My builder also includes something similar to allow for the merging of branches and cycles. Aliases were introduced because vertex names are not unique in BPM graphs. I want a more elegant fluent interface to quickly build graphs, free from those references.

Graph graph = GraphBuilder.newGraph()
                          .addVertex("A")
                          .edgeName("")
                          .addVertex("B", "b-fork")
                          .edgeName("")
                          .addVertex("C")
                          .edgeName("")
                          .addVertex("E")
                          .addBranch("b-fork")
                          .edgeName("")    
                          .addVertex("D")
                          .edgeName("")
                          .addVertex("F")
                          .build();
like image 480
izilotti Avatar asked Mar 06 '15 15:03

izilotti


1 Answers

The problem is that the builder is a chain of methods, while you want to build a graph with cycles. You'll need to backtrack, and to do that it is necessary to refer to previous nodes either explicitely (using their label) or implictly, e.g:

    Graph graph = GraphBuilder.newGraph()
                      .addVertex("A")
                      .edgeName("")
                      .addVertex("B", "b-fork")
                      .edgeName("")
                      .addVertex("C")
                      .edgeName("")
                      .addVertex("E")

                      .goBack(2) // even worse than using label: breaks easily
                      .edgeName("")    
                      .addVertex("D")
                      .edgeName("")
                      .addVertex("F")
                      .build();

You could use a tree structure to build your graph:

    SubGraph.node("id", "label")
        .to("edgeName1", SubGraph.node("A").to("", SubGraph.node("C"))),
        .to("edgeName2", SubGraph.node("B"));

but this just delays the problem, as you will again need to refer to nodes explicitely when cycles come into play. Short of some sort of GUI or extensive ASCII-drawings there is no way to define a graph without aliases.

Personally I would recommend a DOT-style parser:

parse("a -> b -> c -> f -> e; f -> d -> b"); // "Cyclic graph"

which is both easier to read and to type.

EDIT: for the lulz: cyclic graph without aliasing:

    // do not ever do this:
    GraphBuilder.parseASCII(
            "     -->C--      \n" +         
            "    |      v     \n" +
            "A-->B      F-->E \n" + 
            "    |      ^     \n" +
            "     -->D--      \n");
like image 135
Adrian Leonhard Avatar answered Nov 06 '22 10:11

Adrian Leonhard