I'm translating my own algorithm from MATLAB to Python and have run into a problemn with combining edges with weights. For example, let's say I have the following edges with symbolic weights using the NetworkX package:
import networkx as nx
import sympy as sym
import itertools
x, y, z = sym.symbols('x y z')
edges = [('a', 'b', x), ('a', 'b', y), ('b','c', z)]
G = nx.MultiGraph()
G.add_weighted_edges_from(edges)
I want the output to be:
combined_edges = [('a', 'b', x + y), ('b','c', z)]
From reading through the NetworkX tutorial, they list the following code for translating a MultiGraph to a regular Graph:
for n, nbrs in G.adjacency():
for nbr, edict in nbrs.items():
minvalue = min([d['weight'] for d in edict.values()])
GG.add_edge(n, nbr, weight = minvalue)
Due to the fact that I have symbolic weights, this doesn't work.
I wrote some code to find unique edges:
unique_edges = [next(g) for _, g in itertools.groupby(edges, key=lambda x:(x[0],x[1]))]
which produces the output:
print(unique_edges)
[('a', 'b', x), ('b', 'c', z)]
How can I adapt this so that the weights of non-unique edges are summed?
You can iterate over the identical edges, then compute their sum:
import networkx as nx
import sympy as sym
x, y, z = sym.symbols('x y z')
edges = [('a', 'b', x), ('a', 'b', y), ('b','c', z)]
G = nx.MultiGraph()
for n1, n2, w in edges:
G.add_edge(n1, n2, weight=w)
H = nx.Graph()
for n1, n2, d in G.edges(data=True):
if not H.has_edge(n1, n2):
H.add_edge(n1, n2, weight=d['weight'])
else:
H[n1][n2]['weight'] += d['weight']
Or, inspired by this answer:
H = nx.Graph()
for n1, n2, d in G.edges(data=True):
if not H.has_edge(n1, n2):
H.add_edge(n1, n2, weight=sum(d['weight'] for d in G[n1][n2].values()))
Check:
G.edges(data=True)
MultiEdgeDataView([('a', 'b', {'weight': x}),
('a', 'b', {'weight': y}),
('b', 'c', {'weight': z})])
H.edges(data=True)
EdgeDataView([('a', 'b', {'weight': x + y}),
('b', 'c', {'weight': z})])