1.2 图、节点和边
DGL 通过一个唯一的整数来表示每个节点,称为其节点ID,并通过一对整数来表示每条边,这对整数对应于其端节点的ID。DGL 根据边被添加到图中的顺序,为每条边分配一个唯一的整数,称为其边ID。节点和边的ID编号从0开始。在DGL中,所有的边都是有方向的,边 \((u, v)\) 表示方向从节点 \(u\) 指向节点 \(v\)。
要指定多个节点,DGL使用一维整数张量(即PyTorch的张量、TensorFlow的Tensor或MXNet的ndarray)的节点ID。DGL称这种格式为“节点张量”。要指定多个边,它使用节点张量的元组\((U, V)\)。\((U[i], V[i])\)决定从\(U[i]\)到\(V[i]\)的边。
创建DGLGraph的一种方法是使用dgl.graph()方法,该方法接受一组边作为输入。DGL还支持从其他数据源创建图,请参阅1.4 从外部源创建图。
以下代码片段使用 dgl.graph() 方法来创建一个 DGLGraph,对应于下面所示的四节点图,并展示了一些用于查询图结构的API。
>>> import dgl
>>> import torch as th
>>> # edges 0->1, 0->2, 0->3, 1->3
>>> u, v = th.tensor([0, 0, 0, 1]), th.tensor([1, 2, 3, 3])
>>> g = dgl.graph((u, v))
>>> print(g) # number of nodes are inferred from the max node IDs in the given edges
Graph(num_nodes=4, num_edges=4,
ndata_schemes={}
edata_schemes={})
>>> # Node IDs
>>> print(g.nodes())
tensor([0, 1, 2, 3])
>>> # Edge end nodes
>>> print(g.edges())
(tensor([0, 0, 0, 1]), tensor([1, 2, 3, 3]))
>>> # Edge end nodes and edge IDs
>>> print(g.edges(form='all'))
(tensor([0, 0, 0, 1]), tensor([1, 2, 3, 3]), tensor([0, 1, 2, 3]))
>>> # If the node with the largest ID is isolated (meaning no edges),
>>> # then one needs to explicitly set the number of nodes
>>> g = dgl.graph((u, v), num_nodes=8)
对于无向图,需要为两个方向创建边。dgl.to_bidirected()
在这种情况下会很有帮助,它将图转换为一个具有双向边的新图。
>>> bg = dgl.to_bidirected(g)
>>> bg.edges()
(tensor([0, 0, 0, 1, 1, 2, 3, 3]), tensor([1, 2, 3, 0, 3, 0, 0, 1]))
注意
由于其在C语言中的高效内部存储以及明确的数据类型和设备上下文信息,张量类型通常在DGL API中被优先使用。然而,大多数DGL API确实支持将Python可迭代对象(例如列表)或numpy.ndarray作为参数,以便快速原型设计。
DGL 可以使用 \(32\) 位或 \(64\) 位整数来存储节点和边的 ID。节点和边 ID 的数据类型应该相同。通过使用 \(64\) 位,DGL 可以处理最多 \(2^{63} - 1\) 个节点或边的图。然而,如果图包含少于 \(2^{31} - 1\) 个节点或边,则应使用 \(32\) 位整数,因为它可以提高速度并减少内存需求。DGL 提供了进行此类转换的方法。请参见下面的示例。
>>> edges = th.tensor([2, 5, 3]), th.tensor([3, 5, 0]) # edges 2->3, 5->5, 3->0
>>> g64 = dgl.graph(edges) # DGL uses int64 by default
>>> print(g64.idtype)
torch.int64
>>> g32 = dgl.graph(edges, idtype=th.int32) # create a int32 graph
>>> g32.idtype
torch.int32
>>> g64_2 = g32.long() # convert to int64
>>> g64_2.idtype
torch.int64
>>> g32_2 = g64.int() # convert to int32
>>> g32_2.idtype
torch.int32
查看API:dgl.graph(), dgl.DGLGraph.nodes(), dgl.DGLGraph.edges(), dgl.to_bidirected(),
dgl.DGLGraph.int(), dgl.DGLGraph.long(), 和 dgl.DGLGraph.idtype.