python - 从最大化最小距离的一组 3D 点中采样 N 个点
问题描述
(500, 3)
假设我有 500 个由数组表示的随机 3D 点:
import numpy as np
np.random.seed(99)
points = np.random.uniform(0, 10, (500, 3))
现在我想n = 20
从这 500 个点中采样点,使所有成对距离的最小值最大。我正在使用一种贪婪的方法来采样每次最大化最小距离的点。下面是我的 Python 实现:
from scipy.spatial import distance_matrix
def sample_n_points(points, n):
sampled_points = [points[0]]
remained_points = points[1:]
n_sampled = 1
while n_sampled < n:
min_dists = distance_matrix(remained_points, sampled_points).min(axis=1)
imax = np.argmax(min_dists)
sampled_points.append(remained_points[imax])
np.delete(remained_points, (imax), axis=0)
n_sampled += 1
return np.asarray(sampled_points)
print(sample_n_points(points, n=20))
输出:
[[6.72278559 4.88078399 8.25495174]
[1.01317279 9.74063145 0.15102072]
[5.21672436 0.39259574 0.1069965 ]
[9.89383494 9.77095442 1.15681204]
[0.77144184 9.99325146 9.8976312 ]
[0.04558333 2.34842151 5.25634324]
[9.58126175 0.57371576 5.01765991]
[9.93010888 9.959526 9.18606297]
[5.27648557 9.93960401 4.82093673]
[2.97622499 0.46695721 9.90627399]
[0.28351187 3.64220133 0.06793617]
[6.27527665 5.58177254 0.3544929 ]
[0.4861886 7.45547887 5.342708 ]
[0.83203965 5.00400167 9.40102603]
[5.21120971 2.89966623 4.24236342]
[9.18165946 0.26450445 9.58031481]
[5.47605481 9.4493094 9.94331621]
[9.31058632 6.36970353 5.33362741]
[9.47554604 2.31761252 1.53774694]
[3.99460408 6.17908899 6.00786122]]
但是,通过使用此代码,不能保证最佳解决方案。我的代码最明显的“错误”是它总是从对第一个点进行采样开始。当然,我可以使用每个点作为起点运行我的代码,最后采用最大化最小距离的那个,但即使这样也不会给出最佳解决方案。这些点在开始时彼此相距甚远,但随着采样的更多点被迫彼此靠近。经过一番思考,我意识到这个问题本质上变成了
在一组最均匀分布的 3D 点中找到子集。
我想知道是否有任何算法可以找到最佳解决方案或相对快速地给出一个好的近似值?
编辑
此优化问题的决策问题版本将是:
给定距离阈值t,是否有可能找到 n 个点的子集,使得子集中的每对点至少相距t 。
从图形的角度来看,这可以解释为
在欧几里得图中找到一个独立集,如果成对距离d ( v1,v2 ) ≤ t ,则点v1, v2在它们之间有一条边。
如果我们能解决这个决策问题,那么优化问题也可以通过对阈值t进行二分搜索来解决。
解决方案
希望我已经了解您的要求。
从你的开始:
from scipy.spatial import distance_matrix
import numpy as np
np.random.seed(99)
points = np.random.uniform(0, 10, (500, 3))
你应该得到所有点之间的距离并按距离排序:
# get distances between all points
d = distance_matrix(points, points)
# zero the identical upper triangle
dt = np.tril(d)
# list the distances and their indexes
dtv = [(dt[i, j], i, j) for (i, j) in np.argwhere(dt > 0)]
# sort the list
dtvs = sorted(dtv, key=lambda x: x[0], reverse=True)
然后,您可以增长 aset
以获得 20 个索引到有助于最大距离的点。
编辑以将结果限制为k
唯一点索引。
kpoint_index = set()
k = 20
i = 0
for p in (j for i in dtvs for j in i[1:]):
kpoint_index.add(p)
if len(kpoint_index) == k:
break
print("index to points:", kpoint_index)
给予:
index to points: {393, 11, 282, 415, 160, 302, 189, 319, 194, 453, 73, 74, 459, 335, 469, 221, 103, 232, 236, 383}
这运行得很快 - 但我没有计时。
推荐阅读
- r - 为什么 R 不能识别我添加到数据框中的新列?
- json - 如何根据下拉选择更新反应表
- php - LDAP 身份验证并使用 PHP 获取属性列表
- testng - Testng:错误:加载主类 org.testng.remote.RemoteTestNG 时发生 LinkageError
- android - gpu 找到了。供应商 id 10de 设备 if 0x1f07 检查错误的 AMD Vulkan 驱动程序版本
- powershell - 验证数字 1-100(do-while 循环)
- angular - 节点模块未安装
- tensorflow - 如何使用自定义 TF 回调打印出经过测试的 openai 健身房环境的状态?
- arrays - 是否可以并行排序几乎排序的数组?
- asp.net-mvc - 无法在 Visual Studio 2019 中调试 ASP.NET MVC 项目