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.