Приближенный инкрементальный алгоритм ближайшего соседа для движущихся тел - PullRequest
18 голосов
/ 29 июля 2011

Bounty

Этот вопрос поднимает несколько вопросов. Щедрость пойдет на ответ, который обращается к ним целостно.


Вот проблема, с которой я играл.

ПРИМЕЧАНИЕ Меня особенно интересуют решения, которые не основаны на евклидовом пространстве.

Существует набор актеров, которые образуют толпу размером K. Расстояние d(ActorA,ActorB) легко вычисляется для любых двух акторов (решения должны работать для различных определений «расстояния»), и мы можем найти множество из N ближайших Соседи для любого данного Актора, использующего любой из ряда установленных алгоритмов.

Этот набор соседей правильный в первый момент, но Актеры всегда движутся , и я хочу поддерживать развивающийся список из N ближайших соседей для каждого Актера. Что меня интересует, так это приблизительные решения, которые более эффективны, чем совершенные решения.

  1. Решения должны сходиться к правильности после появления ошибок.
  2. Допускается иногда выполнять полное пересчет, если ошибки становятся слишком большими, но обнаружение этих ошибок должно быть дешевым .

До сих пор я использовал алгоритм друга-друга алгоритм:

recompute_nearest (Actor A)
{
    Actor f_o_f [N*N];
    for each Actor n in A.neighbours
        append n to f_o_f if n != A and n not in f_o_f

    Distance distances [N*N];
    for 0 <= i < f_o_f.size
        distances [i] = distance (A, f_o_f [i])

    sort (f_o_f, distances)
    A .neighbours = first N from f_o_f
}

Это работает достаточно хорошо, когда толпа медленно движется, а N достаточно велико. Он сходится после небольших ошибок, удовлетворяющих первым критериям, но

  • У меня нет хорошего способа обнаружить большие ошибки,
  • У меня нет количественного описания размера и частоты ошибок,
  • на практике это сходится, но я не могу доказать , что так будет всегда.

Можете ли вы помочь с любым из этих пунктов?

Кроме того, знаете ли вы какие-либо альтернативные подходы, которые хорошо работают

  • когда толпа быстро движется,
  • когда некоторые актеры быстро движутся,
  • когда N мало,
  • когда толпа в некоторых местах редкая, а в других плотная,
  • или с конкретными алгоритмами пространственного индексирования?

Расширение, над которым я сейчас работаю, заключается в обобщении слова «друг друга», чтобы он брал друга друга в тех случаях, когда сосед быстро движется. Я подозреваю, что это плохо масштабируется, и трудно определить правильные параметры без количественной оценки ошибок.

Я приветствую все предложения! Это небольшая забавная проблема: -)


Примечательные предложения пока

Fexvez: выборка случайных дополнительных соседей, размер выборки в зависимости от скорости Агента. Выборка из области, в которую он собирается перейти, вероятно, также поможет.

Повторная выборка соседей, когда агент speed*delta_time превышает расстояние до самого дальнего известного соседа.

Поддерживать Триангуляцию Делоне , которая является надмножеством графа ближайших соседей. Только для одного ближайшего соседа.

Библиотека Дэвида Маунта ANN Кажется, не обрабатывает движущихся тел.

Ответы [ 7 ]

10 голосов
/ 05 августа 2011

Очень простой и очень быстрый метод из статистики - использовать случайные линейные проекции. Это может помочь вам определить кластеры и соседей очень быстро. Чем больше прогнозов, тем выше точность (я думаю, что я отвечаю на ваш вопрос об ошибках).

В этой статье предлагается обширный количественный анализ нескольких методов, включая новый метод (DPES), связанный с RLP.

В этом документе рассматривается использование RLP, в том числе для сохранения расстояния даже в контексте движущихся точек .

В этом документе рассматриваются RLP для планирования движения и подробно описываются некоторые эвристики.

RLP методы:

  1. Очень быстро
  2. Приведите к приближениям, которые настраиваются на точность и скорость
  3. Сохранение расстояния и угла (доказуемо)
  4. Легко масштабируется для больших размеров и большого количества объектов
  5. Полезно для уменьшения размерности
  6. Приводит к компактным проекциям (например, можно проецировать в иерархическое двоичное разбиение)
  7. Гибкость: вы можете проецировать в любое удобное для вас пространство - обычно R ^ d, но также допустимо проецирование в 2 ^ d (т. Е. Двоичное пространство измерения d), только при условии снижения точности для заданное количество прогнозов.
  8. Статистически интересно

После встраивания в пространство более низких измерений вычисления соседей очень просты, так как проекции, скажем, сгруппированные в тех же областях (если вы скомбинируете проекции в сетку), с большой вероятностью будут близки в исходном пространстве.

Хотя размерность исходных данных мала (даже 10 мала), возможность быстрого проецирования в предварительно выбранную сетку очень полезна для идентификации и подсчета соседей.

Наконец, вам нужно обновить только те объекты, чье местоположение (или относительное местоположение, если вы центрируете и масштабируете данные) изменилось.

Информацию о связанных работах можно найти в лемме Джонсона-Линденштраусса.

4 голосов
/ 29 июля 2011

Вот простой контрпример, показывающий, что алгоритм вашего друга-друга иногда пропускает соседей: начните с длинной прямой линии из множества (по крайней мере, более 3 * N) равноотстоящих актеров и постепенно сгибайте линию вкруг.Если линия достаточно длинная, ее участники не обнаружат локальных изменений в своих кварталах;в частности, актеры на концах не заметят, когда встретятся.

Редактировать: На самом деле, я подумал о еще более простом контрпримере: возьмите два изолированных компактных кластера по N или более актеров каждый и отправьте их накурс столкновения друг с другом.

4 голосов
/ 29 июля 2011

Вы пытались использовать четырехугольное дерево ?

То есть рекурсивно разбивать «мир» на граф с четырьмя подузлами в каждом.Затем дерево может быстро проверить, какие объекты находятся внутри определенного квадрата мира, и отбросить остальные.Очень эффективная методика отбора, часто используемая для улучшения производительности обнаружения столкновений в играх.

Если это 3D, расширьте его до октри.

3 голосов
/ 29 июля 2011

У меня есть нечто, похожее на решение.

На каждом шаге «повторного вычисления» требуется линейное время, которое, я думаю, не является большой проблемой, как вы делаете recompute_nearest (Actor A) для каждого актера.

Давайте перейдем к сути: идея для каждого актера, добавить определенное количество случайных друзей непосредственно перед вычислением recompute_nearest (Actor A). Это число не должно быть маленьким, иначе вы никогда не обнаружите ошибки. Он не должен быть слишком большим, иначе вычисление соседей соседей является квадратичным, это будет слишком дорого в вычислительном отношении.

Но что значит "не слишком маленький" или "не слишком большой"? Мы начнем с одного актера А и посмотрим, как будет обновляться его список соседей. Предположим, что для каждой точки вы добавляете p процентов от первоначальных K актеров. Затем, если другой пункт B приближается к A, но не является другом друга, мы должны «быстро» добавить его через «случайные друзья». На каждой итерации есть (1-p) шанс не выбирать его.

Быстрое вычисление показывает, что если вы хотите определить эту точку за 10 итераций или менее в 90% случаев, вам потребуется p=20%. Это ужасно дорого.

...

Однако еще не все потеряно! Первое, что я хочу сделать, это то, что если ошибки имеют тенденцию «идти вместе», то производительность резко возрастает! Представьте себе два капли, которые изначально находятся далеко друг от друга (люди в чате, звездные скопления и т. Д.). Если эти капли сталкиваются, друг друга никогда не увидит, что существует проблема. Но с моим алгоритмом, если вы обнаружите одну-единственную ошибку и правильно адаптируете свой список соседей, тогда алгоритм друга-друга исправит все оставшиеся ошибки.

Если у вас есть K=1.000 и два маленьких шарика, каждый из которых содержит только 1% точек, и вы хотите выделить 10 итераций или меньше с уверенностью 99%, вы можете вычислить, что вам понадобится только p=1%! (Чем больше K, тем меньше должно быть p!) Ну, это предполагает, что некоторые точки «идут вместе».

У меня есть еще одна оптимизация: адаптировать количество и качество случайных точек. Проще говоря, быстрым актерам нужно дать больше случайных друзей, чем медленным. И вы должны рандомизировать этих друзей, предпочитая других быстрых актеров. Я не могу определить это, но вы можете догадаться, почему это улучшит производительность!


Небольшая правка по вашему вопросу: «Что мне делать, когда актеры быстры»? Вы можете перевести скорость актеров с количеством шагов, которые вы даете себе, чтобы определить ошибку. Я имею в виду, что если вы считаете, что каждый актер окружает своих друзей. Этот теоретический круг соответствует его списку друзей. Если большинство актеров не могут полностью пересечь этот круг за 10 итераций, но могут за 15 итераций, вам следует подумать, что вы даете себе 10 итераций, чтобы определить проблему. Если ваши актеры настолько быстры, что могут пересечь этот «круг» за 3 шага, тогда, ну ... этот алгоритм не для вас (и я думаю, что иллюзорно пытаться вести список соседей, не пересчитывая его на каждом шаге)

По сути, ведение списка соседей предполагает наличие некоторой структуры (т.е. что-то примерно одинаковое между двумя итерациями). Скорость наоборот, быстрые актеры означают, что у вас нет структуры. В случае очень быстрых актеров, ведение списка соседей, вероятно, плохая идея.


Техническая информация о каплях.

У вас есть два больших объекта, каждый из которых содержит s% актеров (размер sK) (например, s = 1%)

Вы задаете себе погрешность в e% (пример 1%) и n шагов (пример 10)

Тогда есть верхняя граница для p: p <= [log(1-e^(1/n))]/[s*K²*log(1-s)]

Истинное значение моего примера - p <= 0.989%!

У вас есть p = [log(1-e^(1/n))]/[s*K²*log(1-s)], если s мало, а K большое. Если это не так, р намного меньше!

1 голос
/ 17 сентября 2011

Что бы я попробовал.

  1. Покрытие деревьев в качестве базовой структуры данных для выполнения кНН. Особенности: не требуется евклидова метрика, использование линейного пространства, kNN / Insert / Remove - все O (log n), когда внутренняя размерность данных фиксирована. Non-функция: движение.

  2. Для обработки движущихся объектов периодически, для каждого объекта, удаляйте его старое положение, вставьте его новое положение и найдите kNN.

Если мы установим период объекта, обратно пропорциональный скорости, то мы знаем, что максимальное расхождение между деревом покрова и реальностью ограничено константой.

0 голосов
/ 29 июля 2011

Когда расстояние, на которое актер перемещается за данный временной шаг, превышает расстояние до его самого дальнего известного соседа, выполните повторную выборку всех соседей.

Другой триггер: когда расстояние, на которое актер переместился с момента последнего повторного отсчета, превышает расстояние до самого дальнего известного соседа, повторный отсчет.

Здесь упрощается тривиальная оптимизация, если существует иерархический пространственный индекс, ищите узел, содержащий а) сферу радиуса, равную размеру прыжка, и б) не менее N актеров.

0 голосов
/ 29 июля 2011

KD-деревья позволяют эффективно выполнять поиск в пределах фиксированного радиуса точки.Если все соседние точки находятся в пределах d1 единиц и максимальное смещение любой точки из предыдущего измерения составляет d2 , то вам нужно искать только в пределах d1 + d2 * 1006.* единицы измерения.

Если вы имели дело с расстоянием Минковского, то вы могли бы использовать библиотеку ANN Дэвида Маунта .Я не уверен, если есть библиотека, которая будет принимать произвольные функции расстояния, хотя.

...