test_permute.py 2.67 KB
Newer Older
rusty1s's avatar
tests  
rusty1s committed
1
2
3
4
5
import pytest
import torch
from torch_cluster.functions.utils.permute import sort, permute


rusty1s's avatar
rusty1s committed
6
7
8
9
10
11
12
13
14
15
16
17
def equal_neighbors(row, col, expected_col, degree):
    e, test = 0, True
    while e < len(row):
        i = row[e]
        neighbors = sorted(col[e:e + degree[i]])
        expected_neighbors = sorted(expected_col[e:e + degree[i]])
        if neighbors != expected_neighbors:
            test = False
        e += degree[i]
    return test


rusty1s's avatar
tests  
rusty1s committed
18
def test_sort_cpu():
rusty1s's avatar
rusty1s committed
19
20
21
22
23
24
25
    row = torch.LongTensor([0, 1, 0, 2, 1, 2, 1, 3, 2, 3])
    col = torch.LongTensor([1, 0, 2, 0, 2, 1, 3, 1, 3, 2])
    row, col = sort(row, col)
    expected_row = [0, 0, 1, 1, 1, 2, 2, 2, 3, 3]
    expected_col = [1, 2, 0, 2, 3, 0, 1, 3, 1, 2]
    assert row.tolist() == expected_row
    assert col.tolist() == expected_col
rusty1s's avatar
tests  
rusty1s committed
26
27
28


def test_permute_cpu():
rusty1s's avatar
rusty1s committed
29
30
    row = torch.LongTensor([0, 1, 0, 2, 1, 2, 1, 3, 2, 3])
    col = torch.LongTensor([1, 0, 2, 0, 2, 1, 3, 1, 3, 2])
rusty1s's avatar
tests  
rusty1s committed
31
32
    node_rid = torch.LongTensor([2, 1, 3, 0])
    edge_rid = torch.LongTensor([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
rusty1s's avatar
rusty1s committed
33
34
35
36
37
    row, col = permute(row, col, 4, node_rid, edge_rid)
    expected_row = [3, 3, 1, 1, 1, 0, 0, 2, 2, 2]
    expected_col = [1, 2, 0, 2, 3, 1, 2, 0, 1, 3]
    assert row.tolist() == expected_row
    assert col.tolist() == expected_col
rusty1s's avatar
tests  
rusty1s committed
38
39
40
41


@pytest.mark.skipif(not torch.cuda.is_available(), reason='no CUDA')
def test_sort_gpu():  # pragma: no cover
rusty1s's avatar
rusty1s committed
42
43
    # Note that `sort` is not stable on the GPU, so it does not preserve the
    # relative ordering of equivalent row elements. Thus, the expected column
rusty1s's avatar
rusty1s committed
44
    # vector differs from the CPU version.
rusty1s's avatar
rusty1s committed
45
46
47
    row = torch.cuda.LongTensor([0, 1, 0, 2, 1, 2, 1, 3, 2, 3])
    col = torch.cuda.LongTensor([1, 0, 2, 0, 2, 1, 3, 1, 3, 2])
    row, col = sort(row, col)
rusty1s's avatar
rusty1s committed
48
    row, col = row.cpu().tolist(), col.cpu().tolist()
rusty1s's avatar
tests  
rusty1s committed
49
    expected_row = [0, 0, 1, 1, 1, 2, 2, 2, 3, 3]
rusty1s's avatar
rusty1s committed
50
    expected_col = [1, 2, 0, 2, 3, 0, 1, 3, 1, 2]
rusty1s's avatar
rusty1s committed
51
52
    assert row == expected_row
    assert equal_neighbors(row, col, expected_col, [2, 3, 3, 2])
rusty1s's avatar
tests  
rusty1s committed
53
54
55
56


@pytest.mark.skipif(not torch.cuda.is_available(), reason='no CUDA')
def test_permute_gpu():  # pragma: no cover
rusty1s's avatar
rusty1s committed
57
    # Equivalent to `sort`, `permute` is not stable on the GPU (see above).
rusty1s's avatar
rusty1s committed
58
59
    row = torch.cuda.LongTensor([0, 1, 0, 2, 1, 2, 1, 3, 2, 3])
    col = torch.cuda.LongTensor([1, 0, 2, 0, 2, 1, 3, 1, 3, 2])
rusty1s's avatar
tests  
rusty1s committed
60
    node_rid = torch.cuda.LongTensor([2, 1, 3, 0])
rusty1s's avatar
rusty1s committed
61
62
    edge_rid = torch.cuda.LongTensor([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
    row, col = permute(row, col, 4, node_rid, edge_rid)
rusty1s's avatar
rusty1s committed
63
    row, col = row.cpu().tolist(), col.cpu().tolist()
rusty1s's avatar
tests  
rusty1s committed
64
    expected_row = [3, 3, 1, 1, 1, 0, 0, 2, 2, 2]
rusty1s's avatar
rusty1s committed
65
    expected_col = [1, 2, 0, 2, 3, 1, 2, 0, 1, 3]
rusty1s's avatar
rusty1s committed
66
67
    assert row == expected_row
    assert equal_neighbors(row, col, expected_col, [2, 3, 3, 2])