Graph rewrite examples, generated by Soffit

in programming •  6 years ago 

I started at doc/examples directory for the soffit project, and
my first two examples are there. Unfortunately, only one of them looks any good.

The way I finally convinced graphviz to lay things out the way I wanted is pretty gross. First, lay out each graph individually, and then copy the position from the Agraph object that does this back to the original networkx graph:

def position( graph ):
    """Render a graph with 'neato', and return its bounding box."""
    agraph = to_agraph( graph )
    agraph.layout( prog='neato' )
    for n in graph.nodes:
        graph.nodes[ n ]['pos'] = agraph.get_node( n ).attr['pos']
    for (s,t) in graph.edges:
        graph.edges[s,t]['pos'] = agraph.get_edge( s, t ).attr['pos']
    return [ float(i) for i in agraph.graph_attr['bb'].split( ',' ) ]

Call this for each graph to get its size:

    (_, _, leftX, leftY) = position( l )
    (_, _, gX, gY) = position( g )
    # FIXME: initialize r with l's positions
    (_, _, rightX, rightY) = position( r )
    # FIXME: initialize h with g's positions
    (_, _, hX, hY) = position( h )

Then rewrite the positions so that they're laid out in the format I want:

    centerX = max( leftX, gX )
    centerY = max( gY, hY )
    # Lower left - Bring g up to the center line
    reposition( g, centerY - gY, 0.0 )
    # Lower right
    reposition( h, centerY - hY, centerX + 10 )
    # Upper left
    reposition( l, centerY + 10, 0.0 )
    # Upper right
    reposition( r, centerY + 10, centerX + 10 )

Here's the code that unpacks and repacks the strings to do the offset:

def reposition_pos( pos, yOffset, xOffset ):\
    return " ".join(
        ",".join( [ str( float( y ) + yOffset ),
                    str( float( x ) + xOffset ) ] )
        for coord in pos.split( " " )
        for (y,x) in [ coord.split( "," ) ]
    )

def reposition( graph, xOffset, yOffset ):
    """Update all pos attributes to a different location."""
    for n in graph.nodes:
        graph.nodes[ n ]['pos'] = reposition_pos( graph.nodes[n]['pos'],
                                                  yOffset, xOffset )
    for (s,t) in graph.edges:
        graph.edges[s,t]['pos'] = reposition_pos( graph.edges[s,t]['pos'],
                                                  yOffset, xOffset )

Finally, put all the graphs back together into a single graph, and plot that:

    collection = nx.disjoint_union( l, r )
    collection = nx.disjoint_union( collection, g )
    collection = nx.disjoint_union( collection, h )
    agraph = to_agraph( collection )
    agraph.draw( outputFile, prog="neato", args="-n" )

I omitted the steps to color and label the graph, which is just a matter of adding attributes.

Here is reproduces the example in "Pushouts on Labeled Graphs", though Soffit does not permit multiple edges between nodes:

As seems standard with graphviz, edge label placement is awful.

Authors get paid when people like you upvote their post.
If you enjoyed what you read here, create your account today and start earning FREE STEEM!
Sort Order:  

Hello! Your post has been resteemed and upvoted by @ilovecoding because we love coding! Keep up good work! Consider upvoting this comment to support the @ilovecoding and increase your future rewards! ^_^ Steem On!

Reply !stop to disable the comment. Thanks!

Also, this display doesn't show the difference between merging A and B and just deleting B.