pyg-nightly 2.7.0.dev20250403__py3-none-any.whl → 2.7.0.dev20250404__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pyg-nightly
3
- Version: 2.7.0.dev20250403
3
+ Version: 2.7.0.dev20250404
4
4
  Summary: Graph Neural Network Library for PyTorch
5
5
  Keywords: deep-learning,pytorch,geometric-deep-learning,graph-neural-networks,graph-convolutional-networks
6
6
  Author-email: Matthias Fey <matthias@pyg.org>
@@ -1,4 +1,4 @@
1
- torch_geometric/__init__.py,sha256=_qoLOGL1sQztFtP1NfwHKDJYsWreO5B0s-W4MHDYSVs,1978
1
+ torch_geometric/__init__.py,sha256=FXQ6WZdtxVAyouslhtsPt0xXJ33VOV4_aeSKmDUWYrU,1978
2
2
  torch_geometric/_compile.py,sha256=f-WQeH4VLi5Hn9lrgztFUCSrN_FImjhQa6BxFzcYC38,1338
3
3
  torch_geometric/_onnx.py,sha256=V9ffrIKSqhDw6xUZ12lkuSfNs48cQp2EeJ6Z19GfnVw,349
4
4
  torch_geometric/backend.py,sha256=lVaf7aLoVaB3M-UcByUJ1G4T4FOK6LXAg0CF4W3E8jo,1575
@@ -426,8 +426,9 @@ torch_geometric/nn/kge/distmult.py,sha256=dGQ0bVzjreZgFN1lXE23_IIidsiOq7ehPrMb-N
426
426
  torch_geometric/nn/kge/loader.py,sha256=5Uc1j3OUMQnBYSHDqL7pLCty1siFLzoPkztigYO2zP8,771
427
427
  torch_geometric/nn/kge/rotate.py,sha256=XLuO1AbyTt5cJxr97ZzoyAyIEsHKesgW5TvDmnGJAao,3208
428
428
  torch_geometric/nn/kge/transe.py,sha256=jlejq5BLMm-sb1wWcLDp7pZqCdelWBgjDIC8ctbjSdU,3088
429
- torch_geometric/nn/models/__init__.py,sha256=gmBRXrbjkxLv_g0hfI87bSXMgwFoIo3XgslpGGdMs3g,2197
429
+ torch_geometric/nn/models/__init__.py,sha256=dwKH_fLrAMV9nda0nQHLyCzIOPezHCZa01pmTCdaJxU,2263
430
430
  torch_geometric/nn/models/attentive_fp.py,sha256=tkgvw28wg9-JqHIfBllfCwTHrZIUiv85yZJcDqjz3z0,6634
431
+ torch_geometric/nn/models/attract_repel.py,sha256=h9OyogT0NY0xiT0DkpJHMxH6ZUmo8R-CmwZdKEwq8Ek,5277
431
432
  torch_geometric/nn/models/autoencoder.py,sha256=nGje-zty78Y3hxOJ9o0_6QziJjOvBlknk6z0_fDQwQU,10770
432
433
  torch_geometric/nn/models/basic_gnn.py,sha256=PGa0RUMyvrNy_5yRI2jX_zwPsmZXwOQWfsWvxOiHsSk,31225
433
434
  torch_geometric/nn/models/captum.py,sha256=kV3lsIM7QdP9MDXmBOTq0Sf1jTEcK-_9LnwLYm2aVzw,3971
@@ -633,7 +634,7 @@ torch_geometric/utils/undirected.py,sha256=H_nfpI0_WluOG6VfjPyldvcjL4w5USAKWu2x5
633
634
  torch_geometric/visualization/__init__.py,sha256=PyR_4K5SafsJrBr6qWrkjKr6GBL1b7FtZybyXCDEVwY,154
634
635
  torch_geometric/visualization/graph.py,sha256=ZuLPL92yGRi7lxlqsUPwL_EVVXF7P2kMcveTtW79vpA,4784
635
636
  torch_geometric/visualization/influence.py,sha256=CWMvuNA_Nf1sfbJmQgn58yS4OFpeKXeZPe7kEuvkUBw,477
636
- pyg_nightly-2.7.0.dev20250403.dist-info/licenses/LICENSE,sha256=ic-27cMJc1kWoMEYncz3Ya3Ur2Bi3bNLWib2DT763-o,1067
637
- pyg_nightly-2.7.0.dev20250403.dist-info/WHEEL,sha256=G2gURzTEtmeR8nrdXUJfNiB3VYVxigPQ-bEQujpNiNs,82
638
- pyg_nightly-2.7.0.dev20250403.dist-info/METADATA,sha256=kIraJoPWCIT5AqAy_reyPy82-5ZLfzUfqqG3j30iYdg,63021
639
- pyg_nightly-2.7.0.dev20250403.dist-info/RECORD,,
637
+ pyg_nightly-2.7.0.dev20250404.dist-info/licenses/LICENSE,sha256=ic-27cMJc1kWoMEYncz3Ya3Ur2Bi3bNLWib2DT763-o,1067
638
+ pyg_nightly-2.7.0.dev20250404.dist-info/WHEEL,sha256=G2gURzTEtmeR8nrdXUJfNiB3VYVxigPQ-bEQujpNiNs,82
639
+ pyg_nightly-2.7.0.dev20250404.dist-info/METADATA,sha256=AO-euV7W-eeQ5YKe9jRqjlvrpn4qZGiLmiYV_VNxKyI,63021
640
+ pyg_nightly-2.7.0.dev20250404.dist-info/RECORD,,
@@ -31,7 +31,7 @@ from .lazy_loader import LazyLoader
31
31
  contrib = LazyLoader('contrib', globals(), 'torch_geometric.contrib')
32
32
  graphgym = LazyLoader('graphgym', globals(), 'torch_geometric.graphgym')
33
33
 
34
- __version__ = '2.7.0.dev20250403'
34
+ __version__ = '2.7.0.dev20250404'
35
35
 
36
36
  __all__ = [
37
37
  'Index',
@@ -36,6 +36,7 @@ from .sgformer import SGFormer
36
36
  # Deprecated:
37
37
  from torch_geometric.explain.algorithm.captum import (to_captum_input,
38
38
  captum_output_to_dicts)
39
+ from .attract_repel import ARLinkPredictor
39
40
 
40
41
  __all__ = classes = [
41
42
  'MLP',
@@ -84,4 +85,5 @@ __all__ = classes = [
84
85
  'MoleculeGPT',
85
86
  'GLEM',
86
87
  'SGFormer',
88
+ 'ARLinkPredictor',
87
89
  ]
@@ -0,0 +1,148 @@
1
+ import torch
2
+ import torch.nn.functional as F
3
+
4
+
5
+ class ARLinkPredictor(torch.nn.Module):
6
+ r"""Link predictor using Attract-Repel embeddings from the paper
7
+ `"Pseudo-Euclidean Attract-Repel Embeddings for Undirected Graphs"
8
+ <https://arxiv.org/abs/2106.09671>`_.
9
+
10
+ This model splits node embeddings into: attract and
11
+ repel.
12
+ The edge prediction score is computed as the dot product of attract
13
+ components minus the dot product of repel components.
14
+
15
+ Args:
16
+ in_channels (int): Size of each input sample.
17
+ hidden_channels (int): Size of hidden embeddings.
18
+ out_channels (int, optional): Size of output embeddings.
19
+ If set to :obj:`None`, will default to :obj:`hidden_channels`.
20
+ (default: :obj:`None`)
21
+ num_layers (int): Number of message passing layers.
22
+ (default: :obj:`2`)
23
+ dropout (float): Dropout probability. (default: :obj:`0.0`)
24
+ attract_ratio (float): Ratio to use for attract component.
25
+ Must be between 0 and 1. (default: :obj:`0.5`)
26
+ """
27
+ def __init__(self, in_channels, hidden_channels, out_channels=None,
28
+ num_layers=2, dropout=0.0, attract_ratio=0.5):
29
+ super().__init__()
30
+
31
+ if out_channels is None:
32
+ out_channels = hidden_channels
33
+
34
+ self.in_channels = in_channels
35
+ self.hidden_channels = hidden_channels
36
+ self.out_channels = out_channels
37
+ self.num_layers = num_layers
38
+ self.dropout = dropout
39
+
40
+ if not 0 <= attract_ratio <= 1:
41
+ raise ValueError(
42
+ f"attract_ratio must be between 0 and 1, got {attract_ratio}")
43
+
44
+ self.attract_ratio = attract_ratio
45
+ self.attract_dim = int(out_channels * attract_ratio)
46
+ self.repel_dim = out_channels - self.attract_dim
47
+
48
+ # Create model layers
49
+ self.lins = torch.nn.ModuleList()
50
+ self.lins.append(torch.nn.Linear(in_channels, hidden_channels))
51
+
52
+ for _ in range(num_layers - 2):
53
+ self.lins.append(torch.nn.Linear(hidden_channels, hidden_channels))
54
+
55
+ # Final layer splits into attract and repel components
56
+ self.lin_attract = torch.nn.Linear(hidden_channels, self.attract_dim)
57
+ self.lin_repel = torch.nn.Linear(hidden_channels, self.repel_dim)
58
+
59
+ self.reset_parameters()
60
+
61
+ def reset_parameters(self):
62
+ """Reset all learnable parameters."""
63
+ for lin in self.lins:
64
+ lin.reset_parameters()
65
+ self.lin_attract.reset_parameters()
66
+ self.lin_repel.reset_parameters()
67
+
68
+ def encode(self, x, *args, **kwargs):
69
+ """Encode node features into attract-repel embeddings.
70
+
71
+ Args:
72
+ x (torch.Tensor): Node feature matrix of shape
73
+ :obj:`[num_nodes, in_channels]`.
74
+ *args: Variable length argument list
75
+ **kwargs: Arbitrary keyword arguments
76
+
77
+ """
78
+ for lin in self.lins:
79
+ x = lin(x)
80
+ x = F.relu(x)
81
+ x = F.dropout(x, p=self.dropout, training=self.training)
82
+
83
+ # Split into attract and repel components
84
+ attract_x = self.lin_attract(x)
85
+ repel_x = self.lin_repel(x)
86
+
87
+ return attract_x, repel_x
88
+
89
+ def decode(self, attract_z, repel_z, edge_index):
90
+ """Decode edge scores from attract-repel embeddings.
91
+
92
+ Args:
93
+ attract_z (torch.Tensor): Attract embeddings of shape
94
+ :obj:`[num_nodes, attract_dim]`.
95
+ repel_z (torch.Tensor): Repel embeddings of shape
96
+ :obj:`[num_nodes, repel_dim]`.
97
+ edge_index (torch.Tensor): Edge indices of shape
98
+ :obj:`[2, num_edges]`.
99
+
100
+ Returns:
101
+ torch.Tensor: Edge prediction scores.
102
+ """
103
+ # Get node embeddings for edges
104
+ row, col = edge_index
105
+ attract_z_row = attract_z[row]
106
+ attract_z_col = attract_z[col]
107
+ repel_z_row = repel_z[row]
108
+ repel_z_col = repel_z[col]
109
+
110
+ # Compute attract-repel scores
111
+ attract_score = torch.sum(attract_z_row * attract_z_col, dim=1)
112
+ repel_score = torch.sum(repel_z_row * repel_z_col, dim=1)
113
+
114
+ return attract_score - repel_score
115
+
116
+ def forward(self, x, edge_index):
117
+ """Forward pass for link prediction.
118
+
119
+ Args:
120
+ x (torch.Tensor): Node feature matrix.
121
+ edge_index (torch.Tensor): Edge indices to predict.
122
+
123
+ Returns:
124
+ torch.Tensor: Predicted edge scores.
125
+ """
126
+ # Encode nodes into attract-repel embeddings
127
+ attract_z, repel_z = self.encode(x)
128
+
129
+ # Decode target edges
130
+ return torch.sigmoid(self.decode(attract_z, repel_z, edge_index))
131
+
132
+ def calculate_r_fraction(self, attract_z, repel_z):
133
+ """Calculate the R-fraction (proportion of energy in repel space).
134
+
135
+ Args:
136
+ attract_z (torch.Tensor): Attract embeddings.
137
+ repel_z (torch.Tensor): Repel embeddings.
138
+
139
+ Returns:
140
+ float: R-fraction value.
141
+ """
142
+ attract_norm_squared = torch.sum(attract_z**2)
143
+ repel_norm_squared = torch.sum(repel_z**2)
144
+
145
+ r_fraction = repel_norm_squared / (attract_norm_squared +
146
+ repel_norm_squared + 1e-10)
147
+
148
+ return r_fraction.item()