I have a program which works with a list of points (in 3D, but it could be in 1D as well, it won't make a difference). Within a loop, it keeps adding new points to the list. To calculate the coordinates of a new point, it needs to use a NearestFunction generated from the list of existing points.

When a new point is added to the list, the NearestFunction needs to be rebuilt as well. This is rather time consuming if I do it using the list of existing points.

Is it possible to more efficiently append a new point to an already constructed NearestFunction? (Perhaps by making use of the knowledge of the internal structure of a NearestFunction)

Good question! I want it the other way round, i.e. delete points from the list for a path optimization task...
–
Yves KlettMar 9 '13 at 20:38

@YvesKlett you may use Nearest[data,x,n] and use the second element if the first one has been "deleted"
–
belisariusMar 9 '13 at 21:46

@belisarius true. For a long list that is whittled down to zero I' ll have to repeatedly return more candidates which takes longer (but I need to benchmark to verify, been a while).
–
Yves KlettMar 10 '13 at 7:09

Here you can see the efficiency limits for the method. We start with 2 10^5 triplets and add a point at a time. We use the above method and the standard Nearest Function recalculation to evaluate the distances to ten random points.
We see that after adding 10^3 points, the suggested method efficiency gain is almost lost, but can be regained with only one recalc.

I don't know what all these things stand for, so what follows might not work in all cases. In any case, what I present below will suggest that adding a point and redoing Nearest is probably not a bad way.

The first (recomputing Nearest) was quicker in more trials than mine. Since the first is definitely safe, I'd say stick with it. Perhaps someone may come up with a more efficient way of updating the parts of NearestFunction.

Unfortunately, your function is not working. The last element of NearestFunction is a fallback that rebuilds the function. It is being invoked each time. Consider ReplacePart[addpoint[nf,point],-1->Hold[banana]][{0,0,0}]: (* banana[{0,0,0}] *).
–
XerxesMar 9 '13 at 23:22

@Xerxes Thanks for testing it. I'm not sure I understand. I found a error in the last example (from pasting out of context), but the function addpoint seems to work for me. I get the same NearestFunction whether I use AppendTo or addpoint
–
Michael E2Mar 10 '13 at 2:06

2

It's not too surprising that this isn't faster. The internal structure of a NearestFunction is most likely a k-d tree or similar. The FullForm is probably only used to (re)build the internal representation when it is missing (e.g. when the NearestFunction is loaded from a package).
–
Oleksandr R.Mar 10 '13 at 4:55

@OleksandrR. Actually from the beginning I was doubtful of any way to do what's being asked -- belisarius' is a clever way around it. But I still thought it worth sharing a negative result, even of a naive approach.
–
Michael E2Mar 10 '13 at 13:30

Here is a variation that is a bit on the slow side but will at least scale fairly well. The idea is to use buckets of NearestFunction objects, as well as a list of "lone" points, and take closest neighbors from amongst neighbors obtained from these separately. Adding new points gets amortized in the sense that usually we add to the "lone" list, then empty that at a threshold and create a new NearestFunction. Which size to create depends on what we already have; if all lists to date are full, we throw them all together 9effectively doubling the size of the largest) and create a new function from those. We then empty the lower slots. When we next need to create a NearestFunction we will fill in those lower slots.

Mathematica is a registered trademark of Wolfram Research, Inc. While the mark is used herein with the limited permission of Wolfram Research, Stack Exchange and this site disclaim all affiliation therewith.