pyclustering  0.10.1
pyclustring is a Python, C++ data mining library.
kdtree.py
1 """!
2 
3 @brief Data Structure: KD-Tree
4 @details Implementation based on paper @cite book::the_design_and_analysis.
5 
6 @authors Andrei Novikov (pyclustering@yandex.ru)
7 @date 2014-2020
8 @copyright BSD-3-Clause
9 
10 """
11 
12 
13 import numpy
14 import matplotlib.pyplot as plt
15 
16 from pyclustering.utils import euclidean_distance_square, find_left_element
17 
18 
20  """!
21  @brief KD-tree visualizer that provides service to display graphical representation of the tree using
22  `matplotlib` library.
23  @details The visualizer is able to visualize 2D KD-trees only.
24 
25  There is an example how to visualize balanced KD-tree for `TwoDiamonds` sample using `kdtree_visualizer`:
26  @code
27  from pyclustering.container.kdtree import kdtree_balanced, kdtree_visualizer
28  from pyclustering.utils import read_sample
29  from pyclustering.samples.definitions import FCPS_SAMPLES
30 
31  sample = read_sample(FCPS_SAMPLES.SAMPLE_TWO_DIAMONDS)
32  tree_instance = kdtree_balanced(sample)
33 
34  kdtree_visualizer(tree_instance).visualize()
35  @endcode
36 
37  Output result of the example above (balanced tree) - figure 1:
38  @image html kd_tree_unbalanced_two_diamonds.png "Fig. 1. Balanced KD-tree for sample 'TwoDiamonds'."
39 
40  There is one more example to demonstrate unbalanced KD-tree. `kdtree` class is child class of `kdtree_balanced`
41  that allows to add points step by step and thus an unbalanced KD-tree can be built.
42  @code
43  from pyclustering.container.kdtree import kdtree, kdtree_visualizer
44  from pyclustering.utils import read_sample
45  from pyclustering.samples.definitions import FCPS_SAMPLES
46 
47  sample = read_sample(FCPS_SAMPLES.SAMPLE_TWO_DIAMONDS)
48  tree_instance = kdtree() # Do not use sample in constructor to avoid building of balanced tree.
49 
50  # Fill KD-tree step by step to obtain unbalanced tree.
51  for point in sample:
52  tree_instance.insert(point)
53 
54  kdtree_visualizer(tree_instance).visualize()
55  @endcode
56 
57  Output result of the example above (unbalanced tree) - figure 2:
58  @image html kd_tree_unbalanced_two_diamonds.png "Fig. 2. Unbalanced KD-tree for sample 'TwoDiamonds'."
59 
60  """
61 
62  def __init__(self, kdtree_instance):
63  """!
64  @brief Initialize KD-tree visualizer.
65 
66  @param[in] kdtree_instance (kdtree): Instance of a KD-tree that should be visualized.
67 
68  """
69  self.__tree = kdtree_instance
70  self.__colors = ['blue', 'red', 'green']
71  self.__verify()
72 
73  def visualize(self):
74  """!
75  @brief Visualize KD-tree using plot in 2-dimensional data-space.
76 
77  """
78  node = self.__tree.get_root()
79  min, max = self.__get_limits()
80 
81  figure = plt.figure(111)
82  ax = figure.add_subplot(111)
83 
84  self.__draw_node(ax, node, min, max)
85 
86  ax.set_xlim(min[0], max[0])
87  ax.set_ylim(min[1], max[1])
88  plt.show()
89 
90  def __draw_node(self, ax, node, min, max):
91  self.__draw_split_line(ax, node, min, max)
92 
93  if node.left is not None:
94  rborder = max[:]
95  rborder[node.disc] = node.data[node.disc]
96  self.__draw_node(ax, node.left, min, rborder)
97 
98  if node.right is not None:
99  lborder = min[:]
100  lborder[node.disc] = node.data[node.disc]
101  self.__draw_node(ax, node.right, lborder, max)
102 
103  def __draw_split_line(self, ax, node, min, max):
104  max_coord = max[:]
105  min_coord = min[:]
106 
107  dimension = len(min)
108  for d in range(dimension):
109  if d == node.disc:
110  max_coord[d] = node.data[d]
111  min_coord[d] = node.data[d]
112 
113  if dimension == 2:
114  ax.plot(node.data[0], node.data[1], color='black', marker='.', markersize=6)
115  ax.plot([min_coord[0], max_coord[0]], [min_coord[1], max_coord[1]], color=self.__colors[node.disc],
116  linestyle='-', linewidth=1)
117 
118  def __get_limits(self):
119  dimension = len(self.__tree.get_root().data)
120  nodes = self.__get_all_nodes()
121 
122  max, min = [float('-inf')] * dimension, [float('+inf')] * dimension
123 
124  for node in nodes:
125  for d in range(dimension):
126  if max[d] < node.data[d]:
127  max[d] = node.data[d]
128 
129  if min[d] > node.data[d]:
130  min[d] = node.data[d]
131 
132  return min, max
133 
134  def __get_all_nodes(self):
135  nodes = []
136 
137  next_level = [self.__tree.get_root()]
138 
139  while len(next_level) != 0:
140  cur_level = next_level
141  nodes += next_level
142  next_level = []
143 
144  for cur_node in cur_level:
145  children = cur_node.get_children()
146  if children is not None:
147  next_level += children
148 
149  return nodes
150 
151  def __verify(self):
152  root = self.__tree.get_root()
153  if root is None:
154  raise ValueError("KD-Tree is empty - nothing to visualize.")
155 
156  dimension = len(root.data)
157  if dimension != 2:
158  raise NotImplementedError("KD-Tree data has '%d' dimension - only KD-tree with 2D data can be visualized."
159  % dimension)
160 
161 
162 
163 class node:
164  """!
165  @brief Represents a node in a KD-Tree.
166  @details The KD-Tree node contains point's coordinates, discriminator, payload and pointers to parent and children.
167 
168  @see kdtree_balanced
169  @see kdtree
170 
171  """
172 
173  def __init__(self, data=None, payload=None, left=None, right=None, disc=None, parent=None):
174  """!
175  @brief Creates KD-tree node.
176 
177  @param[in] data (list): Data point that is presented as list of coordinates.
178  @param[in] payload (any): Payload of node (pointer to essence that is attached to this node).
179  @param[in] left (node): Node of KD-Tree that represents left successor.
180  @param[in] right (node): Node of KD-Tree that represents right successor.
181  @param[in] disc (uint): Index of dimension of that node.
182  @param[in] parent (node): Node of KD-Tree that represents parent.
183 
184  """
185 
186 
187  self.data = data
188 
189 
190  self.payload = payload
191 
192 
193  self.left = left
194 
195 
196  self.right = right
197 
198 
199  self.disc = disc
200 
201 
202  self.parent = parent
203 
204  def __repr__(self):
205  """!
206  @return (string) Default representation of the node.
207 
208  """
209  left = None
210  right = None
211 
212  if self.left is not None:
213  left = self.left.data
214 
215  if self.right is not None:
216  right = self.right.data
217 
218  return "(%s: [L:'%s', R:'%s'])" % (self.data, left, right)
219 
220  def __str__(self):
221  """!
222  @return (string) String representation of the node.
223 
224  """
225  return self.__repr__()
226 
227  def get_children(self):
228  """!
229  @brief Returns list of not `None` children of the node.
230 
231  @return (list) list of not `None` children of the node; if the node does not have children
232  then `None` is returned.
233 
234  """
235 
236  if self.left is not None:
237  yield self.left
238  if self.right is not None:
239  yield self.right
240 
241 
242 
244  """!
245  @brief Represents balanced static KD-tree that does not provide services to add and remove nodes after
246  initialization.
247  @details In the term KD tree, k denotes the dimensionality of the space being represented. Each data point is
248  represented as a node in the k-d tree in the form of a record of type node.
249 
250  There is an example how to create KD-tree:
251  @code
252  from pyclustering.container.kdtree import kdtree_balanced, kdtree_visualizer
253  from pyclustering.utils import read_sample
254  from pyclustering.samples.definitions import FCPS_SAMPLES
255 
256  sample = read_sample(FCPS_SAMPLES.SAMPLE_LSUN)
257  tree_instance = kdtree_balanced(sample)
258 
259  kdtree_visualizer(tree_instance).visualize()
260  @endcode
261 
262  Output result of the example above - figure 1.
263  @image html kd_tree_balanced_lsun.png "Fig. 1. Balanced KD-tree for sample 'Lsun'."
264 
265  @see kdtree
266 
267  """
268 
269  def __init__(self, points, payloads=None):
270  """!
271  @brief Initializes balanced static KD-tree.
272 
273  @param[in] points (array_like): Points that should be used to build KD-tree.
274  @param[in] payloads (array_like): Payload of each point in `points`.
275 
276  """
277 
278  if points is None:
279  self._length = 0
280  self._dimension = 0
281  self._point_comparator = None
282  self._root = None
283  return
284 
285  self._dimension = len(points[0])
286  self._point_comparator = self._create_point_comparator(type(points[0]))
287  self._length = 0
288 
289  nodes = []
290  for i in range(len(points)):
291  payload = None
292  if payloads is not None:
293  payload = payloads[i]
294 
295  nodes.append(node(points[i], payload, None, None, -1, None))
296 
297  self._root = self.__create_tree(nodes, None, 0)
298 
299  def __len__(self):
300  """!
301  @brief Returns amount of nodes in the KD-tree.
302 
303  @return (uint) Amount of nodes in the KD-tree.
304 
305  """
306  return self._length
307 
308  def get_root(self):
309  """!
310  @brief Returns root of the tree.
311 
312  @return (node) The root of the tree.
313 
314  """
315  return self._root
316 
317  def __create_tree(self, nodes, parent, depth):
318  """!
319  @brief Creates balanced sub-tree using elements from list `nodes`.
320 
321  @param[in] nodes (list): List of KD-tree nodes.
322  @param[in] parent (node): Parent node that is used as a root to build the sub-tree.
323  @param[in] depth (uint): Depth of the tree that where children of the `parent` should be placed.
324 
325  @return (node) Returns a node that is a root of the built sub-tree.
326 
327  """
328  if len(nodes) == 0:
329  return None
330 
331  discriminator = depth % self._dimension
332 
333  nodes.sort(key=lambda n: n.data[discriminator])
334  median = len(nodes) // 2
335 
336  # Elements could be the same around the median, but all elements that are >= to the current should
337  # be at the right side.
338  # TODO: optimize by binary search - no need to use O(n)
339  median = find_left_element(nodes, median, lambda n1, n2: n1.data[discriminator] < n2.data[discriminator])
340  # while median - 1 >= 0 and \
341  # nodes[median].data[discriminator] == nodes[median - 1].data[discriminator]:
342  # median -= 1
343 
344  new_node = nodes[median]
345  new_node.disc = discriminator
346  new_node.parent = parent
347  new_node.left = self.__create_tree(nodes[:median], new_node, depth + 1)
348  new_node.right = self.__create_tree(nodes[median + 1:], new_node, depth + 1)
349 
350  self._length += 1
351  return new_node
352 
353  def _create_point_comparator(self, type_point):
354  """!
355  @brief Create point comparator.
356  @details In case of numpy.array specific comparator is required.
357 
358  @param[in] type_point (data_type): Type of point that is stored in KD-node.
359 
360  @return (callable) Callable point comparator to compare to points.
361 
362  """
363  if type_point == numpy.ndarray:
364  return lambda obj1, obj2: numpy.array_equal(obj1, obj2)
365 
366  return lambda obj1, obj2: obj1 == obj2
367 
368  def _find_node_by_rule(self, point, search_rule, cur_node):
369  """!
370  @brief Search node that satisfy to parameters in search rule.
371  @details If node with specified parameters does not exist then None will be returned,
372  otherwise required node will be returned.
373 
374  @param[in] point (list): Coordinates of the point whose node should be found.
375  @param[in] search_rule (lambda): Rule that is called to check whether node satisfies to search parameter.
376  @param[in] cur_node (node): Node from which search should be started.
377 
378  @return (node) Node if it satisfies to input parameters, otherwise it return None.
379 
380  """
381 
382  if cur_node is None:
383  cur_node = self._root
384 
385  while cur_node:
386  if cur_node.data[cur_node.disc] <= point[cur_node.disc]:
387  # no need to check each node, only when it may satisfy the condition
388  if search_rule(cur_node): # compare point with point in the current node
389  return cur_node
390 
391  cur_node = cur_node.right
392  else:
393  cur_node = cur_node.left
394 
395  return None
396 
397  def find_node_with_payload(self, point, point_payload, cur_node=None):
398  """!
399  @brief Find node with specified coordinates and payload.
400  @details If node with specified parameters does not exist then None will be returned,
401  otherwise required node will be returned.
402 
403  @param[in] point (list): Coordinates of the point whose node should be found.
404  @param[in] point_payload (any): Payload of the node that is searched in the tree.
405  @param[in] cur_node (node): Node from which search should be started.
406 
407  @return (node) Node if it satisfies to input parameters, otherwise it return None.
408 
409  """
410 
411  rule_search = lambda node, point=point, payload=point_payload: self._point_comparator(node.data, point) and \
412  node.payload == payload
413  return self._find_node_by_rule(point, rule_search, cur_node)
414 
415  def find_node(self, point, cur_node=None):
416  """!
417  @brief Find node with coordinates that are defined by specified point.
418  @details If node with specified parameters does not exist then None will be returned,
419  otherwise required node will be returned.
420 
421  @param[in] point (list): Coordinates of the point whose node should be found.
422  @param[in] cur_node (node): Node from which search should be started.
423 
424  @return (node) Node if it satisfies to input parameters, otherwise it return None.
425 
426  """
427 
428  rule_search = lambda node, point=point: self._point_comparator(node.data, point)
429  return self._find_node_by_rule(point, rule_search, cur_node)
430 
431  def find_nearest_dist_node(self, point, distance, retdistance=False):
432  """!
433  @brief Find nearest neighbor in area with radius = distance.
434 
435  @param[in] point (list): Maximum distance where neighbors are searched.
436  @param[in] distance (double): Maximum distance where neighbors are searched.
437  @param[in] retdistance (bool): If True - returns neighbors with distances to them, otherwise only neighbors
438  is returned.
439 
440  @return (node|list) Nearest neighbor if 'retdistance' is False and list with two elements [node, distance]
441  if 'retdistance' is True, where the first element is pointer to node and the second element is
442  distance to it.
443 
444  """
445 
446  best_nodes = self.find_nearest_dist_nodes(point, distance)
447 
448  if len(best_nodes) == 0:
449  return None
450 
451  nearest = min(best_nodes, key=lambda item: item[0])
452 
453  if retdistance is True:
454  return nearest
455  else:
456  return nearest[1]
457 
458  def find_nearest_dist_nodes(self, point, distance):
459  """!
460  @brief Find neighbors that are located in area that is covered by specified distance.
461 
462  @param[in] point (list): Coordinates that is considered as centroid for searching.
463  @param[in] distance (double): Distance from the center where searching is performed.
464 
465  @return (list) Neighbors in area that is specified by point (center) and distance (radius).
466 
467  """
468 
469  best_nodes = []
470  if self._root is not None:
471  self.__recursive_nearest_nodes(point, distance, distance * distance, self._root, best_nodes)
472 
473  return best_nodes
474 
475  def __recursive_nearest_nodes(self, point, distance, sqrt_distance, node_head, best_nodes):
476  """!
477  @brief Returns list of neighbors such as tuple (distance, node) that is located in area that is covered by distance.
478 
479  @param[in] point (list): Coordinates that is considered as centroid for searching
480  @param[in] distance (double): Distance from the center where searching is performed.
481  @param[in] sqrt_distance (double): Square distance from the center where searching is performed.
482  @param[in] node_head (node): Node from that searching is performed.
483  @param[in|out] best_nodes (list): List of founded nodes.
484 
485  """
486 
487  if node_head.right is not None:
488  minimum = node_head.data[node_head.disc] - distance
489  if point[node_head.disc] >= minimum:
490  self.__recursive_nearest_nodes(point, distance, sqrt_distance, node_head.right, best_nodes)
491 
492  if node_head.left is not None:
493  maximum = node_head.data[node_head.disc] + distance
494  if point[node_head.disc] < maximum:
495  self.__recursive_nearest_nodes(point, distance, sqrt_distance, node_head.left, best_nodes)
496 
497  candidate_distance = euclidean_distance_square(point, node_head.data)
498  if candidate_distance <= sqrt_distance:
499  best_nodes.append((candidate_distance, node_head))
500 
501 
502 
504  """!
505  @brief Represents KD Tree that is a space-partitioning data structure for organizing points
506  in a k-dimensional space.
507  @details In the term k-d tree, k denotes the dimensionality of the space being represented. Each data point is
508  represented as a node in the k-d tree in the form of a record of type node. The tree supports
509  dynamic construction when nodes can be dynamically added and removed. As a result KD-tree might not be
510  balanced if methods `insert` and `remove` are used to built the tree. If the tree is built using
511  constructor where all points are passed to the tree then balanced tree is built. Single point search and
512  range-search procedures have complexity is `O(n)` in worse case in case of unbalanced tree.
513  If there is no need to build dynamic KD-tree, then it is much better to use static KD-tree
514  `kdtree_balanced`.
515 
516  There is an example how to use KD-tree to search nodes (points from input data) that are nearest to some point:
517  @code
518  # Import required modules
519  from pyclustering.samples.definitions import SIMPLE_SAMPLES;
520  from pyclustering.container.kdtree import kdtree;
521  from pyclustering.utils import read_sample;
522 
523  # Read data from text file
524  sample = read_sample(SIMPLE_SAMPLES.SAMPLE_SIMPLE3);
525 
526  # Create instance of KD-tree and initialize (fill) it by read data.
527  # In this case the tree is balanced.
528  tree_instance = kdtree(sample);
529 
530  # Search for nearest point
531  search_distance = 0.3;
532  nearest_node = tree_instance.find_nearest_dist_node([1.12, 4.31], search_distance);
533 
534  # Search for nearest point in radius 0.3
535  nearest_nodes = tree_instance.find_nearest_dist_nodes([1.12, 4.31], search_distance);
536  print("Nearest nodes:", nearest_nodes);
537  @endcode
538 
539  In case of building KD-tree using `insert` and `remove` method, the output KD-tree might be unbalanced - here
540  is an example that demonstrates this:
541  @code
542  from pyclustering.container.kdtree import kdtree, kdtree_visualizer
543  from pyclustering.utils import read_sample
544  from pyclustering.samples.definitions import FCPS_SAMPLES
545 
546  sample = read_sample(FCPS_SAMPLES.SAMPLE_TWO_DIAMONDS)
547 
548  # Build tree using constructor - balanced will be built because tree will know about all points.
549  tree_instance = kdtree(sample)
550  kdtree_visualizer(tree_instance).visualize()
551 
552  # Build tree using `insert` only - unbalanced tree will be built.
553  tree_instance = kdtree()
554  for point in sample:
555  tree_instance.insert(point)
556 
557  kdtree_visualizer(tree_instance).visualize()
558  @endcode
559 
560  There are two figures where difference between balanced and unbalanced KD-trees is demonstrated.
561 
562  @image html kd_tree_unbalanced_two_diamonds.png "Fig. 1. Balanced KD-tree for sample 'TwoDiamonds'."
563  @image html kd_tree_unbalanced_two_diamonds.png "Fig. 2. Unbalanced KD-tree for sample 'TwoDiamonds'."
564 
565  @see kdtree_balanced
566 
567  """
568 
569  def __init__(self, data_list=None, payload_list=None):
570  """!
571  @brief Create kd-tree from list of points and from according list of payloads.
572  @details If lists were not specified then empty kd-tree will be created.
573 
574  @param[in] data_list (list): Insert points from the list to created KD tree.
575  @param[in] payload_list (list): Insert payload from the list to created KD tree, length should be equal to
576  length of data_list if it is specified.
577 
578  """
579 
580  super().__init__(data_list, payload_list)
581 
582  def insert(self, point, payload=None):
583  """!
584  @brief Insert new point with payload to kd-tree.
585 
586  @param[in] point (list): Coordinates of the point of inserted node.
587  @param[in] payload (any-type): Payload of inserted node. It can be ID of the node or
588  some useful payload that belongs to the point.
589 
590  @return (node) Inserted node to the kd-tree.
591 
592  """
593 
594  if self._root is None:
595  self._dimension = len(point)
596  self._root = node(point, payload, None, None, 0)
597  self._point_comparator = self._create_point_comparator(type(point))
598 
599  self._length += 1
600  return self._root
601 
602  cur_node = self._root
603 
604  while True:
605  discriminator = (cur_node.disc + 1) % self._dimension
606 
607  if cur_node.data[cur_node.disc] <= point[cur_node.disc]:
608  if cur_node.right is None:
609  cur_node.right = node(point, payload, None, None, discriminator, cur_node)
610 
611  self._length += 1
612  return cur_node.right
613  else:
614  cur_node = cur_node.right
615 
616  else:
617  if cur_node.left is None:
618  cur_node.left = node(point, payload, None, None, discriminator, cur_node)
619 
620  self._length += 1
621  return cur_node.left
622  else:
623  cur_node = cur_node.left
624 
625  def remove(self, point, **kwargs):
626  """!
627  @brief Remove specified point from kd-tree.
628  @details It removes the first found node that satisfy to the input parameters. Make sure that
629  pair (point, payload) is unique for each node, otherwise the first found is removed.
630 
631  @param[in] point (list): Coordinates of the point of removed node.
632  @param[in] **kwargs: Arbitrary keyword arguments (available arguments: 'payload').
633 
634  <b>Keyword Args:</b><br>
635  - payload (any): Payload of the node that should be removed.
636 
637  @return (node) Root if node has been successfully removed, otherwise None.
638 
639  """
640 
641  if 'payload' in kwargs:
642  node_for_remove = self.find_node_with_payload(point, kwargs['payload'], None)
643  else:
644  node_for_remove = self.find_node(point, None)
645 
646  if node_for_remove is None:
647  return None
648 
649  self._length -= 1
650 
651  parent = node_for_remove.parent
652  minimal_node = self.__recursive_remove(node_for_remove)
653  if parent is None:
654  self._root = minimal_node
655 
656  # If all k-d tree was destroyed
657  if minimal_node is not None:
658  minimal_node.parent = None
659  else:
660  if parent.left is node_for_remove:
661  parent.left = minimal_node
662  elif parent.right is node_for_remove:
663  parent.right = minimal_node
664 
665  return self._root
666 
667  def __recursive_remove(self, node_removed):
668  """!
669  @brief Delete node and return root of subtree.
670 
671  @param[in] node_removed (node): Node that should be removed.
672 
673  @return (node) Minimal node in line with coordinate that is defined by discriminator.
674 
675  """
676 
677  # Check if it is leaf
678  if (node_removed.right is None) and (node_removed.left is None):
679  return None
680 
681  discriminator = node_removed.disc
682 
683  # Check if only left branch exist
684  if node_removed.right is None:
685  node_removed.right = node_removed.left
686  node_removed.left = None
687 
688  # Find minimal node in line with coordinate that is defined by discriminator
689  minimal_node = self.__find_minimal_node(node_removed.right, discriminator)
690  parent = minimal_node.parent
691 
692  if parent.left is minimal_node:
693  parent.left = self.__recursive_remove(minimal_node)
694  elif parent.right is minimal_node:
695  parent.right = self.__recursive_remove(minimal_node)
696 
697  minimal_node.parent = node_removed.parent
698  minimal_node.disc = node_removed.disc
699  minimal_node.right = node_removed.right
700  minimal_node.left = node_removed.left
701 
702  # Update parent for successors of previous parent.
703  if minimal_node.right is not None:
704  minimal_node.right.parent = minimal_node
705 
706  if minimal_node.left is not None:
707  minimal_node.left.parent = minimal_node
708 
709  return minimal_node
710 
711  def __find_minimal_node(self, node_head, discriminator):
712  """!
713  @brief Find minimal node in line with coordinate that is defined by discriminator.
714 
715  @param[in] node_head (node): Node of KD tree from that search should be started.
716  @param[in] discriminator (uint): Coordinate number that is used for comparison.
717 
718  @return (node) Minimal node in line with discriminator from the specified node.
719 
720  """
721 
722  min_key = lambda cur_node: cur_node.data[discriminator]
723 
724  stack, candidates = [], []
725  is_finished = False
726 
727  while is_finished is False:
728  if node_head is not None:
729  stack.append(node_head)
730  node_head = node_head.left
731  else:
732  if len(stack) != 0:
733  node_head = stack.pop()
734  candidates.append(node_head)
735  node_head = node_head.right
736  else:
737  is_finished = True
738 
739  return min(candidates, key=min_key)
pyclustering.container.kdtree.node.parent
parent
Parent node of the node.
Definition: kdtree.py:202
pyclustering.container.kdtree.kdtree_visualizer.__draw_split_line
def __draw_split_line(self, ax, node, min, max)
Definition: kdtree.py:103
pyclustering.container.kdtree.kdtree_balanced.__recursive_nearest_nodes
def __recursive_nearest_nodes(self, point, distance, sqrt_distance, node_head, best_nodes)
Returns list of neighbors such as tuple (distance, node) that is located in area that is covered by d...
Definition: kdtree.py:475
pyclustering.container.kdtree.kdtree_balanced.__len__
def __len__(self)
Returns amount of nodes in the KD-tree.
Definition: kdtree.py:299
pyclustering.container.kdtree.node.__repr__
def __repr__(self)
Definition: kdtree.py:204
pyclustering.container.kdtree.kdtree
Represents KD Tree that is a space-partitioning data structure for organizing points in a k-dimension...
Definition: kdtree.py:503
pyclustering.container.kdtree.kdtree.__recursive_remove
def __recursive_remove(self, node_removed)
Delete node and return root of subtree.
Definition: kdtree.py:667
pyclustering.container.kdtree.node.data
data
Data point that is presented as list of coordinates.
Definition: kdtree.py:187
pyclustering.container.kdtree.kdtree_balanced
Represents balanced static KD-tree that does not provide services to add and remove nodes after initi...
Definition: kdtree.py:243
pyclustering.container.kdtree.kdtree_balanced._root
_root
Definition: kdtree.py:282
pyclustering.container.kdtree.kdtree_balanced.find_nearest_dist_node
def find_nearest_dist_node(self, point, distance, retdistance=False)
Find nearest neighbor in area with radius = distance.
Definition: kdtree.py:431
pyclustering.container.kdtree.node.__str__
def __str__(self)
Definition: kdtree.py:220
pyclustering.container.kdtree.kdtree.insert
def insert(self, point, payload=None)
Insert new point with payload to kd-tree.
Definition: kdtree.py:582
pyclustering.container.kdtree.kdtree.__init__
def __init__(self, data_list=None, payload_list=None)
Create kd-tree from list of points and from according list of payloads.
Definition: kdtree.py:569
pyclustering.container.kdtree.node.payload
payload
Payload of node that can be used by user for storing specific information in the node.
Definition: kdtree.py:190
pyclustering.container.kdtree.kdtree_balanced.get_root
def get_root(self)
Returns root of the tree.
Definition: kdtree.py:308
pyclustering.container.kdtree.node.disc
disc
Index of dimension.
Definition: kdtree.py:199
pyclustering.container.kdtree.kdtree_visualizer.__get_all_nodes
def __get_all_nodes(self)
Definition: kdtree.py:134
pyclustering.container.kdtree.kdtree_balanced._find_node_by_rule
def _find_node_by_rule(self, point, search_rule, cur_node)
Search node that satisfy to parameters in search rule.
Definition: kdtree.py:368
pyclustering.container.kdtree.node.__init__
def __init__(self, data=None, payload=None, left=None, right=None, disc=None, parent=None)
Creates KD-tree node.
Definition: kdtree.py:173
pyclustering.container.kdtree.kdtree_balanced.__create_tree
def __create_tree(self, nodes, parent, depth)
Creates balanced sub-tree using elements from list nodes.
Definition: kdtree.py:317
pyclustering.container.kdtree.kdtree.__find_minimal_node
def __find_minimal_node(self, node_head, discriminator)
Find minimal node in line with coordinate that is defined by discriminator.
Definition: kdtree.py:711
pyclustering.container.kdtree.kdtree_balanced.__init__
def __init__(self, points, payloads=None)
Initializes balanced static KD-tree.
Definition: kdtree.py:269
pyclustering.container.kdtree.kdtree_balanced.find_nearest_dist_nodes
def find_nearest_dist_nodes(self, point, distance)
Find neighbors that are located in area that is covered by specified distance.
Definition: kdtree.py:458
pyclustering.container.kdtree.kdtree_balanced.find_node
def find_node(self, point, cur_node=None)
Find node with coordinates that are defined by specified point.
Definition: kdtree.py:415
pyclustering.container.kdtree.node.get_children
def get_children(self)
Returns list of not None children of the node.
Definition: kdtree.py:227
pyclustering.container.kdtree.node.right
right
Right node successor of the node.
Definition: kdtree.py:196
pyclustering.container.kdtree.kdtree_visualizer.__draw_node
def __draw_node(self, ax, node, min, max)
Definition: kdtree.py:90
pyclustering.container.kdtree.kdtree_visualizer.visualize
def visualize(self)
Visualize KD-tree using plot in 2-dimensional data-space.
Definition: kdtree.py:73
pyclustering.container.kdtree.node.left
left
Left node successor of the node.
Definition: kdtree.py:193
pyclustering.container.kdtree.kdtree_balanced._dimension
_dimension
Definition: kdtree.py:280
pyclustering.container.kdtree.kdtree_balanced._point_comparator
_point_comparator
Definition: kdtree.py:281
pyclustering.container.kdtree.kdtree.remove
def remove(self, point, **kwargs)
Remove specified point from kd-tree.
Definition: kdtree.py:625
pyclustering.container.kdtree.kdtree_visualizer.__init__
def __init__(self, kdtree_instance)
Initialize KD-tree visualizer.
Definition: kdtree.py:62
pyclustering.container.kdtree.kdtree_visualizer.__get_limits
def __get_limits(self)
Definition: kdtree.py:118
pyclustering.container.kdtree.node
Represents a node in a KD-Tree.
Definition: kdtree.py:163
pyclustering.utils
Utils that are used by modules of pyclustering.
Definition: __init__.py:1
pyclustering.container.kdtree.kdtree_visualizer
KD-tree visualizer that provides service to display graphical representation of the tree using matplo...
Definition: kdtree.py:19
pyclustering.container.kdtree.kdtree_balanced._create_point_comparator
def _create_point_comparator(self, type_point)
Create point comparator.
Definition: kdtree.py:353
pyclustering.container.kdtree.kdtree_balanced.find_node_with_payload
def find_node_with_payload(self, point, point_payload, cur_node=None)
Find node with specified coordinates and payload.
Definition: kdtree.py:397
pyclustering.container.kdtree.kdtree_visualizer.__tree
__tree
Definition: kdtree.py:69
pyclustering.container.kdtree.kdtree_balanced._length
_length
Definition: kdtree.py:279
pyclustering.container.kdtree.kdtree_visualizer.__verify
def __verify(self)
Definition: kdtree.py:151
pyclustering.container.kdtree.kdtree_visualizer.__colors
__colors
Definition: kdtree.py:70