3

I am facing the problem of visualizing this string:

"=IF(A2=1;0;IF(D2=D3;IF(C2=1;TRUE;FALSE);4))";

As you can see the general syntax is similar to an excel formula, so that I have IF(TEST; TRUE; FALSE)

My problem is that I want to visulize this string in a binary search tree format with the libary JUNG2. Below you can see an example of how the tree should look like:

enter image description here

Here is some code which visualizes the vertex at the moment.

public class SimpleGraphView {
    Graph<Integer, String> g;
    Graph<String, String> n;

    /** Creates a new instance of SimpleGraphView */

    String text = "=IF(A2=1;0;IF(D2=D3;IF(C2=1;TRUE;FALSE);4))";


    public SimpleGraphView() {

        n = new SparseMultigraph<String, String>();

        String str = text;
        String delim = ";";
        StringTokenizer tok = new StringTokenizer(str, delim, true);

        text = text.replace("(", " ");
        String s = text.replace(")", " ");
        String[] r = s.split(";");

        for (int i = 0; i < r.length; i++) {

            //Vertex
            if(r.equals("=IF(")) {
                n.addVertex(r[i].toString());
            }

            if(i % 2==0){
                n.addVertex(r[i].toString());
            } else {
                n.addVertex(r[i].toString());
            }

        }

    }

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {
        SimpleGraphView sgv = new SimpleGraphView(); // Creates the graph...
        // Layout<V, E>, VisualizationViewer<V,E>
        Layout<Integer, String> layout = new CircleLayout(sgv.n);
        layout.setSize(new Dimension(300,300));

        VisualizationViewer<Integer,String> vv = new VisualizationViewer<Integer,String>(layout);
        vv.setPreferredSize(new Dimension(350,350));
        // Show vertex and edge labels
        vv.getRenderContext().setVertexLabelTransformer(new ToStringLabeller());
        vv.getRenderContext().setEdgeLabelTransformer(new ToStringLabeller());

        // Create our "custom" mouse here. We start with a PluggableGraphMouse
        // Then add the plugins you desire.
        PluggableGraphMouse gm = new PluggableGraphMouse(); 
        gm.add(new TranslatingGraphMousePlugin(MouseEvent.BUTTON1_MASK));
        gm.add(new ScalingGraphMousePlugin(new CrossoverScalingControl(), 0, 1.1f, 0.9f));

        vv.setGraphMouse(gm); 
        JFrame frame = new JFrame("Interactive Graph View 3");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.getContentPane().add(vv);
        frame.pack();
        frame.setVisible(true);       


    }
}

I can render all vertexes out of the string in the array r. My problem is that I do not know how to connect all these vertexes with the proper edges. Any recommendations, how to connect all vertexes with the right edges?

I really appreciate your answer!

Carol.Kar
  • 4,581
  • 36
  • 131
  • 264
  • From the diagram, all of the edges are directed. There are no undirected edges. Given that, I'm not sure I understand the problem. `SimpleMultiGraph` contains an `addEdge()` function. What part of it are you having trouble with? – mttdbrd Jun 16 '14 at 13:24
  • Thx for your answer! My problem is to connect the right edges with the right vertex(es), so that I can get the graph as shown in the picture. – Carol.Kar Jun 16 '14 at 13:27
  • 1
    Sounds like you're having difficulty in the logic of splitting the string. You're going to have to use regular expressions somewhere I'm betting. Having siad that, I think I'd start by splitting on `IF` rather than `;` because then you know how many conditions you have, and it keeps the condition and at least one of its outcomes together in the substring. – Dan Temple Jun 16 '14 at 13:29
  • Thx for your answer! I think I slightly understand how you would approach the problem, but it`s hard for me to implement it. Would appreciate it, if you could help me on that issue! – Carol.Kar Jun 16 '14 at 13:34

2 Answers2

2

The easiest way to do this is splitting the text in a different way I think. Note that i replaced the methods of the graph with addEdge and addVertex:

String[] operands = text.substring(1, text.length()).split("[;()]+");
int numIfs = operands.length / 3; // actually (operands.length - 1) / 3 but int division makes it the same 
String[] nodes = new String[numIfs]; // stores the nodes (test strings)
int[] operandNos = new int[numIfs]; // stores the number of operands the if currently has
int nodesIndex = -1; // the index of the if node currently parsed
for (String s : operands) {
    if (s.equals("IF")) {
        // new if found -> increase position in the "stack" (nodes)
        operandNos[++nodesIndex] = 0;
    } else {
        addVertex(s);
        switch (operandNos[nodesIndex]++) {
            case 0:
                // first operand = node name
                nodes[nodesIndex] = s;
                break;
            case 1:
                // second operand found -> add edge
                addEdge(s, nodes[nodesIndex]);
                break;
            case 2:
                // last operand found -> add edge and go back
                do {
                    addEdge(s, nodes[nodesIndex]);
                    s = nodes[nodesIndex--];
                } while (nodesIndex >= 0 && operandNos[nodesIndex]++ == 2);
                if (nodesIndex >= 0) {
                    // was not the last operand of the IF
                    addEdge(s, nodes[nodesIndex]);
                }
        }
    }
}

Instead of the addEdge and addVertex use the methods of the graph. I'd recommend using DirectedSparseGraph since your graph is directed and doesn't allow parallel edges. To add a vertex to the graph use graph.addVertex(vertexName) and to add an edge use graph.addEdge(edge, sourceVertexName, destinationVertexName).

The implementation of addEdge and addVertex would then look like this:

void addVertex(String s) {
    n.addVertex(s);
}

void addEdge(String source, String dest) {
    n.addEdge("", source, dest);
}

or better inline them.

fabian
  • 80,457
  • 12
  • 86
  • 114
  • Thx a lot for your answer! However, at the moment I am not able to run it cause eclipse says that `addVertex(s)` etc. is `The method addVertex(String) is undefined for the type SimpleGraphView`. I would appreciate your answer, how to get it running. – Carol.Kar Jun 18 '14 at 07:31
  • @Kare: I thought you could figure out that part on your own. Sometimes a look at the [API doc](http://jung.sourceforge.net/doc/api/edu/uci/ics/jung/graph/DirectedSparseGraph.html) or [some short example](http://www.vainolo.com/2011/02/14/learning-jung-java-universal-networkgraph-framework/) helps. But I edited my answer. – fabian Jun 18 '14 at 13:22
0

As you're looping through the String, you need to keep track of which node is the parent and which is the child. When you enter the "IF=" condition, that is a parent node. The others are children of it until until you encounter the next "IF=" condition (that node is also a child of the previous parent, but a parent to all subsequent nodes). So add the child and parent to a Pair and add that to the SimpleMultiGraph with EdgeType.DIRECTED. The docs are sort of unclear on how directed edges interact with the Pair but I assume that the first Vertex you add to the Pair is outgoing and the second is incoming. Just a guess since the docs are unclear.

mttdbrd
  • 1,791
  • 12
  • 17