Beispiel #1
0
def test_dynamic_addition():
    N = 3
    D = 1

    g = DGLGraph()

    def _init(shape, dtype, ctx, ids):
        return F.copy_to(F.astype(F.randn(shape), dtype), ctx)

    g.set_n_initializer(_init)
    g.set_e_initializer(_init)

    def _message(edges):
        return {
            'm':
            edges.src['h1'] + edges.dst['h2'] + edges.data['h1'] +
            edges.data['h2']
        }

    def _reduce(nodes):
        return {'h': F.sum(nodes.mailbox['m'], 1)}

    def _apply(nodes):
        return {'h': nodes.data['h']}

    g.register_message_func(_message)
    g.register_reduce_func(_reduce)
    g.register_apply_node_func(_apply)
    g.set_n_initializer(dgl.init.zero_initializer)
    g.set_e_initializer(dgl.init.zero_initializer)

    # add nodes and edges
    g.add_nodes(N)
    g.ndata.update({'h1': F.randn((N, D)), 'h2': F.randn((N, D))})
    g.add_nodes(3)
    g.add_edge(0, 1)
    g.add_edge(1, 0)
    g.edata.update({'h1': F.randn((2, D)), 'h2': F.randn((2, D))})
    g.send()
    expected = F.copy_to(F.ones((g.number_of_edges(), ), dtype=F.int64),
                         F.cpu())
    assert F.array_equal(g._get_msg_index().tousertensor(), expected)

    # add more edges
    g.add_edges([0, 2], [2, 0], {'h1': F.randn((2, D))})
    g.send(([0, 2], [2, 0]))
    g.recv(0)

    g.add_edge(1, 2)
    g.edges[4].data['h1'] = F.randn((1, D))
    g.send((1, 2))
    g.recv([1, 2])

    h = g.ndata.pop('h')

    # a complete round of send and recv
    g.send()
    g.recv()
    assert F.allclose(h, g.ndata['h'])
Beispiel #2
0
def test_nx_conversion():
    # check conversion between networkx and DGLGraph

    def _check_nx_feature(nxg, nf, ef):
        # check node and edge feature of nxg
        # this is used to check to_networkx
        num_nodes = len(nxg)
        num_edges = nxg.size()
        if num_nodes > 0:
            node_feat = ddict(list)
            for nid, attr in nxg.nodes(data=True):
                assert len(attr) == len(nf)
                for k in nxg.nodes[nid]:
                    node_feat[k].append(attr[k].unsqueeze(0))
            for k in node_feat:
                feat = th.cat(node_feat[k], dim=0)
                assert U.allclose(feat, nf[k])
        else:
            assert len(nf) == 0
        if num_edges > 0:
            edge_feat = ddict(lambda: [0] * num_edges)
            for u, v, attr in nxg.edges(data=True):
                assert len(attr) == len(ef) + 1  # extra id
                eid = attr['id']
                for k in ef:
                    edge_feat[k][eid] = attr[k].unsqueeze(0)
            for k in edge_feat:
                feat = th.cat(edge_feat[k], dim=0)
                assert U.allclose(feat, ef[k])
        else:
            assert len(ef) == 0

    n1 = th.randn(5, 3)
    n2 = th.randn(5, 10)
    n3 = th.randn(5, 4)
    e1 = th.randn(4, 5)
    e2 = th.randn(4, 7)
    g = DGLGraph(multigraph=True)
    g.add_nodes(5)
    g.add_edges([0, 1, 3, 4], [2, 4, 0, 3])
    g.ndata.update({'n1': n1, 'n2': n2, 'n3': n3})
    g.edata.update({'e1': e1, 'e2': e2})

    # convert to networkx
    nxg = g.to_networkx(node_attrs=['n1', 'n3'], edge_attrs=['e1', 'e2'])
    assert len(nxg) == 5
    assert nxg.size() == 4
    _check_nx_feature(nxg, {'n1': n1, 'n3': n3}, {'e1': e1, 'e2': e2})

    # convert to DGLGraph, nx graph has id in edge feature
    # use id feature to test non-tensor copy
    g.from_networkx(nxg, node_attrs=['n1'], edge_attrs=['e1', 'id'])
    # check graph size
    assert g.number_of_nodes() == 5
    assert g.number_of_edges() == 4
    # check number of features
    # test with existing dglgraph (so existing features should be cleared)
    assert len(g.ndata) == 1
    assert len(g.edata) == 2
    # check feature values
    assert U.allclose(g.ndata['n1'], n1)
    # with id in nx edge feature, e1 should follow original order
    assert U.allclose(g.edata['e1'], e1)
    assert th.equal(g.get_e_repr()['id'], th.arange(4))

    # test conversion after modifying DGLGraph
    g.pop_e_repr(
        'id')  # pop id so we don't need to provide id when adding edges
    new_n = th.randn(2, 3)
    new_e = th.randn(3, 5)
    g.add_nodes(2, data={'n1': new_n})
    # add three edges, one is a multi-edge
    g.add_edges([3, 6, 0], [4, 5, 2], data={'e1': new_e})
    n1 = th.cat((n1, new_n), dim=0)
    e1 = th.cat((e1, new_e), dim=0)
    # convert to networkx again
    nxg = g.to_networkx(node_attrs=['n1'], edge_attrs=['e1'])
    assert len(nxg) == 7
    assert nxg.size() == 7
    _check_nx_feature(nxg, {'n1': n1}, {'e1': e1})

    # now test convert from networkx without id in edge feature
    # first pop id in edge feature
    for _, _, attr in nxg.edges(data=True):
        attr.pop('id')
    # test with a new graph
    g = DGLGraph(multigraph=True)
    g.from_networkx(nxg, node_attrs=['n1'], edge_attrs=['e1'])
    # check graph size
    assert g.number_of_nodes() == 7
    assert g.number_of_edges() == 7
    # check number of features
    assert len(g.ndata) == 1
    assert len(g.edata) == 1
    # check feature values
    assert U.allclose(g.ndata['n1'], n1)
    # edge feature order follows nxg.edges()
    edge_feat = []
    for _, _, attr in nxg.edges(data=True):
        edge_feat.append(attr['e1'].unsqueeze(0))
    edge_feat = th.cat(edge_feat, dim=0)
    assert U.allclose(g.edata['e1'], edge_feat)
Beispiel #3
0
def test_nx_conversion():
    # check conversion between networkx and DGLGraph

    def _check_nx_feature(nxg, nf, ef):
        num_nodes = len(nxg)
        num_edges = nxg.size()
        if num_nodes > 0:
            node_feat = ddict(list)
            for nid, attr in nxg.nodes(data=True):
                assert len(attr) == len(nf)
                for k in nxg.nodes[nid]:
                    node_feat[k].append(attr[k].unsqueeze(0))
            for k in node_feat:
                feat = th.cat(node_feat[k], dim=0)
                assert U.allclose(feat, nf[k])
        else:
            assert len(nf) == 0
        if num_edges > 0:
            edge_feat = ddict(lambda: [0] * num_edges)
            for u, v, attr in nxg.edges(data=True):
                assert len(attr) == len(ef) + 1  # extra id
                eid = attr['id']
                for k in ef:
                    edge_feat[k][eid] = attr[k].unsqueeze(0)
            for k in edge_feat:
                feat = th.cat(edge_feat[k], dim=0)
                assert U.allclose(feat, ef[k])
        else:
            assert len(ef) == 0

    n1 = th.randn(5, 3)
    n2 = th.randn(5, 10)
    n3 = th.randn(5, 4)
    e1 = th.randn(4, 5)
    e2 = th.randn(4, 7)
    g = DGLGraph(multigraph=True)
    g.add_nodes(5)
    g.add_edges([0, 1, 3, 4], [2, 4, 0, 3])
    g.ndata.update({'n1': n1, 'n2': n2, 'n3': n3})
    g.edata.update({'e1': e1, 'e2': e2})

    # convert to networkx
    nxg = g.to_networkx(node_attrs=['n1', 'n3'], edge_attrs=['e1', 'e2'])
    assert len(nxg) == 5
    assert nxg.size() == 4
    _check_nx_feature(nxg, {'n1': n1, 'n3': n3}, {'e1': e1, 'e2': e2})

    # convert to DGLGraph
    # use id feature to test non-tensor copy
    g.from_networkx(nxg, node_attrs=['n1'], edge_attrs=['e1', 'id'])
    assert g.number_of_nodes() == 5
    assert g.number_of_edges() == 4
    assert U.allclose(g.get_n_repr()['n1'], n1)
    assert U.allclose(g.get_e_repr()['e1'], e1)
    assert th.equal(g.get_e_repr()['id'], th.arange(4))

    g.pop_e_repr('id')

    # test modifying DGLGraph
    new_n = th.randn(2, 3)
    new_e = th.randn(3, 5)
    g.add_nodes(2, data={'n1': new_n})
    # add three edges, one is a multi-edge
    g.add_edges([3, 6, 0], [4, 5, 2], data={'e1': new_e})
    n1 = th.cat((n1, new_n), dim=0)
    e1 = th.cat((e1, new_e), dim=0)
    # convert to networkx again
    nxg = g.to_networkx(node_attrs=['n1'], edge_attrs=['e1'])
    assert len(nxg) == 7
    assert nxg.size() == 7
    _check_nx_feature(nxg, {'n1': n1}, {'e1': e1})