Nearest Neighbors - ProkopHapala/SimpleSimulationEngine GitHub Wiki
Nearest neighbor search has complexity N^2. We can reduce it to NlogN or almost linear N by use of special datastructures, such as HashMap or BufferGrid. In 2D and 3D HashMap can be used directly (for each query point $i$ we simply explore all neighboring grid cells). However in more dimensional spaces this is not possible since there is too many such neighboring cells ( 3^D resp. 2^D depending on whether we insert point into just one box, or into all boxes witch which it bounding sphere overlaps ).
In more dimensional space we have to use several independent HashMaps or grids from which we quarry independently. Each of these hashmaps returns it own set of possible neighbors. Only common intersection from all these sets is than considered as possible neighbor. For this narrow subset true pair-wise distance is computed.
Algorithm for HashMap neihbor quarry of atomic structures
- For structure
ievaluate real valued hashes(h_1,h_2,...h_N)(e.g. projection on planewaves for each atom type), and discretize it to integer hashes(ih_1,ih_2,...ih_N) - For
HashMap_k(1D,2D or 3D) quarry compound indexind_k = pack( hi_i(k), hi_(i(k)+1), hi_(i(k)+2) )to obtain setS_k- if first set total set
cellNeighs2D = [(0,0), (-1,0),(+1,0), (0,-1),(0,+1), (-1,-1),(-1,-1), (-1,+1),(+1,-1) ]
def getPossibleNeighbors( geometry, hashMaps, hashFuncs ):
result = None
for hashMap,hashFunc in zip( hashMaps, hashFuncs ):
hashvec = [ hf(geometry) for hf in hashFunc ] # compute real valued hashes (properly scaled by step )
icell = [ int(h) for h in hashvec ] # 1D,2D or 3D index of grid cell
aspect_set = {}
for dicell in cellNeighs2D:
found_list = hashMap.getInBins( icell + dicell)
aspect_set.insert( found_list )
if( result is None ):
result_set = aspect_set # initialize result
else:
result_set = { x if ( x in result_set ) for x in aspect_set } # make intersection with previous result
return result