dmlc--dgl
52d4535b61
* moving heterograph index to another file * node view * python interfaces * heterograph init * bug fixes * docstring for readonly * more docstring * unit tests & lint * oops * oops x2 * removed node/edge addition * addressed comments * lint * rw on frames with one node/edge type * homograph with underlying heterograph demo * view is not necessary * bugfix * replace * scheduler, builtins not working yet * moving bipartite.h to header * moving back bipartite to bipartite.h * oops * asbits and copyto for bipartite * tested update_all and send_and_recv * lightweight node & edge type retrieval * oops * sorry * removing obsolete code * oops * lint * various bug fixes & more tests * UDF tests * multiple type number_of_nodes and number_of_edges * docstring fixes * more tests * going for dict in initialization * lint * updated api as per discussions * lint * bug * bugfix * moving back bipartite impl to cc * note on views * fix
359 行
14 KiB
Python
359 行
14 KiB
Python
import numpy as np
|
|
import dgl
|
|
import dgl.ndarray as nd
|
|
import dgl.graph_index as dgl_gidx
|
|
import dgl.heterograph_index as dgl_hgidx
|
|
from dgl.utils import toindex
|
|
import backend as F
|
|
|
|
"""
|
|
Test with a heterograph of three ntypes and three etypes
|
|
meta graph:
|
|
0 -> 1
|
|
1 -> 2
|
|
2 -> 1
|
|
|
|
Num nodes per ntype:
|
|
0 : 5
|
|
1 : 2
|
|
2 : 3
|
|
|
|
rel graph:
|
|
0->1 : [0 -> 0, 1 -> 0, 2 -> 0, 3 -> 0]
|
|
1->2 : [0 -> 0, 1 -> 1, 1 -> 2]
|
|
2->1 : [0 -> 1, 1 -> 1, 2 -> 1]
|
|
"""
|
|
|
|
def _array_equal(dglidx, l):
|
|
return list(dglidx) == list(l)
|
|
|
|
def rel1_from_coo():
|
|
row = toindex([0, 1, 2, 3])
|
|
col = toindex([0, 0, 0, 0])
|
|
return dgl_hgidx.create_bipartite_from_coo(5, 2, row, col)
|
|
|
|
def rel2_from_coo():
|
|
row = toindex([0, 1, 1])
|
|
col = toindex([0, 1, 2])
|
|
return dgl_hgidx.create_bipartite_from_coo(2, 3, row, col)
|
|
|
|
def rel3_from_coo():
|
|
row = toindex([0, 1, 2])
|
|
col = toindex([1, 1, 1])
|
|
return dgl_hgidx.create_bipartite_from_coo(3, 2, row, col)
|
|
|
|
def rel1_from_csr():
|
|
indptr = toindex([0, 1, 2, 3, 4, 4])
|
|
indices = toindex([0, 0, 0, 0])
|
|
edge_ids = toindex([0, 1, 2, 3])
|
|
return dgl_hgidx.create_bipartite_from_csr(5, 2, indptr, indices, edge_ids)
|
|
|
|
def rel2_from_csr():
|
|
indptr = toindex([0, 1, 3])
|
|
indices = toindex([0, 1, 2])
|
|
edge_ids = toindex([0, 1, 2])
|
|
return dgl_hgidx.create_bipartite_from_csr(2, 3, indptr, indices, edge_ids)
|
|
|
|
def rel3_from_csr():
|
|
indptr = toindex([0, 1, 2, 3])
|
|
indices = toindex([1, 1, 1])
|
|
edge_ids = toindex([0, 1, 2])
|
|
return dgl_hgidx.create_bipartite_from_csr(3, 2, indptr, indices, edge_ids)
|
|
|
|
def gen_from_coo():
|
|
mg = dgl_gidx.from_edge_list([(0, 1), (1, 2), (2, 1)], is_multigraph=False, readonly=True)
|
|
return dgl_hgidx.create_heterograph(mg, [rel1_from_coo(), rel2_from_coo(), rel3_from_coo()])
|
|
|
|
def gen_from_csr():
|
|
mg = dgl_gidx.from_edge_list([(0, 1), (1, 2), (2, 1)], is_multigraph=False, readonly=True)
|
|
return dgl_hgidx.create_heterograph(mg, [rel1_from_csr(), rel2_from_csr(), rel3_from_csr()])
|
|
|
|
def test_query():
|
|
R1 = 0
|
|
R2 = 1
|
|
R3 = 2
|
|
def _test_g(g):
|
|
assert g.number_of_ntypes() == 3
|
|
assert g.number_of_etypes() == 3
|
|
assert g.metagraph.number_of_nodes() == 3
|
|
assert g.metagraph.number_of_edges() == 3
|
|
assert g.ctx() == nd.cpu(0)
|
|
assert g.nbits() == 64
|
|
assert not g.is_multigraph()
|
|
assert g.is_readonly()
|
|
# relation graph 1
|
|
assert g.number_of_nodes(R1) == 5
|
|
assert g.number_of_edges(R1) == 4
|
|
assert g.has_node(0, 0)
|
|
assert not g.has_node(0, 10)
|
|
assert _array_equal(g.has_nodes(0, toindex([0, 10])), [1, 0])
|
|
assert g.has_edge_between(R1, 3, 0)
|
|
assert not g.has_edge_between(R1, 4, 0)
|
|
assert _array_equal(g.has_edges_between(R1, toindex([3, 4]), toindex([0, 0])), [1, 0])
|
|
assert _array_equal(g.predecessors(R1, 0), [0, 1, 2, 3])
|
|
assert _array_equal(g.predecessors(R1, 1), [])
|
|
assert _array_equal(g.successors(R1, 3), [0])
|
|
assert _array_equal(g.successors(R1, 4), [])
|
|
assert _array_equal(g.edge_id(R1, 0, 0), [0])
|
|
src, dst, eid = g.edge_ids(R1, toindex([0, 2, 1, 3]), toindex([0, 0, 0, 0]))
|
|
assert _array_equal(src, [0, 2, 1, 3])
|
|
assert _array_equal(dst, [0, 0, 0, 0])
|
|
assert _array_equal(eid, [0, 2, 1, 3])
|
|
src, dst, eid = g.find_edges(R1, toindex([3, 0]))
|
|
assert _array_equal(src, [3, 0])
|
|
assert _array_equal(dst, [0, 0])
|
|
assert _array_equal(eid, [3, 0])
|
|
src, dst, eid = g.in_edges(R1, toindex([0, 1]))
|
|
assert _array_equal(src, [0, 1, 2, 3])
|
|
assert _array_equal(dst, [0, 0, 0, 0])
|
|
assert _array_equal(eid, [0, 1, 2, 3])
|
|
src, dst, eid = g.out_edges(R1, toindex([1, 0, 4]))
|
|
assert _array_equal(src, [1, 0])
|
|
assert _array_equal(dst, [0, 0])
|
|
assert _array_equal(eid, [1, 0])
|
|
src, dst, eid = g.edges(R1, 'eid')
|
|
assert _array_equal(src, [0, 1, 2, 3])
|
|
assert _array_equal(dst, [0, 0, 0, 0])
|
|
assert _array_equal(eid, [0, 1, 2, 3])
|
|
assert g.in_degree(R1, 0) == 4
|
|
assert g.in_degree(R1, 1) == 0
|
|
assert _array_equal(g.in_degrees(R1, toindex([0, 1])), [4, 0])
|
|
assert g.out_degree(R1, 2) == 1
|
|
assert g.out_degree(R1, 4) == 0
|
|
assert _array_equal(g.out_degrees(R1, toindex([4, 2])), [0, 1])
|
|
# adjmat
|
|
adj = g.adjacency_matrix(R1, True, F.cpu())[0]
|
|
assert np.allclose(F.sparse_to_numpy(adj),
|
|
np.array([[1., 0.],
|
|
[1., 0.],
|
|
[1., 0.],
|
|
[1., 0.],
|
|
[0., 0.]]))
|
|
adj = g.adjacency_matrix(R2, True, F.cpu())[0]
|
|
assert np.allclose(F.sparse_to_numpy(adj),
|
|
np.array([[1., 0., 0.],
|
|
[0., 1., 1.]]))
|
|
adj = g.adjacency_matrix(R3, True, F.cpu())[0]
|
|
assert np.allclose(F.sparse_to_numpy(adj),
|
|
np.array([[0., 1.],
|
|
[0., 1.],
|
|
[0., 1.]]))
|
|
|
|
g = gen_from_coo()
|
|
_test_g(g)
|
|
g = gen_from_csr()
|
|
_test_g(g)
|
|
|
|
def test_subgraph():
|
|
R1 = 0
|
|
R2 = 1
|
|
R3 = 2
|
|
def _test_g(g):
|
|
# node subgraph
|
|
induced_nodes = [toindex([0, 1, 4]), toindex([0]), toindex([0, 2])]
|
|
sub = g.node_subgraph(induced_nodes)
|
|
subg = sub.graph
|
|
assert subg.number_of_ntypes() == 3
|
|
assert subg.number_of_etypes() == 3
|
|
assert subg.number_of_nodes(0) == 3
|
|
assert subg.number_of_nodes(1) == 1
|
|
assert subg.number_of_nodes(2) == 2
|
|
assert subg.number_of_edges(R1) == 2
|
|
assert subg.number_of_edges(R2) == 1
|
|
assert subg.number_of_edges(R3) == 0
|
|
adj = subg.adjacency_matrix(R1, True, F.cpu())[0]
|
|
assert np.allclose(F.sparse_to_numpy(adj),
|
|
np.array([[1.],
|
|
[1.],
|
|
[0.]]))
|
|
adj = subg.adjacency_matrix(R2, True, F.cpu())[0]
|
|
assert np.allclose(F.sparse_to_numpy(adj),
|
|
np.array([[1., 0.]]))
|
|
adj = subg.adjacency_matrix(R3, True, F.cpu())[0]
|
|
assert np.allclose(F.sparse_to_numpy(adj),
|
|
np.array([[0.],
|
|
[0.]]))
|
|
assert len(sub.induced_nodes) == 3
|
|
assert _array_equal(sub.induced_nodes[0], induced_nodes[0])
|
|
assert _array_equal(sub.induced_nodes[1], induced_nodes[1])
|
|
assert _array_equal(sub.induced_nodes[2], induced_nodes[2])
|
|
assert len(sub.induced_edges) == 3
|
|
assert _array_equal(sub.induced_edges[0], [0, 1])
|
|
assert _array_equal(sub.induced_edges[1], [0])
|
|
assert _array_equal(sub.induced_edges[2], [])
|
|
|
|
# node subgraph with empty type graph
|
|
induced_nodes = [toindex([0, 1, 4]), toindex([0]), toindex([])]
|
|
sub = g.node_subgraph(induced_nodes)
|
|
subg = sub.graph
|
|
assert subg.number_of_ntypes() == 3
|
|
assert subg.number_of_etypes() == 3
|
|
assert subg.number_of_nodes(0) == 3
|
|
assert subg.number_of_nodes(1) == 1
|
|
assert subg.number_of_nodes(2) == 0
|
|
assert subg.number_of_edges(R1) == 2
|
|
assert subg.number_of_edges(R2) == 0
|
|
assert subg.number_of_edges(R3) == 0
|
|
adj = subg.adjacency_matrix(R1, True, F.cpu())[0]
|
|
assert np.allclose(F.sparse_to_numpy(adj),
|
|
np.array([[1.],
|
|
[1.],
|
|
[0.]]))
|
|
adj = subg.adjacency_matrix(R2, True, F.cpu())[0]
|
|
assert np.allclose(F.sparse_to_numpy(adj),
|
|
np.array([]))
|
|
adj = subg.adjacency_matrix(R3, True, F.cpu())[0]
|
|
assert np.allclose(F.sparse_to_numpy(adj),
|
|
np.array([]))
|
|
|
|
# edge subgraph (preserve_nodes=False)
|
|
induced_edges = [toindex([0, 2]), toindex([0]), toindex([0, 1, 2])]
|
|
sub = g.edge_subgraph(induced_edges, False)
|
|
subg = sub.graph
|
|
assert subg.number_of_ntypes() == 3
|
|
assert subg.number_of_etypes() == 3
|
|
assert subg.number_of_nodes(0) == 2
|
|
assert subg.number_of_nodes(1) == 2
|
|
assert subg.number_of_nodes(2) == 3
|
|
assert subg.number_of_edges(R1) == 2
|
|
assert subg.number_of_edges(R2) == 1
|
|
assert subg.number_of_edges(R3) == 3
|
|
adj = subg.adjacency_matrix(R1, True, F.cpu())[0]
|
|
assert np.allclose(F.sparse_to_numpy(adj),
|
|
np.array([[1., 0.],
|
|
[1., 0.]]))
|
|
adj = subg.adjacency_matrix(R2, True, F.cpu())[0]
|
|
assert np.allclose(F.sparse_to_numpy(adj),
|
|
np.array([[1., 0., 0.],
|
|
[0., 0., 0.]]))
|
|
adj = subg.adjacency_matrix(R3, True, F.cpu())[0]
|
|
assert np.allclose(F.sparse_to_numpy(adj),
|
|
np.array([[0., 1.],
|
|
[0., 1.],
|
|
[0., 1.]]))
|
|
assert len(sub.induced_nodes) == 3
|
|
assert _array_equal(sub.induced_nodes[0], [0, 2])
|
|
assert _array_equal(sub.induced_nodes[1], [0, 1])
|
|
assert _array_equal(sub.induced_nodes[2], [0, 1, 2])
|
|
assert len(sub.induced_edges) == 3
|
|
assert _array_equal(sub.induced_edges[0], induced_edges[0])
|
|
assert _array_equal(sub.induced_edges[1], induced_edges[1])
|
|
assert _array_equal(sub.induced_edges[2], induced_edges[2])
|
|
|
|
# edge subgraph (preserve_nodes=True)
|
|
induced_edges = [toindex([0, 2]), toindex([0]), toindex([0, 1, 2])]
|
|
sub = g.edge_subgraph(induced_edges, True)
|
|
subg = sub.graph
|
|
assert subg.number_of_ntypes() == 3
|
|
assert subg.number_of_etypes() == 3
|
|
assert subg.number_of_nodes(0) == 5
|
|
assert subg.number_of_nodes(1) == 2
|
|
assert subg.number_of_nodes(2) == 3
|
|
assert subg.number_of_edges(R1) == 2
|
|
assert subg.number_of_edges(R2) == 1
|
|
assert subg.number_of_edges(R3) == 3
|
|
adj = subg.adjacency_matrix(R1, True, F.cpu())[0]
|
|
assert np.allclose(F.sparse_to_numpy(adj),
|
|
np.array([[1., 0.],
|
|
[0., 0.],
|
|
[1., 0.],
|
|
[0., 0.],
|
|
[0., 0.]]))
|
|
adj = subg.adjacency_matrix(R2, True, F.cpu())[0]
|
|
assert np.allclose(F.sparse_to_numpy(adj),
|
|
np.array([[1., 0., 0.],
|
|
[0., 0., 0.]]))
|
|
adj = subg.adjacency_matrix(R3, True, F.cpu())[0]
|
|
assert np.allclose(F.sparse_to_numpy(adj),
|
|
np.array([[0., 1.],
|
|
[0., 1.],
|
|
[0., 1.]]))
|
|
assert len(sub.induced_nodes) == 3
|
|
assert _array_equal(sub.induced_nodes[0], [0, 1, 2, 3, 4])
|
|
assert _array_equal(sub.induced_nodes[1], [0, 1])
|
|
assert _array_equal(sub.induced_nodes[2], [0, 1, 2])
|
|
assert len(sub.induced_edges) == 3
|
|
assert _array_equal(sub.induced_edges[0], induced_edges[0])
|
|
assert _array_equal(sub.induced_edges[1], induced_edges[1])
|
|
assert _array_equal(sub.induced_edges[2], induced_edges[2])
|
|
|
|
# edge subgraph with empty induced edges (preserve_nodes=False)
|
|
induced_edges = [toindex([0, 2]), toindex([]), toindex([0, 1, 2])]
|
|
sub = g.edge_subgraph(induced_edges, False)
|
|
subg = sub.graph
|
|
assert subg.number_of_ntypes() == 3
|
|
assert subg.number_of_etypes() == 3
|
|
assert subg.number_of_nodes(0) == 2
|
|
assert subg.number_of_nodes(1) == 2
|
|
assert subg.number_of_nodes(2) == 3
|
|
assert subg.number_of_edges(R1) == 2
|
|
assert subg.number_of_edges(R2) == 0
|
|
assert subg.number_of_edges(R3) == 3
|
|
adj = subg.adjacency_matrix(R1, True, F.cpu())[0]
|
|
assert np.allclose(F.sparse_to_numpy(adj),
|
|
np.array([[1., 0.],
|
|
[1., 0.]]))
|
|
adj = subg.adjacency_matrix(R2, True, F.cpu())[0]
|
|
assert np.allclose(F.sparse_to_numpy(adj),
|
|
np.array([[0., 0., 0.],
|
|
[0., 0., 0.]]))
|
|
adj = subg.adjacency_matrix(R3, True, F.cpu())[0]
|
|
assert np.allclose(F.sparse_to_numpy(adj),
|
|
np.array([[0., 1.],
|
|
[0., 1.],
|
|
[0., 1.]]))
|
|
assert len(sub.induced_nodes) == 3
|
|
assert _array_equal(sub.induced_nodes[0], [0, 2])
|
|
assert _array_equal(sub.induced_nodes[1], [0, 1])
|
|
assert _array_equal(sub.induced_nodes[2], [0, 1, 2])
|
|
assert len(sub.induced_edges) == 3
|
|
assert _array_equal(sub.induced_edges[0], induced_edges[0])
|
|
assert _array_equal(sub.induced_edges[1], induced_edges[1])
|
|
assert _array_equal(sub.induced_edges[2], induced_edges[2])
|
|
|
|
# edge subgraph with empty induced edges (preserve_nodes=True)
|
|
induced_edges = [toindex([0, 2]), toindex([]), toindex([0, 1, 2])]
|
|
sub = g.edge_subgraph(induced_edges, True)
|
|
subg = sub.graph
|
|
assert subg.number_of_ntypes() == 3
|
|
assert subg.number_of_etypes() == 3
|
|
assert subg.number_of_nodes(0) == 5
|
|
assert subg.number_of_nodes(1) == 2
|
|
assert subg.number_of_nodes(2) == 3
|
|
assert subg.number_of_edges(R1) == 2
|
|
assert subg.number_of_edges(R2) == 0
|
|
assert subg.number_of_edges(R3) == 3
|
|
adj = subg.adjacency_matrix(R1, True, F.cpu())[0]
|
|
assert np.allclose(F.sparse_to_numpy(adj),
|
|
np.array([[1., 0.],
|
|
[0., 0.],
|
|
[1., 0.],
|
|
[0., 0.],
|
|
[0., 0.]]))
|
|
adj = subg.adjacency_matrix(R2, True, F.cpu())[0]
|
|
assert np.allclose(F.sparse_to_numpy(adj),
|
|
np.array([[0., 0., 0.],
|
|
[0., 0., 0.]]))
|
|
adj = subg.adjacency_matrix(R3, True, F.cpu())[0]
|
|
assert np.allclose(F.sparse_to_numpy(adj),
|
|
np.array([[0., 1.],
|
|
[0., 1.],
|
|
[0., 1.]]))
|
|
assert len(sub.induced_nodes) == 3
|
|
assert _array_equal(sub.induced_nodes[0], [0, 1, 2, 3, 4])
|
|
assert _array_equal(sub.induced_nodes[1], [0, 1])
|
|
assert _array_equal(sub.induced_nodes[2], [0, 1, 2])
|
|
assert len(sub.induced_edges) == 3
|
|
assert _array_equal(sub.induced_edges[0], induced_edges[0])
|
|
assert _array_equal(sub.induced_edges[1], induced_edges[1])
|
|
assert _array_equal(sub.induced_edges[2], induced_edges[2])
|
|
|
|
g = gen_from_coo()
|
|
_test_g(g)
|
|
g = gen_from_csr()
|
|
_test_g(g)
|
|
|
|
if __name__ == '__main__':
|
|
test_query()
|
|
test_subgraph()
|