gpt4 book ai didi

python - 在给定的点集中选择最远点的子集

转载 作者:太空狗 更新时间:2023-10-30 01:19:11 25 4
gpt4 key购买 nike

假设给定了 3 个维度中包含 n 个点的集合 S。任意两点之间的距离是简单的欧氏距离。你想从这个集合中选择 k 个点的子集 Q,使它们彼此相距最远。换句话说,不存在其他 k 个点的子集 Q',使得 Q 中所有成对距离的最小值小于 Q' 中的最小值。

如果 n 约为 1600 万,k 约为 300,我们如何有效地做到这一点?

我的猜测是,这个 NP-hard 问题可能是因为我们只想关注近似值。我能想到的一个想法是使用多维缩放将这些点排成一条直线,然后使用二进制搜索的版本来获取这条线上相距最远的点。

最佳答案

这被称为离散 p 色散 (maxmin) 问题。

最优界在 White (1991) 中得到证明和 Ravi et al. (1994)给出问题的因子 2 近似值,后者证明这种启发式是最好的(除非 P=NP)。

因子 2 近似

factor-2 近似如下:

Let V be the set of nodes/objects.
Let i and j be two nodes at maximum distance.
Let p be the number of objects to choose.
P = set([i,j])
while size(P)<p:
Find a node v in V-P such that min_{v' in P} dist(v,v') is maximum.
\That is: find the node with the greatest minimum distance to the set P.
P = P.union(v)
Output P

您可以像这样在 Python 中实现它:

#!/usr/bin/env python3

import numpy as np

p = 50
N = 400

print("Building distance matrix...")
d = np.random.rand(N,N) #Random matrix
d = (d + d.T)/2 #Make the matrix symmetric

print("Finding initial edge...")
maxdist = 0
bestpair = ()
for i in range(N):
for j in range(i+1,N):
if d[i,j]>maxdist:
maxdist = d[i,j]
bestpair = (i,j)

P = set()
P.add(bestpair[0])
P.add(bestpair[1])

print("Finding optimal set...")
while len(P)<p:
print("P size = {0}".format(len(P)))
maxdist = 0
vbest = None
for v in range(N):
if v in P:
continue
for vprime in P:
if d[v,vprime]>maxdist:
maxdist = d[v,vprime]
vbest = v
P.add(vbest)

print(P)

精确解

您也可以将其建模为 MIP。对于 p=50,n=400 6000 秒后,最优性差距仍为 568%。近似算法用了 0.47s 来获得 100%(或更少)的最优性差距。朴素的 Gurobi Python 表示可能如下所示:

#!/usr/bin/env python
import numpy as np
import gurobipy as grb

p = 50
N = 400

print("Building distance matrix...")
d = np.random.rand(N,N) #Random matrix
d = (d + d.T)/2 #Make the matrix symmetric

m = grb.Model(name="MIP Model")

used = [m.addVar(vtype=grb.GRB.BINARY) for i in range(N)]

objective = grb.quicksum( d[i,j]*used[i]*used[j] for i in range(0,N) for j in range(i+1,N) )

m.addConstr(
lhs=grb.quicksum(used),
sense=grb.GRB.EQUAL,
rhs=p
)

# for maximization
m.ModelSense = grb.GRB.MAXIMIZE
m.setObjective(objective)

# m.Params.TimeLimit = 3*60

# solving with Glpk
ret = m.optimize()

缩放

显然,初始点的 O(N^2) 缩放很糟糕。通过认识到这对必须位于数据集的凸包上,我们可以更有效地找到它们。这为我们提供了一种O(N log N) 的方法来找到这对。一旦我们找到它,我们就会像以前一样进行(使用 SciPy 进行加速)。

缩放的最佳方法是使用 R* 树有效地找到候选点 p 和集合 P 之间的最小距离。但这在 Python 中不能有效地完成,因为 for 循环仍然存在。

import numpy as np
from scipy.spatial import ConvexHull
from scipy.spatial.distance import cdist

p = 300
N = 16000000

# Find a convex hull in O(N log N)
points = np.random.rand(N, 3) # N random points in 3-D

# Returned 420 points in testing
hull = ConvexHull(points)

# Extract the points forming the hull
hullpoints = points[hull.vertices,:]

# Naive way of finding the best pair in O(H^2) time if H is number of points on
# hull
hdist = cdist(hullpoints, hullpoints, metric='euclidean')

# Get the farthest apart points
bestpair = np.unravel_index(hdist.argmax(), hdist.shape)

P = np.array([hullpoints[bestpair[0]],hullpoints[bestpair[1]]])

# Now we have a problem
print("Finding optimal set...")
while len(P)<p:
print("P size = {0}".format(len(P)))
distance_to_P = cdist(points, P)
minimum_to_each_of_P = np.min(distance_to_P, axis=1)
best_new_point_idx = np.argmax(minimum_to_each_of_P)
best_new_point = np.expand_dims(points[best_new_point_idx,:],0)
P = np.append(P,best_new_point,axis=0)

print(P)

关于python - 在给定的点集中选择最远点的子集,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48925086/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com