Подтвердить что ты не робот

Приближенный, инкрементный алгоритм ближайшего соседа для движущихся тел

Bounty

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


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

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

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

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

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

До сих пор я использовал алгоритм friend-of-a-friend:

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 превышают расстояние до самого дальнего известного соседа.

Поддерживайте триангуляцию Delaunay, которая является надмножеством графика ближайшего соседа. Учитывается только ближайший сосед один.

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

4b9b3361

Ответ 1

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

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

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

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

Методы RLP:

  • Очень быстро
  • Приведите к приближениям, которые можно настроить для точности и скорости.
  • Сохранение расстояния и угла (доказуемо)
  • Легко масштабируется до больших размеров и больших # объектов
  • Полезно для уменьшения размерности
  • Привести к компактным проекциям (например, можно проектировать в иерархическое двоичное разбиение)
  • Гибкость: вы можете проецироваться в любое пространство, которое, по вашему мнению, будет полезно для вас - обычно R ^ d, но проецирование на 2 ^ d (т.е. двоичное пространство размерности d) также допустимо, только с учетом уменьшения точности для заданное количество проекций.
  • Статистически интересный

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

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

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

Для соответствующих работ рассмотрим лемму Джонсона-Линденштрауса.

Ответ 2

Вы пытались использовать quad tree?

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

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

Ответ 3

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

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

Ответ 4

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

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

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

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

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

...

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

Если у вас есть 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 велико. Если это не так, p намного меньше!

Ответ 5

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

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

  • Чтобы обрабатывать движущиеся объекты периодически, для каждого объекта, удалять его старую позицию, вставлять новую позицию и находить kNN.

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

Ответ 6

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

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

Ответ 7

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

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

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