:param x: tuple (s, V) of `torch.Tensor` :param edge_index: array of shape [2, n_edges] :param edge_attr: tuple (s, V) of `torch.Tensor` :param autoregressive_x: tuple (s, V) of `torch.Tensor`. If not `None`, will be used as src node embeddings
(self, x, edge_index, edge_attr,
autoregressive_x=None, node_mask=None)
| 337 | self.ff_func = nn.Sequential(*ff_func) |
| 338 | |
| 339 | def forward(self, x, edge_index, edge_attr, |
| 340 | autoregressive_x=None, node_mask=None): |
| 341 | ''' |
| 342 | :param x: tuple (s, V) of `torch.Tensor` |
| 343 | :param edge_index: array of shape [2, n_edges] |
| 344 | :param edge_attr: tuple (s, V) of `torch.Tensor` |
| 345 | :param autoregressive_x: tuple (s, V) of `torch.Tensor`. |
| 346 | If not `None`, will be used as src node embeddings |
| 347 | for forming messages where src >= dst. The corrent node |
| 348 | embeddings `x` will still be the base of the update and the |
| 349 | pointwise feedforward. |
| 350 | :param node_mask: array of type `bool` to index into the first |
| 351 | dim of node embeddings (s, V). If not `None`, only |
| 352 | these nodes will be updated. |
| 353 | ''' |
| 354 | |
| 355 | if autoregressive_x is not None: |
| 356 | src, dst = edge_index |
| 357 | mask = src < dst |
| 358 | edge_index_forward = edge_index[:, mask] |
| 359 | edge_index_backward = edge_index[:, ~mask] |
| 360 | edge_attr_forward = tuple_index(edge_attr, mask) |
| 361 | edge_attr_backward = tuple_index(edge_attr, ~mask) |
| 362 | |
| 363 | dh = tuple_sum( |
| 364 | self.conv(x, edge_index_forward, edge_attr_forward), |
| 365 | self.conv(autoregressive_x, edge_index_backward, edge_attr_backward) |
| 366 | ) |
| 367 | |
| 368 | count = scatter_add(torch.ones_like(dst), dst, |
| 369 | dim_size=dh[0].size(0)).clamp(min=1).unsqueeze(-1) |
| 370 | |
| 371 | dh = dh[0] / count, dh[1] / count.unsqueeze(-1) |
| 372 | |
| 373 | else: |
| 374 | dh = self.conv(x, edge_index, edge_attr) |
| 375 | |
| 376 | if node_mask is not None: |
| 377 | x_ = x |
| 378 | x, dh = tuple_index(x, node_mask), tuple_index(dh, node_mask) |
| 379 | |
| 380 | x = self.norm[0](tuple_sum(x, self.dropout[0](dh))) |
| 381 | |
| 382 | dh = self.ff_func(x) |
| 383 | x = self.norm[1](tuple_sum(x, self.dropout[1](dh))) |
| 384 | |
| 385 | if node_mask is not None: |
| 386 | x_[0][node_mask], x_[1][node_mask] = x[0], x[1] |
| 387 | x = x_ |
| 388 | return x |
nothing calls this directly
no test coverage detected