这个问题提出了几个问题。赏金将会回答整体问题。
这是我一直在玩的问题。
注意我对不在欧几里得空间的解决方案特别感兴趣。
有一组Actors形成一个大小为K的人群。距离d(ActorA,ActorB)
很容易为任何两个演员计算(解决方案应该适用于'距离'的各种定义),我们可以找到任何给定Actor的N个最近邻居使用任何已建立的算法。
这个邻居集在第一时刻是正确的,但是 Actors总是在移动,我想维护每个Actor的N个最近邻居的进化列表。我感兴趣的是近似解决方案,它比完美解决方案更有效。
到目前为止,我一直在使用朋友的朋友算法:
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适当大时,这表现得相当好。它在小错误之后收敛,满足第一个标准,但是
你能帮助解决这些问题吗?
另外,你知道任何表现良好的替代方法
我正在进行的扩展是为了推广朋友的朋友,以便在邻居快速移动的情况下接收一位朋友的朋友。我怀疑这不能很好地扩展,如果没有量化错误,很难得出正确的参数。
我欢迎所有的建议!这是一个有趣的小问题: - )
Fexvez:样本随机额外邻居,样本大小取决于代理的速度。 从即将进入的区域进行抽样可能也会有所帮助。
当代理speed*delta_time
超过距离最远的已知邻居的距离时,重新对邻居进行重采样。
维护Delaunay triangulation,它是最近邻图的超集。 仅考虑一个最近邻居。
David Mount的ANN library 似乎无法处理移动正文。
答案 0 :(得分:10)
统计学中一种非常简单且非常快速的方法是使用随机线性投影。这些可以帮助您快速确定群集和邻居。通过更多投影,您可以获得更高的准确性(我相信,解决有关错误的问题)。
This paper提供了对几种方法的广泛定量分析,包括与RLP相关的新方法(DPES)。
This paper解决了RLP的使用问题,即使在移动点的情况下也可用于距离保留。
This paper解决了RLP的运动规划问题,并详细介绍了几种启发式方法。
RLP方法是:
嵌入到较低维空间后,邻居计算非常容易,因为在相同区域(如果将投影分成网格)中的分组投影很可能在原始空间中很接近。
虽然原始数据的维度很小(甚至10很小),但快速投影到预选网格的能力对于识别和计算邻居非常有用。
最后,您只需更新那些位置(或相对位置,如果您居中和缩放数据)已更改的对象。
对于相关作品,请查看Johnson-Lindenstrauss引理。
答案 1 :(得分:4)
您是否尝试使用quad tree?
即,将“世界”递归地划分为每个具有四个子节点的图形。然后,树可以快速检查哪些物体位于世界的特定方格内,并丢弃其余的物体。一种非常有效的剔除技术,通常用于提高游戏中碰撞检测的性能。
如果是3D,请将其扩展为八叉树。
答案 2 :(得分:4)
这是一个简单的反例,显示你朋友的朋友算法有时会错过邻居:从许多(至少超过3 * N)等距间距演员的长直线开始,逐渐将线条弯曲成一个圆圈。如果这条线足够长,那么其中的演员将检测到他们的社区没有本地变化;特别是,当他们见面时,两端的演员都不会注意到。
编辑:实际上,我想到了一个更简单的反例:每个N或更多演员采取两个孤立的紧凑集群,并将它们相互发送。
答案 3 :(得分:3)
我有点看起来像解决方案。
在每次“重新计算”步骤中,它需要一个线性时间,我猜这并不是一个问题,因为你对每个演员都recompute_nearest (Actor A)
。
让我们明白一点:每个演员的想法都是,在计算recompute_nearest (Actor A)
之前添加一定数量的随机朋友。这个数字不应该很小,否则你永远不会发现错误。它不应该太大,否则邻居的计算邻居是二次的,它在计算上太昂贵了。
但“不太小”或“不太大”是什么意思?我们将从一个演员A开始,看看他的邻居名单将如何更新。让我们假设对于每个点,您添加原始K个角色的p
%。然后,如果另一个点B接近A但不是朋友的朋友,我们应该“快速”通过“随机朋友”添加他。在每次迭代中,(1-p)
有机会不选择他。
快速计算表明,如果要在90%的情况下在10次或更少次迭代中发现此点,则需要p=20%
。这非常昂贵。
...
但是,一切都不会丢失!我想说的第一点是,如果错误倾向于“一起”,那么性能会急剧增加!想象一下最初相距很远的两个斑点(人们聊天,星团等等)。如果这些斑点碰撞,朋友的朋友将永远不会发现存在问题。但是,根据我的算法,如果您发现一个错误,并正确调整您的邻居列表,那么,朋友之友算法将纠正所有剩余错误。
如果您有K=1.000
和两个小blob,每个只包含1%的点,并且您希望在99次确定性的10次或更少的迭代中发现,您可以计算出您只需要{{1 }}! (K越大,需要的p就越小!)好吧,假设某些点“一起”。
我还有另一个优化:调整随机点的数量和质量。简单地说,快速演员应该比慢演员更随意地交给朋友。你应该随机选择这些喜欢其他快速演员的朋友。我无法量化它,但你可以猜到为什么它会改善性能!
关于你的问题的小编辑:“当演员快速时我该怎么办”?您可以使用您自己发现的步数来转换演员的速度以发现错误。我的意思是,如果你可以认为每个演员都围绕着他的朋友圈。该理论圈对应于他的朋友列表。如果大多数演员不能在10次迭代中完全越过这个圆圈,但是可以在15次,那么你应该考虑给自己10次迭代来发现问题。如果你的演员如此之快以至于他们可以通过3个步骤穿过这个“圆圈”,那么,嗯......这个算法不适合你(我想这是一种虚幻的尝试保留邻居列表而不在每一步重新计算它)
从根本上说,保留邻居列表表明存在一些结构(即两次迭代之间的大致相同)。速度恰恰相反,快速的演员意味着你没有结构。在非常快的演员的情况下,保持邻居名单可能是一个坏主意。
有关blob的技术细节。
你有两个blob,其中包含每个p=1%
个actor(大小s%
)(例如s = sK
)
您给自己的错误余量为1%
(例如e%
)和1%
步骤(例如10)
然后p:n
我的例子的真正价值是p <= [log(1-e^(1/n))]/[s*K²*log(1-s)]
!
如果s很小而K很大,那么你有p <= 0.989%
。如果不是这样,那么p要小得多!
答案 4 :(得分:1)
我会尝试什么。
Cover trees作为执行kNN的基础数据结构。特征:当数据的固有维数固定时,不需要欧几里德度量,线性空间使用,kNN /插入/删除都是O(log n)。非特征:动作。
要定期处理每个对象的移动对象,请删除其旧位置,插入新位置,然后找到kNN。
如果我们设置一个物体的周期与速度成反比,那么我们就知道覆盖树和现实之间的最大差异是由一个常数限制的。
答案 5 :(得分:0)
KD树允许您在一个点的固定半径内有效搜索。如果所有点的邻居都在 d1 单位内并且前一次测量中任何点的最大位移是 d2 ,那么您只需要在 d1 + d2内搜索单位。
如果您正在处理Minkowski距离,那么您可以使用David Mount's ANN library。我不确定,是否有一个可以使用任意距离函数的库。
答案 6 :(得分:0)
当演员在给定时间步长内移动的距离超过其最远的已知邻居的距离时,重新采样所有邻居。
另一个触发器:当自上一次重采样后Actor移动的距离超过距离最远的已知邻居的距离时,重新采样。
平凡优化在这里很顺利,如果存在层次空间索引,则搜索包含a)半径等于跳跃大小的球体的节点,以及b)至少N个Actors。