How to build a weighted graph in dgl?


#1

So recently I want to build a weighted graph which has weighted edges, and I try to build a weighted graph by using networkx first, and turn it into the DGLGraph like following:
import networkx as nx
import dgl
import torch

G=nx.Graph()
G.add_edge(0,1,weight=0.6)
G.add_edge(0,2,weight=0.2)
G.add_edge(2,3,weight=0.1)
G.add_edge(2,4,weight=0.7)
G.add_edge(2,5,weight=0.9)
G.add_edge(0,3,weight=0.3)

dgl_G=dgl.DGLGraph(G)
and I tried to use the message_passing to know whether it is a weighted graph or not, but it seems not, or I don’t know how to use the information of edges’ weights.
So how to build a weighted graph in dgl, or how to use the information of edge’s weights in message_passing??
Thanks a lot!


#2

Hi, Thanks for using dgl!
If you want to create a DGLGraph from networkx while preserving node/edge attributes, you are encouraged to use our from_networkx api. More specifically, for your case you could rewrite your code as:

import networkx as nx
import dgl
import torch

G=nx.Graph()
G.add_edge(0,1,weight=0.6)
G.add_edge(0,2,weight=0.2)
G.add_edge(2,3,weight=0.1)
G.add_edge(2,4,weight=0.7)
G.add_edge(2,5,weight=0.9)
G.add_edge(0,3,weight=0.3)

dgl_G = dgl.DGLGraph()
dgl_G.from_networkx(G, edge_attrs=['weight']) # likewise, you could use `node_attrs` to specify node attributes.

print(dgl_G.edata['weight'])
# tensor([0.6000, 0.2000, 0.3000, 0.6000, 0.2000, 0.1000, 0.7000, 0.9000, 0.3000,
#        0.1000, 0.7000, 0.9000])

Then weight would be stored in edge data of the graph.

In message passing, there are many ways to deal with edge attributes;

In message function, you could get edge attribute by calling edges.data[field]:

import torch as th
import dgl.function as fn
g = dgl_G
g.ndata['x'] = th.ones(g.number_of_nodes()) * 0.5 # the feature 'x' of each node is 0.5
print(g.ndata['x'])
# tensor([0.5000, 0.5000, 0.5000, 0.5000, 0.5000, 0.5000])
def msg_func(edges):
    return {'src_mul_edge': edges.data['weight'] * edges.src['x']}

g.update_all(message_func=msg_func, reduce_func=fn.sum('src_mul_edge', 'x'))
print(g.ndata['x'])
# tensor([0.5500, 0.3000, 0.9500, 0.2000, 0.3500, 0.4500])

Here message func takes the node attribute x of source node, multiply it by the edge attribute weight, and send the result to the mailbox of destination node tagged with attribute src_mul_edge.
In reduce function (however, we are using the built-in function sum, for more about built-in functions, you may find our gcn tutorial useful), we take the features in mailbox tagged with src_mul_edge and summed them, we update our node feature x with the results.

We also provide an interface apply_edges, which has the same interface as message_func, but the returned value is stored on edges(it is useful in computing attention score), I think the GAT tutorial is a good place to start with.


#3

THX,I’ll have a try about that.