Search code examples
pythonnetworkxparseexceptiongraph-modelling-language

in networkX reading a gml file getting ParseException: Expected "]"


I am trying to read a GML (graph modelling language) file from networkX, but it returns a ParseError.

I just wrote a couple of lines of code:

import networkx as nx
G = nx.read_gml('test.gml')
print G.node

This is the GML file:

graph [
  directed 1
  node [
    id 0
    label 1
    shape 
    name "square"
    center (132, 258)
  ]
  node [
    id 1
    label 2
    shape 
    name "triangle"
    center (132, 128)
  ]
  edge [
    source 0
    target 1
    relation "below"
  ]
  edge [
    source 1
    target 0
    relation "above"
  ]
]

And this is the error I got:

ParseException: Expected "]" (at char 23), (line:3, col:3)

However, I don't see any ] missing


Solution

  • Immediate Problem

    The parser is getting confused with your input. I have never used gml before but I built your gml file up one piece at a time and found two problems.

    1. the shape key with no value
    2. the keys that have tuple-like values (132, 258)

    Assuming that this reference is correct, there are 4 possible value types:

    A value may have one out of four possible types, an integer (type gml$ _$int), a double (type gml$ _$double), a string (type gml$ _$string), or a list of GML objects (type gml$ _$list).

    Therefore (132, 258) is not valid and I believe having no value also would not be valid.

    Try the below commented-out gml and it will load.

    graph [
      directed 1
      node [
        id 0
        label 1
        #shape 
        name "square"
        #center (132, 258)
      ]
      node [
        id 1
        label 2
        #shape 
        name "triangle"
        #center (132, 128)
      ]
      edge [
        source 0
        target 1
        relation "below"
      ]
      edge [
        source 1
        target 0
        relation "above"
      ]
    ]
    

    Alternative Solution

    I found somewhere that nx.write_gml does not support mixed graphs including nested graphs. So even if you are creating the graph correctly, it's not going to write it correctly to a file.

    Here is an alternative flat structure that will write although I don't know if this is a good way to structure the data. It makes labels that can be constructed to identify the corners of each shape.

    import networkx as nx
    
    dg = nx.DiGraph()
    
    # square data
    square_label = '0'
    square_corners = [(0, 0), (0, 1), (1, 1), (1, 0)]
    
    # main square node
    dg.add_node(square_label, name='square')
    # shape data for square
    base_id = '{0}.corners.'.format(square_label)
    last_corner_id = '{0}{1}'.format(base_id, len(square_corners)-1)
    for i, corner in enumerate(square_corners):
        x, y = corner
        corner_id = '{0}{1}'.format(base_id, i)
        dg.add_node(corner_id, x=x, y=y)
        # instead of linking the square to every corner, you might want to link
        # only to one corner and handle the cycle with edges between the corners
        # or whatever. there are many ways it could be done I guess.
        dg.add_edge(square_label, corner_id)  # link from square to each corner
        dg.add_edge(last_corner_id, corner_id)  # corner to corner edges
        last_corner_id = corner_id
    
    nx.write_gml(dg, 'test.gml')
    

    output:

    graph [
      directed 1
      node [
        id 1
        label "0"
        name "square"
      ]
      node [
        id 0
        label "0.corners.1"
        y 1
        x 0
      ]
      node [
        id 2
        label "0.corners.3"
        y 0
        x 1
      ]
      node [
        id 3
        label "0.corners.2"
        y 1
        x 1
      ]
      node [
        id 4
        label "0.corners.0"
        y 0
        x 0
      ]
      edge [
        source 0
        target 3
      ]
      edge [
        source 1
        target 0
      ]
      edge [
        source 1
        target 4
      ]
      edge [
        source 1
        target 2
      ]
      edge [
        source 1
        target 3
      ]
      edge [
        source 2
        target 4
      ]
      edge [
        source 3
        target 2
      ]
      edge [
        source 4
        target 0
      ]
    ]