简体   繁体   中英

Collapsing two directed edges into one in igraph [python]

I have a directed graph where there are edges going both ways in many cases between two nodes, with varying weights. For example, a-->b with weight 3, and b-->a with weight 1. I want to combine these into a graph where only the aggregate weight exists, ie this example would result in a graph where a--> with weight 2.

I've seen g.simplify(), but how do I get this to combine opposing edges?

Assuming that there can be multiple edges in the same direction between the same two vertices, and you want to add up their weights if so, you can start with

g.simplify(combine_edges='sum')

Then for each pair of vertices a and b , at most one edge goes from a to b .

To combine these opposing edges into one edge, you can use the instance method to_undirected , which transforms g to an undirected graph. After the first step, there should be at most two edges between each pair of vertices, always opposed. So if you want to subtract the weight in one direction from the other, you could do this:

def subwt(attrs):
     if len(attrs) == 1:
         return attrs[0]
     assert len(attrs) == 2
     return attrs[0] - attrs[1]

g.to_undirected(combine_edges=subwt)

But this gives you an undirected graph, and whether the weight of an edge should be taken as going from a to b , or from b to a , is impossible to tell.

If instead you want a directed graph, how do you choose whether to make an edge from a to b with weight 2, or from b to a with weight -2?

Here is a function which will produce such a directed graph; the direction of each edge in the output graph is determined by the first edge encountered between the vertices in the input graph. Also, any edge attributes besides 'weight' are copied from that first edge, ignoring any other edges.

def combine_edges(graph):
    combe = graph.copy() # copies graph attributes, vertex attributes
    combe.delete_edges(None) # removes all edges
    for e in graph.es:
        src, targ = e.tuple
        if combe.are_connected(src, targ):
            ced = combe.es(_source=src, _target=targ)[0]
            ced['weight'] += e['weight']
        elif combe.are_connected(targ, src):
            ced = combe.es(_source=targ, _target=src)[0]
            ced['weight'] -= e['weight']
        else:
            combe.add_edge(src, targ, **e.attributes())
    return combe

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM