dgl.adj_product_graph

dgl.adj_product_graph(A, B, weight_name, etype='_E')[source]

创建一个加权图,其邻接矩阵是给定两个图的邻接矩阵的乘积。

具体来说,给定两个加权图 AB,它们的行表示源节点,列表示目标节点,此函数返回一个新的图,其加权邻接矩阵是 \(\mathrm{adj}(A) \times \mathrm{adj}(B)\)

这两个图必须是简单图,并且只能有一种边类型。此外,A 的目标节点类型与 B 的源节点类型的节点数量必须相同。

返回图的源节点类型将与图 A 的源节点类型相同。返回图的目标节点类型将与图 B 的目标节点类型相同。如果这两种节点类型相同,则返回的图将是同构图。否则,它将是一个二分图。

scipy 不同,如果结果图中的边权重为零,它不会从图中移除。

注释

此函数可在 CPU 和 GPU 上运行。对于 GPU,由于 cuSPARSE 的限制,节点和边的数量必须小于 int32 的最大值(即 2 ** 31 - 1)。

此函数返回的边权重相对于输入边权重是可微的。

如果图格式受限,则两个图都必须提供 CSR 格式。

参数:
  • A (DGLGraph) – 作为左操作数的图。

  • B (DGLGraph) – 作为右操作数的图。

  • weight_name (str) –

    两个图的边权重的特征名称。

    相应的边特征必须是标量。

  • etype (str, optional) – 返回图的边类型。

返回:

新的图。返回图的边权重将与 weight_name 具有相同的特征名称。

返回类型:

DGLGraph

示例

以下示例展示了两个二分图之间的加权邻接矩阵乘法。只要相同类型的节点数量匹配,你也可以在两个同构图或一个同构图和一个二分图之间执行此操作。

>>> A = dgl.heterograph({
...     ('A', 'AB', 'B'): ([2, 2, 0, 2, 0, 1], [2, 1, 0, 0, 2, 2])},
...     num_nodes_dict={'A': 3, 'B': 4})
>>> B = dgl.heterograph({
...     ('B', 'BA', 'A'): ([0, 3, 2, 1, 3, 3], [1, 2, 0, 2, 1, 0])},
...     num_nodes_dict={'A': 3, 'B': 4})

如果你的图是多重图,你需要先调用 dgl.to_simple() 将其转换为简单图。

>>> A = dgl.to_simple(A)
>>> B = dgl.to_simple(B)

初始化可学习的边权重。

>>> A.edata['w'] = torch.randn(6).requires_grad_()
>>> B.edata['w'] = torch.randn(6).requires_grad_()

计算乘积。

>>> C = dgl.adj_product_graph(A, B, 'w')
>>> C.edges()
(tensor([0, 0, 1, 2, 2, 2]), tensor([0, 1, 0, 0, 2, 1]))
>>> C.edata['w']
tensor([0.6906, 0.2002, 0.0591, 0.3672, 0.1066, 0.1328],
       grad_fn=<CSRMMBackward>)

注意,此函数是可微的。

>>> C.edata['w'].sum().backward()
>>> A.edata['w'].grad
tensor([0.7153, 0.2775, 0.7141, 0.7141, 0.7153, 0.7153])
>>> B.edata['w'].grad
tensor([0.4664, 0.0000, 1.5614, 0.3840, 0.0000, 0.0000])

如果左操作数的源节点类型与右操作数的目标节点类型相同,则此函数返回同构图。

>>> C.ntypes
['A']

否则,它返回二分图。

>>> A = dgl.heterograph({
...     ('A', 'AB', 'B'): ([2, 2, 0, 2, 0, 1], [2, 1, 0, 0, 2, 2])},
...     num_nodes_dict={'A': 3, 'B': 4})
>>> B = dgl.heterograph({
...     ('B', 'BC', 'C'): ([0, 3, 2, 1, 3, 3], [1, 2, 0, 2, 1, 0])},
...     num_nodes_dict={'C': 3, 'B': 4})
>>> A.edata['w'] = torch.randn(6).requires_grad_()
>>> B.edata['w'] = torch.randn(6).requires_grad_()
>>> C = dgl.adj_product_graph(A, B, 'w')
>>> C.ntypes
['A', 'C']