Exemplo n.º 1
0
 def islocalnettree(self):
     if self.T.root.getchild() is None:
         return True
     q = [self.T.root.getchild()]
     for node in q:
         # nesting
         if len(node.ch) > 0 and node.point not in [
                 ch.point for ch in node.ch
         ]:
             print('Violates LNT nesting')
             return False
         # parent
         for par in rel(node.par):
             if dist(node, node.par) > dist(node, par):
                 print('Violates LNT parent')
                 return False
         for ch1 in node.ch:
             q.append(ch1)
             # covering
             if dist(node, ch1) > self.T.cc * self.T.tau**node.level:
                 print('Violates LNT covering')
                 return False
             # packing
             for ch2 in node.ch:
                 if ch1 != ch2 and dist(ch1,
                                        ch2) <= self.T.cp * self.T.tau**max(
                                            ch1.level, ch2.level):
                     print('Violates LNT packing: ', ch1.point, ch1.level,
                           ch2.point, ch2.level)
                     return False
     return True
Exemplo n.º 2
0
 def changernn(self, point, fromnode, tonode, todist=None):
     """
     Changes the center of an uninserted point to a different node and moves the point 
     to the cell of that node.
     
     Parameters:
     ----------
     point : Point
         An uninserted point.
     fromnode : Node
         The current center of the uninserted point.
     tonode : Node
         The next center of the uninserted point.
     todist : float
         The precomputed distance between point and tonode.
         If todist==None, then the method computed the distance.
     """
     todist = todist or dist(tonode, point)
     self._nn[point] = tonode
     self._nndist[point] = todist
     if todist <= self.tree.cp * (self.tree.tau ** (tonode.level - 1)) / 2:
         self._rnn_in[tonode].add(point)
     else:
         self._rnn_out[tonode].add(point)
     self._rnn_in[fromnode].discard(point)
     self._rnn_out[fromnode].discard(point)
Exemplo n.º 3
0
 def isglobalnettree(self):
     if self.T.root.getchild() is None:
         return True
     q = [self.T.root.getchild()]
     dictnry = dict()
     self.findleaves(self.T.root, dictnry)
     for node in q:
         # nesting
         if len(node.ch) > 0 and node.point not in [
                 ch.point for ch in node.ch
         ]:
             print('Violates NT nesting')
             return False
         # covering
         for leaf in dictnry[node]:
             if dist(node, leaf) > self.T.cc * self.T.tau**node.level:
                 print('Violates NT covering')
                 return False
         # packing
         others = [n.point for n in dictnry[self.T.root] - dictnry[node]]
         if len(others) > 0 and node.point.distto(
                 *others) <= self.T.cp * self.T.tau**node.level:
             print('Violates NT packing')
             return False
         for ch1 in node.ch:
             q.append(ch1)
     return True
Exemplo n.º 4
0
 def nnhelper(self, point, currentnodes, level):
     if point.distto(*[n.point for n in currentnodes
                       ]) > self.tree.cr * self.tree.tau**level:
         return None
     nextnodes = {
         n if n.level == level - 1 else n.par
         for n in ch(currentnodes)
         if dist(n, point) <= self.tree.cr * self.tree.tau**level
     }
     nn = self.nnhelper(point, nextnodes, level - 1)
     return nn if nn else min(currentnodes,
                              key=lambda n: point.distto(n.point))
Exemplo n.º 5
0
 def update_ch(self, node):
     """
     Updates children of a given node.
     
     Parameters:
     ----------
     node : Node
         The node that its relatives should be updated.
     """
     for other in ch(rel(node)):
         if dist(node, other) < dist(other, other.par):
             oldpar = other.par
             node.addch(other)
             child = oldpar.getchild()
             # The old parent should not be removed from the tree because it is a relative of `node`
             # However, if it has only one child, then that child should be checked 
             # against the semi-compressed condition
             if len(oldpar.ch) == 1 and len(child.ch) == 1 and len(child.rel) == 1:
                 if hasattr(self, 'ploc'): self.ploc.updateonremoval(child)
                 oldpar.addch(child.getchild())
                 oldpar.ch.discard(child)          
Exemplo n.º 6
0
 def update_par(self, node, closest):
     """
     Updates the parent of a given node.
     
     Parameters:
     ----------
     node : Node
         The node that its parent should be updated.
     closest : Node
         The node closest to `node` at the same level.
     """
     newpar = nearest(node, rel(par(closest)))
     # There may be a node in rel(par(@closest)) such that
     # its distance to `node` is the same as the distance of `node` to `closest.par`.
     # In this case, the right parent should be the parent of `closest`,
     # otherwise we may need to delete `closest` from the tree.
     if dist(node, newpar) == dist(node, closest.par):
         newpar = closest.par
     if newpar.getchild().level < node.level:
         self.splitbelow(newpar, node.level)
         if self.isrel(node, newpar): node.addrel(newpar.getchild())
     node.setpar(newpar)
Exemplo n.º 7
0
 def nn(self, point):
     currentnode = self.tree.root
     nextnode = self.tree.root.getchild()
     self.basictouchno += 1
     while dist(nextnode,
                point) <= self.tree.cr * self.tree.tau**nextnode.level:
         currentnode = nextnode
         allnodes = ch(rel(currentnode))
         nextlevel = max(n.level for n in allnodes)
         nextnode = min(allnodes,
                        key=functools.partial(self.mincoveringdist,
                                              point=point,
                                              level=nextlevel))
     return currentnode
Exemplo n.º 8
0
 def iscovered(self, node):
     """
     Tests whether the covering property for `node.par` is satisfied or not.
     
     Parameters:
     ----------
     node : Node
         The node that should be tested against the covering property.
         
     Returns:
     -------
     bool
         Returns True is the distance between `node` and its parent is 
         not greater than c_c\tau**(node.level+1).
     """
     return dist(node, node.par) <= self.cc * (self.tau**(node.level + 1))
Exemplo n.º 9
0
 def insert(self, point, closest=None):
     """
     Insertes a point into the net-tree.
     
     Parameters:
     ----------
     point : Point
         The point to be inserted.
     closest : Node
         The center of the point. If `closest` is not provided, then the 
         point location data structure is used to find it.
     """
     closest = closest or self.ploc.nn(point)
     if hasattr(self, 'ploc'):
         dst = self.ploc.nndist(point, closest)
         # Removes the uninserted point from the point location data structure.
         # In other words, the point is removed from the mappings for the centers and cells
         self.ploc.removepoint(point)
     else:
         dst = dist(closest, point)
     # Finding the lowest level so that the point can still be a relative of the closest node
     level = self.minlevelrelatives(closest, point, dst)
     # If the packing property does not hold at this level,
     # then the node should be inserted in exactly one level down
     if dst <= self.cp * self.tau**level:
         level -= 1
     if level < closest.level:
         # If there is a jump, then we should split it
         if closest.getchild().level < level:
             closest = self.splitbelow(closest, level)
         # Otehrwise, find the node associated to the same point
         else:
             closest = [n for n in closest.ch
                        if n.point == closest.point][0]
     node = Node(point, level)
     self.update(node, closest)
     lowest = node
     # We ensure that the nesting property is satisfied
     if len(node.ch) > 0:
         lowest = Node(node.point, node.level - 1)
         if lowest not in node.ch:
             lowest.setpar(node)
             if hasattr(self, 'ploc'): self.ploc.updateonsplit(lowest)
     self.splitbelow(lowest, config.arithmatic.ninfty)
     while not self.iscovered(node):
         node = self.promote(node)
Exemplo n.º 10
0
 def nndist(self, point, nn = None):
     """
     Returns the distance of point to its center.
     
     Parameters:
     ----------
     point : Point
         An uninserted point.
     nn : Node
         The center of the uninserted point. If nn==None, then the data structure 
         looks up the center in its saved mapping.
         
     Returns:
     -------
     float
         The distance between the uninserted point and its center.
     """
     return self._nndist[point] or dist(nn or self._nn[point], point)
Exemplo n.º 11
0
 def isrel(self, node, other, computeddist=None):
     """
     Determines if the distance between `node` and `other` is  at most c_r\tau**(node.level).
     
     Parameters:
     ----------
     node : Node
         A node of the tree.
     other : Node or Point
         Either a node of the tree or a point.
     computeddist : float
         If the distance between `node` and `other` is precomputed, then we do not recompute it.
         Otherwise, if computeddist==None, then the method calculates the distance.
     
     Returns:
         bool
     """
     return (computeddist or dist(node, other)) <= self.cr * (self.tau ** node.level)
Exemplo n.º 12
0
 def nnhelper(self, point, currentnodes, level):
     if len(currentnodes) != 0:
         self.basictouchno += len(currentnodes)
     if len(currentnodes) == 0 or \
         point.distto(*[n.point for n in currentnodes]) > self.tree.cr * self.tree.tau ** level:
         return None
     children = ch(currentnodes)
     nextlevel = max(n.level for n in children)
     nextnodes = {
         n if n.level == nextlevel else n.par
         for n in children
         if dist(n, point) <= self.tree.cr * self.tree.tau**nextlevel
     }
     self.basictouchno += len(children)
     nn = self.nnhelper(point, nextnodes, nextlevel)
     if nn:
         return nn
     self.basictouchno += len(currentnodes)
     return min(currentnodes, key=lambda n: point.distto(n.point))
Exemplo n.º 13
0
 def minlevelrelatives(self, first, second, computeddist=None):
     """
     Determines the minimum level so that `first` and `second` can be relatives.
     
     Parameters:
     ----------
     first : Node
         A node of the tree.
     second : Node or Point
         A node of the tree or a point.
     computeddist : float
         If the distance between `node` and `other` is precomputed, then we do not recompute it.
         Otherwise, if computeddist==None, then the method calculates the distance.
     
     Returns:
     -------
     float
     """
     return math.ceil(math.log((computeddist or dist(first, second)) / self.cr, self.tau))
Exemplo n.º 14
0
 def nn(self, point):
     currentnode = self.tree.root
     nextnode = self.tree.root.getchild()
     #         closestdist = dist(nextnode, point)
     #         while closestdist <= self.tree.cr * self.tree.tau ** nextnode.level:
     #             currentnode = nextnode
     #             allnodes = ch(rel(currentnode))
     #             nextnode = allnodes.pop()
     #             closestdist = dist(nextnode, point)
     #             for n in allnodes:
     #                 newdist = dist(n,point)
     #                 if newdist < closestdist and newdist <= self.tree.cr * self.tree.tau ** n.level:
     #                     nextnode, closestdist = n, newdist
     while dist(nextnode,
                point) <= self.tree.cr * self.tree.tau**nextnode.level:
         currentnode = nextnode
         allnodes = ch(rel(currentnode))
         nextlevel = max(n.level for n in allnodes)
         nextnode = min(allnodes,
                        key=functools.partial(self.mincoveringdist,
                                              point=point,
                                              level=nextlevel))
     return currentnode
Exemplo n.º 15
0
 def trytochangernn(self, point, tonode):
     """
     Determines whether an uninserted point should change its cells or not. If so, the change will happen.
     
     Parameters:
     ----------
     point : Point
         The uninserted point.
     tonode : Node
         The node that may be the new center for the uninserted point.
     """
     fromnode = self._nn[point]
     todist = self.nndist(point) if fromnode.point == tonode.point else dist(tonode, point)
     if self.tree.isrel(tonode, point, todist):
         '''
         we change the center of a point if either:
         1) the current and next centers are associated to the same point and 
             we have a split below (next center has a lower level)
         2) the current and next centers are associated with different points 
             and the next center is closer to the point than its current center
         '''
         if (fromnode.point == tonode.point and fromnode.level > tonode.level) or \
             (fromnode.point != tonode.point and todist < self.nndist(point)):
             self.changernn(point, fromnode, tonode, todist)
Exemplo n.º 16
0
 def mincoveringdist(self, node, point, level):
     dst = dist(node, point)
     self.basictouchno += 1
     return dst if dst <= self.tree.cr * self.tree.tau**level else float(
         'inf')
Exemplo n.º 17
0
 def nn(self, point):
     child = self.tree.root.getchild()
     if dist(child, point) > self.tree.cr * self.tree.tau**child.level:
         return self.tree.root
     return self.nnhelper(point, {child}, child.level) or self.tree.root
Exemplo n.º 18
0
 def nndist(self, point, nn=None):
     return dist(nn or self.nn(point), point)