[Author Prev][Author Next][Thread Prev][Thread Next][Author Index][Thread Index]

Re: [pygame] Need Help with Distance Algorithm in Numeric



Kamilche <klachemin@xxxxxxxxxxx>:
>
> Ooh, interesting! And what if I wanted to save the index of the entry in 
> the second array, and the actual distance, instead of the values 
> themselves? So that the final answer would be:
> 
> [(1, dist0),
>  (0, dist1),
>  (4, dist2)]
> 
> Where on the first line, 1 is the index to [20, 20, 20], and 'dist0' is 
> the distance between [10, 20, 30] and its nearest neighbor [20, 20, 20], 
> etc.
> 
> I have this all worked out in non-Numeric code, and I really appreciate 
> your help with converting it to Numeric!

This just requires splitting up the stuff from the original
calculation, that is:

  take(second, argmin(dist(first, second[..., NewAxis]), 0))

Instead of using take (or, in numarray, using the argmin as an index
array) you can simply keep the returned indices around:

  idxes = argmin(dist(first, second[..., NewAxis]), 0)

This should give you the array [1 0 4] in this example.

As for getting the actual distances -- I'm not sure how to do that in
a pretty way with Numeric. The take() function just doesn't seem to
cut it. With numarray, however, you could do the following, assuming
that the dist(...) part of the previous expression could be found in
all_dists:

  dists = all_dists[idxes, range(len(first))]

Here idxes gives the row coordinates and range(len(first)) gives the
column coordinates. I'd guess you could do something similar with
Numeric, but, as I said, I can't think of a pretty solution at the
moment.

On the other hand -- this last step is the cheapest one. You have
already had Numeric search for the minimums; you have the indices and
will have to go through the entire result list anyway, so getting the
values from all_dists instead of from dists won't make much
difference. You could just do something like

  for i in range(len(first)):
      idx = idxes[i]
      dist = all_dists[idx, i]
      # Do other stuff

Or you could just make a list comprehension of it, to get the list you
were after:

  result = [(idxes[i], all_dists[idxes[i], i]] for i in
            range(len(first))]

Hope that helps :)

-- 
Magnus Lie Hetland                   Fall seven times, stand up eight
http://hetland.org                                 [Japanese proverb]