Completed
Branch master (5cc02c)
by Andrei
01:30
created

pyclustering.container.tests.Test.testKDTreeInsertRemoveNode1()   F

Complexity

Conditions 10

Size

Total Lines 25

Duplication

Lines 0
Ratio 0 %
Metric Value
cc 10
dl 0
loc 25
rs 3.1304

How to fix   Complexity   

Complexity

Complex classes like pyclustering.container.tests.Test.testKDTreeInsertRemoveNode1() often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

1
'''
2
3
Unit-tests for KD-Tree.
4
5
Copyright (C) 2015    Andrei Novikov ([email protected])
6
7
pyclustering is free software: you can redistribute it and/or modify
8
it under the terms of the GNU General Public License as published by
9
the Free Software Foundation, either version 3 of the License, or
10
(at your option) any later version.
11
12
pyclustering is distributed in the hope that it will be useful,
13
but WITHOUT ANY WARRANTY; without even the implied warranty of
14
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15
GNU General Public License for more details.
16
17
You should have received a copy of the GNU General Public License
18
along with this program.  If not, see <http://www.gnu.org/licenses/>.
19
20
'''
21
22
import unittest;
23
import itertools;
24
25
from pyclustering.container.kdtree import kdtree;
26
27
class Test(unittest.TestCase):
28
    def testKDTreeCreateWithoutPayload(self):
29
        # Create k-d tree without any payload
30
        array = [ [4, 3], [3, 4], [5, 8], [3, 3], [3, 9], [6, 4], [5, 9] ];
31
        tree = kdtree(array);
32
        
33
        assert len(tree.traverse()) == len(array);
34
        for item in array:
35
            node = tree.find_node(item);
36
            
37
            assert node != None;            # node should exist in the tree.
38
            assert node.payload == None;    # because we have created tree without any payloads.
39
            assert node.data == item;       # check for valid data.
40
    
41
    
42
    def testKDTreeCreateWithPayload(self):
43
        # Create k-d tree with payload
44
        array = [ [4, 3], [3, 4], [5, 8], [3, 3], [3, 9], [6, 4], [5, 9] ];
45
        payload = ['q', 'w', 'e', 'r', 't', 'y', 'u'];
46
        
47
        tree = kdtree(array, payload);
48
        assert len(tree.traverse()) == len(array);
49
        for index in range(len(array)):
50
            node = tree.find_node(array[index]);
51
            
52
            assert node != None;
53
            assert node.payload == payload[index];
54
            assert node.data == array[index];
55
56
57
    def testKDTreeCreateTrivial(self):
58
        "Create k-d tree"
59
        array = [ [3, 4], [5, 6], [9, 8], [7, 3], [1, 2], [2, 4], [2, 5], [3, 2] ];
60
        tree = kdtree(array);
61
        
62
        assert len(tree.traverse()) == len(array);
63
        for item in array:
64
            assert tree.find_node(item).data == item;
65
    
66
    
67
    def testKDTreeInsertNodes(self):
68
        "Create empty k-d tree and insert nodes"
69
        array = [ [4, 3], [3, 4], [5, 8], [3, 3], [3, 9], [6, 4], [5, 9] ];
70
        payload = ['q', 'w', 'e', 'r', 't', 'y', 'u'];
71
        
72
        tree = kdtree();
73
        assert len(tree.traverse()) == 0;
74
        for index in range(len(array)):
75
            node = tree.insert(array[index], payload[index]);
76
            
77
            assert len(tree.traverse()) == index + 1;
78
                        
79
            assert node != None;
80
            assert node.payload == payload[index];
81
            assert node.data == array[index];
82
            
83
    
84
    def testKDTreeParentSearch(self):
85
        "Check for right parents"
86
        array = [ [4, 3], [3, 4], [5, 8], [3, 3], [3, 9], [6, 4], [5, 9] ];
87
        tree = kdtree(array);
88
        
89
        node = tree.find_node([4, 3]);
90
        assert node.parent == None;
91
        
92
        node = tree.find_node([3, 4]);
93
        assert node.parent.data == [4, 3];
94
        
95
        node = tree.find_node([5, 8]);
96
        assert node.parent.data == [4, 3];
97
    
98
        node = tree.find_node([6, 4]);
99
        assert node.parent.data == [5, 8];
100
        
101
        node = tree.find_node([3, 3]);
102
        assert node.parent.data == [3, 4];
103
        
104
        node = tree.find_node([5, 9]);
105
        assert node.parent.data == [5, 8];
106
        
107
        node = tree.find_node([3, 9]);
108
        assert node.parent.data == [3, 4];
109
    
110
    
111
    def testKDTreeInsertRemoveNode1(self):
112
        "Create empty k-d tree and insert nodes and after that remove all nodes"
113
        array = [ [4, 3], [3, 4], [5, 8], [3, 3], [3, 9], [6, 4], [5, 9] ];
114
        payload = ['q', 'w', 'e', 'r', 't', 'y', 'u'];
115
        
116
        tree = kdtree();
117
        for index in range(len(array)):
118
            node = tree.insert(array[index], payload[index]);
119
        
120
        length = len(array);
121
        for index in range(0, length):
122
            node = tree.remove(array[index]);
123
            assert len(tree.traverse()) == length - index - 1;
124
            
125
            if (index + 1 < length):    # When root is removed then None will be returned
126
                assert node != None;
127
            else:
128
                assert node == None;
129
130
            # Check other nodes are located in the tree
131
            for k in range(index + 1, length):
132
                node = tree.find_node(array[k]);
133
                
134
                assert node.data == array[k];
135
                assert node.payload == payload[k];
136
                
137
    
138
    def testKDTreeInsertRemoveNode2(self):
139
        # This test simulates situation when a bug (16.01.2014) with removing was occuring
140
        array = [ [9, 9], [3, 3], [4, 4] ];
141
        tree = kdtree(array);
142
        
143
        assert None != tree.remove([9, 9]);
144
        assert len(tree.traverse()) == 2;
145
        
146
        assert None != tree.remove([4, 4]);
147
        assert len(tree.traverse()) == 1;
148
        
149
        assert None == tree.remove([3, 3]);
150
        assert len(tree.traverse()) == 0;
151
            
152
    
153
    def testKDTreeRemoveLongBranch(self):
154
        # Create only one branch - worth case and remove it
155
        array = [ [5, 5], [6, 5], [6, 6], [7, 6], [7, 7] ];
156
        tree = kdtree(array);    
157
        
158
        assert len(tree.traverse()) == len(array);
159
        #tree.show();
160
        
161
        for index in range(len(array)):
162
            node = tree.remove(array[index]);
163
            assert len(tree.traverse()) == len(array) - index - 1;
164
        
165
        # Remove from other end
166
        tree = kdtree(array);
167
        for index in range(len(array)):
168
            node = tree.remove(array[len(array) - index - 1]);
169
            assert len(tree.traverse()) == len(array) - index - 1;
170
    
171
    
172
    def testKDTreeNearestNodeTrivial1(self):
173
        array = [ [4, 3], [3, 4], [5, 8], [3, 3], [3, 9], [6, 4], [6, 9], [4, 9] ];
174
        tree = kdtree(array);
175
        
176
        for item in array:
177
            assert tree.find_nearest_dist_node(item, 0).data == item;
178
            assert tree.find_nearest_dist_node(item, 0.5).data == item;
179
            assert tree.find_nearest_dist_node(item, 1).data == item;
180
            assert tree.find_nearest_dist_node(item, 3).data == item;
181
            assert tree.find_nearest_dist_node(item, 10).data == item;
182
        
183
        assert tree.find_nearest_dist_node([6.1, 4.1], 0.5).data == [6, 4];
184
        assert tree.find_nearest_dist_node([6, 12], 0) == None;
185
        assert tree.find_nearest_dist_node([6, 12], 1) == None;
186
        assert tree.find_nearest_dist_node([6, 12], 3).data == [6, 9];
187
    
188
189
    def testKDTreeNearestNodeTrivial2(self):
190
        arrays = [ 
191
                    [ [3, 4], [5, 6], [9, 8], [7, 3], [1, 2], [2, 4], [2, 5], [3, 2], [3, 3] ],
192
                    [ [5, 6], [1, 3], [7, 3], [1, 1], [9, 9], [4, 7], [0, 3], [3, 5], [1, 2], [9, 3], [9, 8], [5, 5], [6, 6], [0, 0], [-4, -5], [-1, 5], [-8, 3] ] 
193
                 ];
194
                 
195
        distances = [0.0, 0.5, 1.0, 3.0, 10.0];
196
        
197
        for array in arrays:
198
            tree = kdtree(array);
199
            
200
            for item in array:
201
                for distance in distances:
202
                    assert tree.find_nearest_dist_node(item, distance).data == item;
203
    
204
    # Verification test, so it is required too much time for testing.
205
    #def testVerificationKdTree1(self):
206
    #    array = [ [5, 5], [4, 5], [4, 4], [3, 4], [3, 3], [6, 6], [8, 8], [7, 7], [9, 9]];
207
    #    self.template_verification_insert_remove_kdtree_test(array);
208
                    
209
    def templateVerificationInsertRemoveKDTreeTest(self, array):
210
        for perm_array in itertools.permutations(array):
211
            tree = kdtree(array);
212
            length = len(array);
213
            
214
            for index in range(len(perm_array)):
215
                #tree.show();
216
                
217
                node = tree.remove(perm_array[index]);
218
219
                if ( index + 1 < length ):
220
                    assert node is not None;
221
                    
222
                assert len(tree.traverse()) == length - index - 1;
223
224
225
if __name__ == "__main__":
226
    unittest.main();