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的目标节点类型相同。如果两个节点类型相同,返回的图将是同质的。否则,它将是一个二分图。

Unlike scipy, if an edge in the result graph has zero weight, it will not be removed from the graph.

注释

This function works on both CPU and GPU. For GPU, the number of nodes and edges must be less than the maximum of int32 (i.e. 2 ** 31 - 1) due to restriction of cuSPARSE.

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

如果图形格式受到限制,两个图形都必须具有CSR可用。

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

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

  • weight_name (str) –

    The feature name of edge weight of both graphs.

    The corresponding edge feature must be scalar.

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

Returns:

The new graph. The edge weight of the returned graph will have the same feature name as weight_name.

Return type:

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']