"tests/vscode:/vscode.git/clone" did not exist on "a99095e78ca1fc50ecf538d778097e5eff9894c4"
Unverified Commit dacc7afe authored by Mufei Li's avatar Mufei Li Committed by GitHub
Browse files

[Convert] Reserve node/edge IDs in to_heterogeneous (#2045)



* Fix

* Fix
Co-authored-by: default avatarxiang song(charlie.song) <classicxsong@gmail.com>
parent 9088c635
...@@ -369,7 +369,10 @@ def to_heterogeneous(G, ntypes, etypes, ntype_field=NTYPE, ...@@ -369,7 +369,10 @@ def to_heterogeneous(G, ntypes, etypes, ntype_field=NTYPE,
type name, but can be distinguished by a canonical edge type tuple. type name, but can be distinguished by a canonical edge type tuple.
This function will copy any node/edge features from :attr:`G` to the returned heterogeneous This function will copy any node/edge features from :attr:`G` to the returned heterogeneous
graph, except for node/edge types and IDs used to recover the heterogeneous graph. graph, except for node/edge types to recover the heterogeneous graph.
One can retrieve the IDs of the nodes/edges in :attr:`G` from the returned heterogeneous
graph with node feature ``dgl.NID`` and edge feature ``dgl.EID`` respectively.
Parameters Parameters
---------- ----------
...@@ -408,15 +411,19 @@ def to_heterogeneous(G, ntypes, etypes, ntype_field=NTYPE, ...@@ -408,15 +411,19 @@ def to_heterogeneous(G, ntypes, etypes, ntype_field=NTYPE,
Examples Examples
-------- --------
The following example uses PyTorch backend.
>>> import dgl >>> import dgl
>>> import torch
>>> hg = dgl.heterograph({ >>> hg = dgl.heterograph({
... ('user', 'develops', 'activity'): ([0, 1], [1, 2]), ... ('user', 'develops', 'activity'): (torch.tensor([0, 1]), torch.tensor([1, 2])),
... ('developer', 'develops', 'game'): ([0, 1], [0, 1]) ... ('developer', 'develops', 'game'): (torch.tensor([0, 1]), torch.tensor([0, 1]))
... }) ... })
>>> print(hg) >>> print(hg)
Graph(num_nodes={'user': 2, 'activity': 3, 'developer': 2, 'game': 2}, Graph(num_nodes={'activity': 3, 'developer': 2, 'game': 2, 'user': 2},
num_edges={('user', 'develops', 'activity'): 2, ('developer', 'develops', 'game'): 2}, num_edges={('developer', 'develops', 'game'): 2, ('user', 'develops', 'activity'): 2},
metagraph=[('user', 'activity'), ('developer', 'game')]) metagraph=[('developer', 'game', 'develops'), ('user', 'activity', 'develops')])
We first convert the heterogeneous graph to a homogeneous graph. We first convert the heterogeneous graph to a homogeneous graph.
...@@ -428,19 +435,30 @@ def to_heterogeneous(G, ntypes, etypes, ntype_field=NTYPE, ...@@ -428,19 +435,30 @@ def to_heterogeneous(G, ntypes, etypes, ntype_field=NTYPE,
edata_schemes={'_TYPE': Scheme(shape=(), dtype=torch.int64), edata_schemes={'_TYPE': Scheme(shape=(), dtype=torch.int64),
'_ID': Scheme(shape=(), dtype=torch.int64)}) '_ID': Scheme(shape=(), dtype=torch.int64)})
>>> g.ndata >>> g.ndata
{'_TYPE': tensor([0, 0, 1, 1, 1, 2, 2, 3, 3]), '_ID': tensor([0, 1, 0, 1, 2, 0, 1, 0, 1])} {'_TYPE': tensor([0, 0, 0, 1, 1, 2, 2, 3, 3]), '_ID': tensor([0, 1, 2, 0, 1, 0, 1, 0, 1])}
Nodes 0, 1 for 'user', 2, 3, 4 for 'activity', 5, 6 for 'developer', 7, 8 for 'game' Nodes 0, 1, 2 for 'activity', 3, 4 for 'developer', 5, 6 for 'game', 7, 8 for 'user'
>>> g.edata >>> g.edata
{'_TYPE': tensor([0, 0, 1, 1]), '_ID': tensor([0, 1, 0, 1])} {'_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') Edges 0, 1 for ('developer', 'develops', 'game'), 2, 3 for ('user', 'develops', 'activity')
Now convert the homogeneous graph back to a heterogeneous graph. Now convert the homogeneous graph back to a heterogeneous graph.
>>> hg_2 = dgl.to_heterogeneous(g, hg.ntypes, hg.etypes) >>> hg_2 = dgl.to_heterogeneous(g, hg.ntypes, hg.etypes)
>>> print(hg_2) >>> print(hg_2)
Graph(num_nodes={'user': 2, 'activity': 3, 'developer': 2, 'game': 2}, Graph(num_nodes={'activity': 3, 'developer': 2, 'game': 2, 'user': 2},
num_edges={('user', 'develops', 'activity'): 2, ('developer', 'develops', 'game'): 2}, num_edges={('developer', 'develops', 'game'): 2, ('user', 'develops', 'activity'): 2},
metagraph=[('user', 'activity'), ('developer', 'game')]) metagraph=[('developer', 'game', 'develops'), ('user', 'activity', 'develops')])
Retrieve the original node/edge IDs.
>>> hg_2.ndata[dgl.NID]
{'activity': tensor([0, 1, 2]),
'developer': tensor([3, 4]),
'game': tensor([5, 6]),
'user': tensor([7, 8])}
>>> hg_2.edata[dgl.EID]
{('developer', 'develops', 'game'): tensor([0, 1]),
('user', 'develops', 'activity'): tensor([2, 3])}
See Also See Also
-------- --------
...@@ -530,6 +548,13 @@ def to_heterogeneous(G, ntypes, etypes, ntype_field=NTYPE, ...@@ -530,6 +548,13 @@ def to_heterogeneous(G, ntypes, etypes, ntype_field=NTYPE,
hg._edge_frames[hg.get_etype_id(canonical_etypes[etid])][key] = \ hg._edge_frames[hg.get_etype_id(canonical_etypes[etid])][key] = \
F.gather_row(data, rows) F.gather_row(data, rows)
# Record the original IDs of the nodes/edges
for ntid, ntype in enumerate(hg.ntypes):
hg._node_frames[ntid][NID] = F.copy_to(F.tensor(ntype2ngrp[ntype]), device)
for etid in range(len(hg.canonical_etypes)):
hg._edge_frames[hg.get_etype_id(canonical_etypes[etid])][EID] = \
F.copy_to(F.tensor(edge_groups[etid]), device)
return hg return hg
def to_hetero(G, ntypes, etypes, ntype_field=NTYPE, etype_field=ETYPE, def to_hetero(G, ntypes, etypes, ntype_field=NTYPE, etype_field=ETYPE,
......
...@@ -1009,6 +1009,12 @@ def test_convert(idtype): ...@@ -1009,6 +1009,12 @@ def test_convert(idtype):
assert hg.number_of_edges('e0') == 2 assert hg.number_of_edges('e0') == 2
assert hg.number_of_edges('e1') == 1 assert hg.number_of_edges('e1') == 1
assert hg.number_of_edges('e2') == 1 assert hg.number_of_edges('e2') == 1
assert F.array_equal(hg.ndata[dgl.NID]['l0'], F.tensor([0, 1], F.int64))
assert F.array_equal(hg.ndata[dgl.NID]['l1'], F.tensor([2], F.int64))
assert F.array_equal(hg.ndata[dgl.NID]['l2'], F.tensor([3], F.int64))
assert F.array_equal(hg.edata[dgl.EID][('l0', 'e0', 'l1')], F.tensor([0, 1], F.int64))
assert F.array_equal(hg.edata[dgl.EID][('l0', 'e2', 'l2')], F.tensor([3], F.int64))
assert F.array_equal(hg.edata[dgl.EID][('l1', 'e1', 'l2')], F.tensor([2], F.int64))
# hetero_from_homo test case 3 # hetero_from_homo test case 3
mg = nx.MultiDiGraph([ mg = nx.MultiDiGraph([
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment