test_traversal.py 4.5 KB
Newer Older
GaiYu0's avatar
GaiYu0 committed
1
2
3
4
5
6
7
8
import random
import sys
import time

import dgl
import networkx as nx
import numpy as np
import scipy.sparse as sp
9
import backend as F
GaiYu0's avatar
GaiYu0 committed
10

Gan Quan's avatar
Gan Quan committed
11
import itertools
12
from utils import parametrize_dtype
Gan Quan's avatar
Gan Quan committed
13

GaiYu0's avatar
GaiYu0 committed
14
15
np.random.seed(42)

Gan Quan's avatar
Gan Quan committed
16
def toset(x):
VoVAllen's avatar
VoVAllen committed
17
    # F.zerocopy_to_numpy may return a int
18
    return set(F.zerocopy_to_numpy(x).tolist())
Gan Quan's avatar
Gan Quan committed
19

20
21
@parametrize_dtype
def test_bfs(index_dtype, n=100):
Minjie Wang's avatar
Minjie Wang committed
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
    def _bfs_nx(g_nx, src):
        edges = nx.bfs_edges(g_nx, src)
        layers_nx = [set([src])]
        edges_nx = []
        frontier = set()
        edge_frontier = set()
        for u, v in edges:
            if u in layers_nx[-1]:
                frontier.add(v)
                edge_frontier.add(g.edge_id(u, v))
            else:
                layers_nx.append(frontier)
                edges_nx.append(edge_frontier)
                frontier = set([v])
                edge_frontier = set([g.edge_id(u, v)])
37
38
39
40
        # avoids empty successors
        if len(frontier) > 0 and len(edge_frontier) > 0:
            layers_nx.append(frontier)
            edges_nx.append(edge_frontier)
Minjie Wang's avatar
Minjie Wang committed
41
        return layers_nx, edges_nx
GaiYu0's avatar
GaiYu0 committed
42

Minjie Wang's avatar
Minjie Wang committed
43
    g = dgl.DGLGraph()
44
    a = sp.random(n, n, 3 / n, data_rvs=lambda n: np.ones(n))
Minjie Wang's avatar
Minjie Wang committed
45
    g.from_scipy_sparse_matrix(a)
46
47
48
49
50
    if index_dtype == 'int32':
        g = dgl.graph(g.edges()).int()
    else:
        g = dgl.graph(g.edges()).long()

Minjie Wang's avatar
Minjie Wang committed
51
    g_nx = g.to_networkx()
GaiYu0's avatar
GaiYu0 committed
52
    src = random.choice(range(n))
Minjie Wang's avatar
Minjie Wang committed
53
    layers_nx, _ = _bfs_nx(g_nx, src)
54
    layers_dgl = dgl.bfs_nodes_generator(g, src)
GaiYu0's avatar
GaiYu0 committed
55
56
57
    assert len(layers_dgl) == len(layers_nx)
    assert all(toset(x) == y for x, y in zip(layers_dgl, layers_nx))

Minjie Wang's avatar
Minjie Wang committed
58
59
60
    g_nx = nx.random_tree(n, seed=42)
    g = dgl.DGLGraph()
    g.from_networkx(g_nx)
61
62
63
64
65
    if index_dtype == 'int32':
        g = dgl.graph(g.edges()).int()
    else:
        g = dgl.graph(g.edges()).long()

Minjie Wang's avatar
Minjie Wang committed
66
67
    src = 0
    _, edges_nx = _bfs_nx(g_nx, src)
Gan Quan's avatar
Gan Quan committed
68
69
70
71
    edges_dgl = dgl.bfs_edges_generator(g, src)
    assert len(edges_dgl) == len(edges_nx)
    assert all(toset(x) == y for x, y in zip(edges_dgl, edges_nx))

72
73
@parametrize_dtype
def test_topological_nodes(index_dtype, n=100):
GaiYu0's avatar
GaiYu0 committed
74
    g = dgl.DGLGraph()
75
    a = sp.random(n, n, 3 / n, data_rvs=lambda n: np.ones(n))
GaiYu0's avatar
GaiYu0 committed
76
77
    b = sp.tril(a, -1).tocoo()
    g.from_scipy_sparse_matrix(b)
78
79
80
81
    if index_dtype == 'int32':
        g = dgl.graph(g.edges()).int()
    else:
        g = dgl.graph(g.edges()).long()
GaiYu0's avatar
GaiYu0 committed
82
83
84
85
86
87

    layers_dgl = dgl.topological_nodes_generator(g)

    adjmat = g.adjacency_matrix()
    def tensor_topo_traverse():
        n = g.number_of_nodes()
88
        mask = F.copy_to(F.ones((n, 1)), F.cpu())
89
90
91
        degree = F.spmm(adjmat, mask)
        while F.reduce_sum(mask) != 0.:
            v = F.astype((degree == 0.), F.float32)
GaiYu0's avatar
GaiYu0 committed
92
93
            v = v * mask
            mask = mask - v
94
            frontier = F.copy_to(F.nonzero_1d(F.squeeze(v, 1)), F.cpu())
GaiYu0's avatar
GaiYu0 committed
95
            yield frontier
96
            degree -= F.spmm(adjmat, v)
GaiYu0's avatar
GaiYu0 committed
97
98
99
100
101
102
103

    layers_spmv = list(tensor_topo_traverse())

    assert len(layers_dgl) == len(layers_spmv)
    assert all(toset(x) == toset(y) for x, y in zip(layers_dgl, layers_spmv))

DFS_LABEL_NAMES = ['forward', 'reverse', 'nontree']
104
105
@parametrize_dtype
def test_dfs_labeled_edges(index_dtype, example=False):
GaiYu0's avatar
GaiYu0 committed
106
    dgl_g = dgl.DGLGraph()
Gan Quan's avatar
Gan Quan committed
107
108
    dgl_g.add_nodes(6)
    dgl_g.add_edges([0, 1, 0, 3, 3], [1, 2, 2, 4, 5])
109
110
111
112
    if index_dtype == 'int32':
        dgl_g = dgl.graph(dgl_g.edges()).int()
    else:
        dgl_g = dgl.graph(dgl_g.edges()).long()
GaiYu0's avatar
GaiYu0 committed
113
    dgl_edges, dgl_labels = dgl.dfs_labeled_edges_generator(
Gan Quan's avatar
Gan Quan committed
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
            dgl_g, [0, 3], has_reverse_edge=True, has_nontree_edge=True)
    dgl_edges = [toset(t) for t in dgl_edges]
    dgl_labels = [toset(t) for t in dgl_labels]
    g1_solutions = [
            # edges           labels
            [[0, 1, 1, 0, 2], [0, 0, 1, 1, 2]],
            [[2, 2, 0, 1, 0], [0, 1, 0, 2, 1]],
    ]
    g2_solutions = [
            # edges        labels
            [[3, 3, 4, 4], [0, 1, 0, 1]],
            [[4, 4, 3, 3], [0, 1, 0, 1]],
    ]

    def combine_frontiers(sol):
        es, ls = zip(*sol)
        es = [set(i for i in t if i is not None)
              for t in itertools.zip_longest(*es)]
        ls = [set(i for i in t if i is not None)
              for t in itertools.zip_longest(*ls)]
        return es, ls

    for sol_set in itertools.product(g1_solutions, g2_solutions):
        es, ls = combine_frontiers(sol_set)
        if es == dgl_edges and ls == dgl_labels:
            break
    else:
        assert False

GaiYu0's avatar
GaiYu0 committed
143
if __name__ == '__main__':
144
145
146
    test_bfs(index_dtype='int32')
    test_topological_nodes(index_dtype='int32')
    test_dfs_labeled_edges(index_dtype='int32')