Return the relation slice of this graph.

You can get a relation slice with self[srctype, etype, dsttype], where srctype, etype, and dsttype can be either a string or a full slice (:) representing wildcard (i.e. any source/edge/destination type).

A relation slice is a homogeneous (with one node type and one edge type) or bipartite (with two node types and one edge type) graph, transformed from the original heterogeneous graph.

If there is only one canonical edge type found, then the returned relation slice would be a subgraph induced from the original graph. That is, it is equivalent to self.edge_type_subgraph(etype). The node and edge features of the returned graph would be shared with thew original graph.

If there are multiple canonical edge types found, then the source/edge/destination node types would be a concatenation of original node/edge types. The new source/destination node type would have the concatenation determined by dgl.combine_names() called on original source/destination types as its name. The source/destination node would be formed by concatenating the common features of the original source/destination types. Therefore they are not shared with the original graph. Edge type is similar.


key (str or tuple) – Either a string representing the edge type name, or a tuple in the form of (srctype, etype, dsttype) where srctype, etype, dsttype can be either strings representing type names or a full slice object (:).


The relation slice.

Return type



This function returns a new graph. Changing the content of this graph does not reflect onto the original graph.

If the graph combines multiple node types or edge types together, it will have the mapping of node/edge types and IDs from the new graph to the original graph. The mappings have the name dgl.NTYPE, dgl.NID, dgl.ETYPE and dgl.EID, similar to the function dgl.to_homogenenous().


>>> g = dgl.heterograph({
...     ('A1', 'AB1', 'B'): ([0, 1, 2], [1, 2, 3]),
...     ('A1', 'AB2', 'B'): ([1, 2, 3], [3, 4, 5]),
...     ('A2', 'AB2', 'B'): ([1, 3, 5], [2, 4, 6])})
>>> new_g = g['A1', :, 'B']         # combines all edge types between A1 and B
>>> new_g
Graph(num_nodes={'A1': 4, 'B': 7},
      num_edges={('A1', 'AB1+AB2', 'B'): 6},
      metagraph=[('A1', 'B', 'AB1+AB2')])
>>> new_g.edges()
(tensor([0, 1, 2, 1, 2, 3]), tensor([1, 2, 3, 3, 4, 5]))
>>> new_g2 = g[:, 'AB2', 'B']        # combines all node types that are source of AB2
>>> new_g2
Graph(num_nodes={'A1+A2': 10, 'B': 7},
      num_edges={('A1+A2', 'AB2+AB2', 'B'): 6},
      metagraph=[('A1+A2', 'B', 'AB2+AB2')])
>>> new_g2.edges()
(tensor([1, 2, 3, 5, 7, 9]), tensor([3, 4, 5, 2, 4, 6]))

If a combination of multiple node types and edge types occur, one can find the mapping to the original node type and IDs like the following:

>>> new_g1.edges['AB1+AB2'].data[dgl.EID]
tensor([0, 1, 2, 0, 1, 2])
>>> new_g1.edges['AB1+AB2'].data[dgl.ETYPE]
tensor([0, 0, 0, 1, 1, 1])
>>> new_g2.nodes['A1+A2'].data[dgl.NID]
tensor([0, 1, 2, 3, 0, 1, 2, 3, 4, 5])
>>> new_g2.nodes['A1+A2'].data[dgl.NTYPE]
tensor([0, 0, 0, 0, 1, 1, 1, 1, 1, 1])