MCPcopy
hub / github.com/dmlc/dgl / random_walk_pe

Function random_walk_pe

python/dgl/transforms/functional.py:3553–3611  ·  view source on GitHub ↗

r"""Random Walk Positional Encoding, as introduced in `Graph Neural Networks with Learnable Structural and Positional Representations `__ This function computes the random walk positional encodings as landing probabilities from 1-step to k-step, sta

(g, k, eweight_name=None)

Source from the content-addressed store, hash-verified

3551
3552
3553def random_walk_pe(g, k, eweight_name=None):
3554 r"""Random Walk Positional Encoding, as introduced in
3555 `Graph Neural Networks with Learnable Structural and Positional Representations
3556 <https://arxiv.org/abs/2110.07875>`__
3557
3558 This function computes the random walk positional encodings as landing probabilities
3559 from 1-step to k-step, starting from each node to itself.
3560
3561 Parameters
3562 ----------
3563 g : DGLGraph
3564 The input graph. Must be homogeneous.
3565 k : int
3566 The number of random walk steps. The paper found the best value to be 16 and 20
3567 for two experiments.
3568 eweight_name : str, optional
3569 The name to retrieve the edge weights. Default: None, not using the edge weights.
3570
3571 Returns
3572 -------
3573 Tensor
3574 The random walk positional encodings of shape :math:`(N, k)`, where :math:`N` is the
3575 number of nodes in the input graph.
3576
3577 Example
3578 -------
3579 >>> import dgl
3580 >>> g = dgl.graph(([0,1,1], [1,1,0]))
3581 >>> dgl.random_walk_pe(g, 2)
3582 tensor([[0.0000, 0.5000],
3583 [0.5000, 0.7500]])
3584 """
3585 N = g.num_nodes() # number of nodes
3586 M = g.num_edges() # number of edges
3587 A = g.adj_external(scipy_fmt="csr") # adjacency matrix
3588 if eweight_name is not None:
3589 # add edge weights if required
3590 W = sparse.csr_matrix(
3591 (g.edata[eweight_name].squeeze(), g.find_edges(list(range(M)))),
3592 shape=(N, N),
3593 )
3594 A = A.multiply(W)
3595 # 1-step transition probability
3596 if version.parse(scipy.__version__) < version.parse("1.11.0"):
3597 RW = np.array(A / (A.sum(1) + 1e-30))
3598 else:
3599 # Sparse matrix divided by a dense array returns a sparse matrix in
3600 # scipy since 1.11.0.
3601 RW = (A / (A.sum(1) + 1e-30)).toarray()
3602
3603 # Iterate for k steps
3604 PE = [F.astype(F.tensor(np.array(RW.diagonal())), F.float32)]
3605 RW_power = RW
3606 for _ in range(k - 1):
3607 RW_power = RW_power @ RW
3608 PE.append(F.astype(F.tensor(np.array(RW_power.diagonal())), F.float32))
3609 PE = F.stack(PE, dim=-1)
3610

Callers

nothing calls this directly

Calls 6

adj_externalMethod · 0.80
appendMethod · 0.80
num_nodesMethod · 0.45
num_edgesMethod · 0.45
find_edgesMethod · 0.45
astypeMethod · 0.45

Tested by

no test coverage detected