Menu

Indexing bug in GraphMLFileHandler

Anonymous
2004-03-11
2004-03-15
  • Anonymous

    Anonymous - 2004-03-11

    Hi,
    I have created a graph using GraphMLFile. When I load the Graph, and try to associate a decorator, the indexing of the vertices is random. I mean, the first node with the id="1" and the label="a" is not the first vertex I got when I iterate through the graph.
    Please run the following method, and explain me why the indexation is not respected !
    Remark: the code is extracted from your Junit test case.
    Ciao,
    Vincent

    public static void test() throws Exception {
        StringBuffer buffer = new StringBuffer();
        buffer.append("<?xml version=\&quot;1.0\&quot; encoding=\&quot;iso-8859-1\&quot; ?>\n");
        buffer.append("<graph edgedefault=\&quot;undirected\&quot;>\n");
        buffer.append("<node id=\&quot;1\&quot; label=\&quot;a\&quot;/>\n");
        buffer.append("<node id=\&quot;2\&quot; label=\&quot;b\&quot;/>\n");
        buffer.append("<node id=\&quot;3\&quot; label=\&quot;c\&quot;/>\n");
        buffer.append("<node id=\&quot;4\&quot; label=\&quot;d\&quot;/>\n");
        buffer.append("<node id=\&quot;5\&quot; label=\&quot;e\&quot;/>\n");
        buffer.append("<node id=\&quot;6\&quot; label=\&quot;f\&quot;/>\n");
        buffer.append("<node id=\&quot;7\&quot; label=\&quot;g\&quot;/>\n");
        buffer.append("<edge source=\&quot;1\&quot; target=\&quot;2\&quot;/>\n");
        buffer.append("<edge source=\&quot;1\&quot; target=\&quot;5\&quot;/>\n");
        buffer.append("<edge source=\&quot;2\&quot; target=\&quot;3\&quot;/>\n");
        buffer.append("<edge source=\&quot;2\&quot; target=\&quot;4\&quot;/>\n");
        buffer.append("<edge source=\&quot;2\&quot; target=\&quot;5\&quot;/>\n");
        buffer.append("<edge source=\&quot;5\&quot; target=\&quot;6\&quot;/>\n");
        buffer.append("<edge source=\&quot;5\&quot; target=\&quot;7\&quot;/>\n");
        buffer.append("</graph>\n");
       
        GraphMLFile graphmlFile = new GraphMLFile();
        graph = graphmlFile.load(new StringInputStream(buffer.toString()));
        sl = StringLabeller.getLabeller(graph);
        char c = 0;
        for (Iterator iter = graph.getVertices().iterator(); iter.hasNext();) {
          Vertex v = (Vertex) iter.next();
          sl.setLabel(v, "" + (char) (c + 'a' ));
          c++;
        }
        System.out.println(graph);
        Vertex va = sl.getVertex("a");
        System.out.println(va);
        System.out.println("a neighbors=" + va.numNeighbors());
        Vertex vb = sl.getVertex("b");
        System.out.println(vb);
        System.out.println("b neighbors=" + vb.numNeighbors());
        Vertex vc = sl.getVertex("c");
        System.out.println(vc);
        System.out.println("c neighbors=" + vc.numNeighbors());
        Vertex vd = sl.getVertex("d");
        System.out.println(vd);
        System.out.println("d neighbors=" + vd.numNeighbors());
        Vertex ve = sl.getVertex("e");
        System.out.println(ve);
        System.out.println("e neighbors=" + ve.numNeighbors());
        Vertex vf = sl.getVertex("f");
        System.out.println(vf);
        System.out.println("f neighbors=" + vf.numNeighbors());
        Vertex vg = sl.getVertex("g");
        System.out.println(vg);
        System.out.println("g neighbors=" + vg.numNeighbors());  }

    *********Console*************
    GraphMLFileHandler>> mGraph=G8116722[]
    GraphMLFileHandler>> vertex=V0
    GraphMLFileHandler>> vertex=V1
    GraphMLFileHandler>> vertex=V2
    GraphMLFileHandler>> vertex=V3
    GraphMLFileHandler>> vertex=V4
    GraphMLFileHandler>> vertex=V5
    GraphMLFileHandler>> vertex=V6
    GraphMLFileHandler>> Edge=E(V0,V1)
    GraphMLFileHandler>> Edge=E(V0,V4)
    GraphMLFileHandler>> Edge=E(V1,V2)
    GraphMLFileHandler>> Edge=E(V1,V3)
    GraphMLFileHandler>> Edge=E(V1,V4)
    GraphMLFileHandler>> Edge=E(V4,V5)
    GraphMLFileHandler>> Edge=E(V4,V6)
    MyTestClass>> G8116722[V6, V3, V5, V1, V2, V4, V0]
    MyTestClass>> V6
    MyTestClass>> a neighbors=1
    MyTestClass>> V3
    MyTestClass>> b neighbors=1
    MyTestClass>> V5
    MyTestClass>> c neighbors=1
    MyTestClass>> V1
    MyTestClass>> d neighbors=4
    MyTestClass>> V2
    MyTestClass>> e neighbors=1
    MyTestClass>> V4
    MyTestClass>> f neighbors=4
    MyTestClass>> V0
    MyTestClass>> g neighbors=2

     
    • Joshua O'Madadhain

      Vincent:

      The short answer is that this is not a bug (although it may not be the behavior that you want).  The contract for the java Set iterator states that the order in which the iterator visits the elements of the Set is undefined.  In particular, the order is not guaranteed to be the insertion order (and usually isn't).

      The vertices are connected up as they should be, according to their IDs; the problem you're seeing is that your IDs and your labels aren't matching up.

      FYI, GraphML uses the (default) StringLabeller to assign ids to vertices.  This means that when you get the default StringLabeller and start setting labels, you're overwriting the ID labels.  (I admit that the GraphML code and documentation need some work.)

      To fix this, don't use the iterator on g.getVertices(); fetch the vertices by ID and attach the correct label to them.  The code would look something like this:

      //sl = StringLabeller.getLabeller(graph);
      ids = StringLabeller.getLabeller(graph);
      labels = StringLabeller.getLabeller(graph, "myLabel");
      char c = 0;
      for (Iterator iter = graph.getVertices().iterator();iter.hasNext();)
      {
      //Vertex v = (Vertex) iter.next();
      Vertex v = ids.getVertex(c + '1');
      //sl.setLabel(v, "" + (char) (c + 'a' ));
      labels.setLabel(v, "" + (char) (c + 'a' ));
      c++;
      }

      I think that should do it.  Give it a try and let us know.

      Joshua

       
    • Anonymous

      Anonymous - 2004-03-12

      Joshua:
      I have just made:
      StringLabeller ids = StringLabeller.getLabeller(graph);
      Vertex v = ids.getVertex("1");
      System.out.println(v); //output: V0
      It works, thanks.
      Looping through a char is not convenient, even impossible if the labels are not in alphabetic order. GraphMLFileHandler should return a StringLabeller for the "label", and an Indexer for the "nodeId"...

      I really don't like to have the decorator separated from the graph. Are you thinking about a DecoratedGraph class, which would extend the Graph class, and implement a Labeller class ?
      Ciao,
      Vincent

       
      • Joshua O'Madadhain

        Vincent:

        I agree that looping through chars is not a robust or elegant solution.  What really needs to happen, as you noted, is that we need the GraphML code to correctly interpret (and store) the rest of the metadata provided in the file.

        Re: Indexer: the problem with using Indexer for this is that the GraphML node IDs are not guaranteed to be consecutive, which would break the Indexer contract.

        As for the separation of decorators from graphs, I have two comments. 

        (1) One of our short/medium-term goals is to improve the decorator architecture.  We have a number of ideas for this but haven't had the time to put them together into a complete design.  If you have any thoughts along these lines, we'd like to hear them.

        (2) If you really want a DecoratedGraph class, it should be pretty easy for you to create one.   At the moment I'm not convinced that it would be a good general feature for JUNG, in part because there are so many different types of decorations, and so many ways to implement them. 

        Joshua

         
    • Anonymous

      Anonymous - 2004-03-15

      Joshua:
      sorry, I have no idea how to implement a generic DecoratedGraph class. My DecoratedGraph class is quite trivial containing an instance of Graph and an instance of StringLabeller (as well as an instance of Layout). As you write, it is easy for me because I already know what kind of graph and decorator is required for my program.

      I'm happy to hear that you are working on a new design. The only thing I can do is to encourage you. Vai ! Vai ! Vai !

      Ciao,
      Vincent

       

Log in to post a comment.