dgl.to_hetero(G, ntypes, etypes, ntype_field='_TYPE', etype_field='_TYPE', metagraph=None)[source]

Convert the given homogeneous graph to a heterogeneous graph.

The input graph should have only one type of nodes and edges. Each node and edge stores an integer feature (under ntype_field and etype_field), representing the type id, which can be used to retrieve the type names stored in the given ntypes and etypes arguments.

The function will automatically distinguish edge types that have the same given type IDs but different src and dst type IDs. For example, we allow both edges A and B to have the same type ID 0, but one has (0, 1) and the other as (2, 3) as the (src, dst) type IDs. In this case, the function will “split” edge type 0 into two types: (0, ty_A, 1) and (2, ty_B, 3). In another word, these two edges share the same edge type name, but can be distinguished by a canonical edge type tuple.

  • G (DGLHeteroGraph) – Input homogeneous graph.
  • ntypes (list of str) – The node type names.
  • etypes (list of str) – The edge type names.
  • ntype_field (str, optional) – The feature field used to store node type. (Default: dgl.NTYPE)
  • etype_field (str, optional) – The feature field used to store edge type. (Default: dgl.ETYPE)
  • metagraph (networkx MultiDiGraph, optional) – Metagraph of the returned heterograph. If provided, DGL assumes that G can indeed be described with the given metagraph. If None, DGL will infer the metagraph from the given inputs, which would be potentially slower for large graphs.

A heterograph. The parent node and edge ID are stored in the column dgl.NID and dgl.EID respectively for all node/edge types.

Return type:



The returned node and edge types may not necessarily be in the same order as ntypes and etypes. And edge types may be duplicated if the source and destination types differ.

The node IDs of a single type in the returned heterogeneous graph is ordered the same as the nodes with the same ntype_field feature. Edge IDs of a single type is similar.


>>> g1 = dgl.bipartite([(0, 1), (1, 2)], 'user', 'develops', 'activity')
>>> g2 = dgl.bipartite([(0, 0), (1, 1)], 'developer', 'develops', 'game')
>>> hetero_g = dgl.hetero_from_relations([g1, g2])
>>> print(hetero_g)
Graph(num_nodes={'user': 2, 'activity': 3, 'developer': 2, 'game': 2},
      num_edges={('user', 'develops', 'activity'): 2, ('developer', 'develops', 'game'): 2},
      metagraph=[('user', 'activity'), ('developer', 'game')])

We first convert the heterogeneous graph to a homogeneous graph.

>>> homo_g = dgl.to_homo(hetero_g)
>>> print(homo_g)
Graph(num_nodes=9, num_edges=4,
      ndata_schemes={'_TYPE': Scheme(shape=(), dtype=torch.int64),
                     '_ID': Scheme(shape=(), dtype=torch.int64)}
      edata_schemes={'_TYPE': Scheme(shape=(), dtype=torch.int64),
                     '_ID': Scheme(shape=(), dtype=torch.int64)})
>>> homo_g.ndata
{'_TYPE': tensor([0, 0, 1, 1, 1, 2, 2, 3, 3]), '_ID': tensor([0, 1, 0, 1, 2, 0, 1, 0, 1])}
Nodes 0, 1 for 'user', 2, 3, 4 for 'activity', 5, 6 for 'developer', 7, 8 for 'game'
>>> homo_g.edata
{'_TYPE': tensor([0, 0, 1, 1]), '_ID': tensor([0, 1, 0, 1])}
Edges 0, 1 for ('user', 'develops', 'activity'), 2, 3 for ('developer', 'develops', 'game')

Now convert the homogeneous graph back to a heterogeneous graph.

>>> hetero_g_2 = dgl.to_hetero(homo_g, hetero_g.ntypes, hetero_g.etypes)
>>> print(hetero_g_2)
Graph(num_nodes={'user': 2, 'activity': 3, 'developer': 2, 'game': 2},
      num_edges={('user', 'develops', 'activity'): 2, ('developer', 'develops', 'game'): 2},
      metagraph=[('user', 'activity'), ('developer', 'game')])

See also