test_readout.py 7.47 KB
Newer Older
1
2
import unittest

3
import backend as F
4
5

import dgl
6
import networkx as nx
7
import numpy as np
8
import pytest
nv-dlasalle's avatar
nv-dlasalle committed
9
from test_utils import parametrize_idtype
10
11
from test_utils.graph_cases import get_cases

12

nv-dlasalle's avatar
nv-dlasalle committed
13
@parametrize_idtype
14
15
16
17
def test_sum_case1(idtype):
    # NOTE: If you want to update this test case, remember to update the docstring
    #  example too!!!
    g1 = dgl.graph(([0, 1], [1, 0]), idtype=idtype, device=F.ctx())
18
    g1.ndata["h"] = F.tensor([1.0, 2.0])
19
    g2 = dgl.graph(([0, 1], [1, 2]), idtype=idtype, device=F.ctx())
20
    g2.ndata["h"] = F.tensor([1.0, 2.0, 3.0])
21
    bg = dgl.batch([g1, g2])
22
23
24
25
26
    bg.ndata["w"] = F.tensor([0.1, 0.2, 0.1, 0.5, 0.2])
    assert F.allclose(F.tensor([3.0]), dgl.sum_nodes(g1, "h"))
    assert F.allclose(F.tensor([3.0, 6.0]), dgl.sum_nodes(bg, "h"))
    assert F.allclose(F.tensor([0.5, 1.7]), dgl.sum_nodes(bg, "h", "w"))

27

nv-dlasalle's avatar
nv-dlasalle committed
28
@parametrize_idtype
29
30
@pytest.mark.parametrize("g", get_cases(["homo"], exclude=["dglgraph"]))
@pytest.mark.parametrize("reducer", ["sum", "max", "mean"])
31
32
def test_reduce_readout(g, idtype, reducer):
    g = g.astype(idtype).to(F.ctx())
33
34
    g.ndata["h"] = F.randn((g.number_of_nodes(), 3))
    g.edata["h"] = F.randn((g.number_of_edges(), 2))
35
36

    # Test.1: node readout
37
    x = dgl.readout_nodes(g, "h", op=reducer)
38
39
40
41
    # check correctness
    subg = dgl.unbatch(g)
    subx = []
    for sg in subg:
42
        sx = dgl.readout_nodes(sg, "h", op=reducer)
43
44
45
        subx.append(sx)
    assert F.allclose(x, F.cat(subx, dim=0))

46
    x = getattr(dgl, "{}_nodes".format(reducer))(g, "h")
47
48
49
50
    # check correctness
    subg = dgl.unbatch(g)
    subx = []
    for sg in subg:
51
        sx = getattr(dgl, "{}_nodes".format(reducer))(sg, "h")
52
53
54
55
        subx.append(sx)
    assert F.allclose(x, F.cat(subx, dim=0))

    # Test.2: edge readout
56
    x = dgl.readout_edges(g, "h", op=reducer)
57
58
59
60
    # check correctness
    subg = dgl.unbatch(g)
    subx = []
    for sg in subg:
61
        sx = dgl.readout_edges(sg, "h", op=reducer)
62
63
64
        subx.append(sx)
    assert F.allclose(x, F.cat(subx, dim=0))

65
    x = getattr(dgl, "{}_edges".format(reducer))(g, "h")
66
67
68
69
    # check correctness
    subg = dgl.unbatch(g)
    subx = []
    for sg in subg:
70
        sx = getattr(dgl, "{}_edges".format(reducer))(sg, "h")
71
72
73
        subx.append(sx)
    assert F.allclose(x, F.cat(subx, dim=0))

74

nv-dlasalle's avatar
nv-dlasalle committed
75
@parametrize_idtype
76
77
@pytest.mark.parametrize("g", get_cases(["homo"], exclude=["dglgraph"]))
@pytest.mark.parametrize("reducer", ["sum", "max", "mean"])
78
79
def test_weighted_reduce_readout(g, idtype, reducer):
    g = g.astype(idtype).to(F.ctx())
80
81
82
83
    g.ndata["h"] = F.randn((g.number_of_nodes(), 3))
    g.ndata["w"] = F.randn((g.number_of_nodes(), 1))
    g.edata["h"] = F.randn((g.number_of_edges(), 2))
    g.edata["w"] = F.randn((g.number_of_edges(), 1))
84
85

    # Test.1: node readout
86
    x = dgl.readout_nodes(g, "h", "w", op=reducer)
87
88
89
90
    # check correctness
    subg = dgl.unbatch(g)
    subx = []
    for sg in subg:
91
        sx = dgl.readout_nodes(sg, "h", "w", op=reducer)
92
93
94
        subx.append(sx)
    assert F.allclose(x, F.cat(subx, dim=0))

95
    x = getattr(dgl, "{}_nodes".format(reducer))(g, "h", "w")
96
97
98
99
    # check correctness
    subg = dgl.unbatch(g)
    subx = []
    for sg in subg:
100
        sx = getattr(dgl, "{}_nodes".format(reducer))(sg, "h", "w")
101
102
103
104
        subx.append(sx)
    assert F.allclose(x, F.cat(subx, dim=0))

    # Test.2: edge readout
105
    x = dgl.readout_edges(g, "h", "w", op=reducer)
106
107
108
109
    # check correctness
    subg = dgl.unbatch(g)
    subx = []
    for sg in subg:
110
        sx = dgl.readout_edges(sg, "h", "w", op=reducer)
111
112
113
        subx.append(sx)
    assert F.allclose(x, F.cat(subx, dim=0))

114
    x = getattr(dgl, "{}_edges".format(reducer))(g, "h", "w")
115
116
117
118
    # check correctness
    subg = dgl.unbatch(g)
    subx = []
    for sg in subg:
119
        sx = getattr(dgl, "{}_edges".format(reducer))(sg, "h", "w")
120
121
122
        subx.append(sx)
    assert F.allclose(x, F.cat(subx, dim=0))

123

nv-dlasalle's avatar
nv-dlasalle committed
124
@parametrize_idtype
125
126
@pytest.mark.parametrize("g", get_cases(["homo"], exclude=["dglgraph"]))
@pytest.mark.parametrize("descending", [True, False])
127
128
def test_topk(g, idtype, descending):
    g = g.astype(idtype).to(F.ctx())
129
    g.ndata["x"] = F.randn((g.number_of_nodes(), 3))
130
131

    # Test.1: to test the case where k > number of nodes.
132
    dgl.topk_nodes(g, "x", 100, sortby=-1)
133
134
135
136
137
138

    # Test.2: test correctness
    min_nnodes = F.asnumpy(g.batch_num_nodes()).min()
    if min_nnodes <= 1:
        return
    k = min_nnodes - 1
139
    val, indices = dgl.topk_nodes(g, "x", k, descending=descending, sortby=-1)
140
    print(k)
141
142
143
    print(g.ndata["x"])
    print("val", val)
    print("indices", indices)
144
145
146
    subg = dgl.unbatch(g)
    subval, subidx = [], []
    for sg in subg:
147
148
        subx = F.asnumpy(sg.ndata["x"])
        ai = np.argsort(subx[:, -1:].flatten())
149
150
151
152
153
154
155
156
157
158
        if descending:
            ai = np.ascontiguousarray(ai[::-1])
        subx = np.expand_dims(subx[ai[:k]], 0)
        subval.append(F.tensor(subx))
        subidx.append(F.tensor(np.expand_dims(ai[:k], 0)))
    print(F.cat(subval, dim=0))
    assert F.allclose(val, F.cat(subval, dim=0))
    assert F.allclose(indices, F.cat(subidx, dim=0))

    # Test.3: sorby=None
159
    dgl.topk_nodes(g, "x", k, sortby=None)
160

161
    g.edata["x"] = F.randn((g.number_of_edges(), 3))
162
163

    # Test.4: topk edges where k > number of edges.
164
    dgl.topk_edges(g, "x", 100, sortby=-1)
165
166
167
168
169
170

    # Test.5: topk edges test correctness
    min_nedges = F.asnumpy(g.batch_num_edges()).min()
    if min_nedges <= 1:
        return
    k = min_nedges - 1
171
    val, indices = dgl.topk_edges(g, "x", k, descending=descending, sortby=-1)
172
    print(k)
173
174
175
    print(g.edata["x"])
    print("val", val)
    print("indices", indices)
176
177
178
    subg = dgl.unbatch(g)
    subval, subidx = [], []
    for sg in subg:
179
180
        subx = F.asnumpy(sg.edata["x"])
        ai = np.argsort(subx[:, -1:].flatten())
181
182
183
184
185
186
187
188
189
        if descending:
            ai = np.ascontiguousarray(ai[::-1])
        subx = np.expand_dims(subx[ai[:k]], 0)
        subval.append(F.tensor(subx))
        subidx.append(F.tensor(np.expand_dims(ai[:k], 0)))
    print(F.cat(subval, dim=0))
    assert F.allclose(val, F.cat(subval, dim=0))
    assert F.allclose(indices, F.cat(subidx, dim=0))

190

nv-dlasalle's avatar
nv-dlasalle committed
191
@parametrize_idtype
192
@pytest.mark.parametrize("g", get_cases(["homo"], exclude=["dglgraph"]))
193
194
def test_softmax(g, idtype):
    g = g.astype(idtype).to(F.ctx())
195
196
    g.ndata["h"] = F.randn((g.number_of_nodes(), 3))
    g.edata["h"] = F.randn((g.number_of_edges(), 2))
197
198

    # Test.1: node readout
199
    x = dgl.softmax_nodes(g, "h")
200
201
202
    subg = dgl.unbatch(g)
    subx = []
    for sg in subg:
203
        subx.append(F.softmax(sg.ndata["h"], dim=0))
204
205
206
    assert F.allclose(x, F.cat(subx, dim=0))

    # Test.2: edge readout
207
    x = dgl.softmax_edges(g, "h")
208
209
210
    subg = dgl.unbatch(g)
    subx = []
    for sg in subg:
211
        subx.append(F.softmax(sg.edata["h"], dim=0))
212
213
    assert F.allclose(x, F.cat(subx, dim=0))

214

nv-dlasalle's avatar
nv-dlasalle committed
215
@parametrize_idtype
216
@pytest.mark.parametrize("g", get_cases(["homo"], exclude=["dglgraph"]))
217
218
219
220
221
def test_broadcast(idtype, g):
    g = g.astype(idtype).to(F.ctx())
    gfeat = F.randn((g.batch_size, 3))

    # Test.0: broadcast_nodes
222
    g.ndata["h"] = dgl.broadcast_nodes(g, gfeat)
223
224
    subg = dgl.unbatch(g)
    for i, sg in enumerate(subg):
225
226
227
228
        assert F.allclose(
            sg.ndata["h"],
            F.repeat(F.reshape(gfeat[i], (1, 3)), sg.number_of_nodes(), dim=0),
        )
229
230

    # Test.1: broadcast_edges
231
    g.edata["h"] = dgl.broadcast_edges(g, gfeat)
232
233
    subg = dgl.unbatch(g)
    for i, sg in enumerate(subg):
234
235
236
237
        assert F.allclose(
            sg.edata["h"],
            F.repeat(F.reshape(gfeat[i], (1, 3)), sg.number_of_edges(), dim=0),
        )