简体   繁体   中英

How to remove an edge with attributes from a multidigraph in NetworkX?

I will be building out a large multidigraph which will have paths that repeat edges. It seems that if I can iterate through each edge as is, I should be able to delete that edge.

See the example code from below. Say that I want to remove edge with path=a and sequence=3.

H.remove_edge(u,v,key=none) implies the use of a singular key, labeled "key". Remove_edge(1,2) will pick an arbitrary edge from that list.

Is there a way to remove that edge without the addition of "key" attributes for each edge?

H = nx.MultiDiGraph()
H.add_edge(1,2,path='a',sequence=1)
H.add_edge(2,1,path='a',sequence=2)
H.add_edge(1,2,path='a',sequence=3)
H.add_edge(1,2,path='b',sequence=1)

print "starting edges:"
for u,v,d in H.edges_iter(data=True):
    print str(u)+ " -> " +str(v) + ": "+str(d)

for post in H.out_edges(1,data=True):
    if post[2]['path'] == 'a' and post[2]['sequence'] == 3:
        H.remove_edge(*post[:2])

print "after single edge removal:"
for u,v,d in H.edges_iter(data=True):
    print str(u)+ " -> " +str(v) + ": "+str(d)
  • Output:
    • starting edges:
    • 1 -> 2: {'path': 'a', 'sequence': 1}
    • 1 -> 2: {'path': 'a', 'sequence': 3}
    • 1 -> 2: {'path': 'b', 'sequence': 1}
    • 2 -> 1: {'path': 'a', 'sequence': 2}
    • after single edge removal:
    • 1 -> 2: {'path': 'a', 'sequence': 3}
    • 1 -> 2: {'path': 'b', 'sequence': 1}
    • 2 -> 1: {'path': 'a', 'sequence': 2}

Since keys are built in to the graph automatically, you can access an edge by its key while iterating:

for post in H.out_edges(1,keys=True,data=True):
    if post[3]['path'] == 'a' and post[3]['sequence'] == 3:
        H.remove_edge(post[0],post[1],key=post[2])

Take a look at networkx's source code: classes/multigraph.py

def remove_edge(self, u, v, key=None):
    """Remove an edge between u and v.

    """
    try:
        d=self.adj[u][v]

...

    # remove the edge with specified data
    if key is None:
        d.popitem()
    else:
        try:
            del d[key]
        except (KeyError):
            raise NetworkXError(
            "The edge %s-%s with key %s is not in the graph."%(u,v,key))
    if len(d)==0:
        # remove the key entries if last edge
        del self.adj[u][v]
        if u!=v:  # check for selfloop
            del self.adj[v][u]

As you can see, networkx really just del s the edge; if you don't want to use a key key, just iterate over the edges between 1 and 2 and del the one you want to get rid of.

You could also invent a add_edge wrapper (or simply overwrite add_edge ) that would (if not specified otherwise) write a key according to your path and sequence parameters (instead of just counting up the last automatic key id).

Here is how to remove a single keyed edge using the networkx api:

In [1]: import networkx as nx

In [2]: H = nx.MultiDiGraph()

In [3]: H.add_edge(1,2,path='a',sequence=1)

In [4]: H.add_edge(2,1,path='a',sequence=2)

In [5]: H.add_edge(1,2,path='a',sequence=3)

In [6]: H.add_edge(1,2,path='b',sequence=1)

In [7]: for u,v,key,data in H.out_edges(1,data=True,keys=True):
            if data['path']== 'a' and data['sequence']==3:
                H.remove_edge(u,v,key=key)
   ...:         

In [8]: H.edges(data=True)
Out[8]: 
[(1, 2, {'path': 'a', 'sequence': 1}),
 (1, 2, {'path': 'b', 'sequence': 1}),
 (2, 1, {'path': 'a', 'sequence': 2})]

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