Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/341.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/algorithm/10.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 以最小最近邻距离和最大密度在三维空间中随机采样给定点_Python_Algorithm_Numpy_Random_Nearest Neighbor - Fatal编程技术网

Python 以最小最近邻距离和最大密度在三维空间中随机采样给定点

Python 以最小最近邻距离和最大密度在三维空间中随机采样给定点,python,algorithm,numpy,random,nearest-neighbor,Python,Algorithm,Numpy,Random,Nearest Neighbor,我在3D空间中有n点。我想随机采样所有最近邻距离大于r的点子集。子集m的大小未知,但我希望采样点尽可能密集,即最大化m 也有类似的问题,但都是关于生成点,而不是从给定点采样。 假设我有300个随机的3D点 import numpy as np n = 300 points = np.random.uniform(0, 10, size=(n, 3)) 在最大化m的同时,以最小最近邻距离r=1获取m点子集的最快方法是什么?这可能不会太快,但要迭代3D距离公式,附加到字典中,排序,然后获取id

我在3D空间中有
n
点。我想随机采样所有最近邻距离大于
r
的点子集。子集
m
的大小未知,但我希望采样点尽可能密集,即最大化
m

也有类似的问题,但都是关于生成点,而不是从给定点采样。

假设我有300个随机的3D点

import numpy as np
n = 300
points = np.random.uniform(0, 10, size=(n, 3))

在最大化
m
的同时,以最小最近邻距离
r=1
获取
m
点子集的最快方法是什么?

这可能不会太快,但要迭代3D距离公式,附加到字典中,排序,然后获取id

三维距离公式由点
(x,y,z)
(x1,y1,z1)
给出:


d
是总距离,
^0.5
是sqrt。)

可能有一个有效的双标准近似方案,但是当整数规划平均速度如此之快时,为什么还要麻烦呢

import numpy as np

n = 300
points = np.random.uniform(0, 10, size=(n, 3))

from ortools.linear_solver import pywraplp

solver = pywraplp.Solver.CreateSolver("SCIP")
variables = [solver.BoolVar("x[{}]".format(i)) for i in range(n)]
solver.Maximize(sum(variables))
for j, q in enumerate(points):
    for i, p in enumerate(points[:j]):
        if np.linalg.norm(p - q) <= 1:
            solver.Add(variables[i] + variables[j] <= 1)
solver.EnableOutput()
solver.Solve()
print(len([i for (i, variable) in enumerate(variables) if variable.SolutionValue()]))
将numpy导入为np
n=300
点=np.随机.均匀(0,10,大小=(n,3))
从ortools.linear_解算器导入pywraplp
solver=pywraplp.solver.CreateSolver(“SCIP”)
变量=[solver.BoolVar(“x[{}]”格式(i))表示范围(n)内的i]
最大化(求和(变量))
对于枚举中的j,q(点):
对于枚举中的i,p(点[:j]):

如果np.linalg.norm(p-q)这不是一个子集的最大值,但应该很接近,而不会花费很长时间,使用
KDTree
优化距离计算:

from scipy.spatial import KDTree
import numpy as np

def space_sample(n = 300, low = 0, high = 10, dist = 1):
    points = np.random.uniform(low, high, size=(n, 3))
    k = KDTree(points)
    pairs = np.array(list(k.query_pairs(dist)))
    
    def reduce_pairs(pairs, remove = []):  #iteratively remove the most connected node
        p = pairs[~np.isin(pairs, remove).any(1)]
        if p.size >0:
            count = np.bincount(p.flatten(), minlength = n)
            r = remove + [count.argmax()]
            return reduce_pairs(p, r)
        else:
            return remove
    
    return np.array([p for i, p in enumerate(points) if not(i in reduce_pairs(pairs))])

subset = space_sample()

迭代删除连接最紧密的节点不是最优的(保留300个点中的大约200个),但可能是接近最优的最快算法(唯一更快的是随机删除)。你可能会
@njit
减少\u对
以加快该部分的速度(如果我稍后有时间,将尝试)。

测试@David Eisenstat的答案,给出30分:

from ortools.linear_solver import pywraplp
import numpy as np

def subset_David_Eisenstat(points, r):
    solver = pywraplp.Solver.CreateSolver("SCIP")
    variables = [solver.BoolVar("x[{}]".format(i)) for i in range(len(points))]
    solver.Maximize(sum(variables))
    for j, q in enumerate(points):
        for i, p in enumerate(points[:j]):
            if np.linalg.norm(p - q) <= r:
                solver.Add(variables[i] + variables[j] <= 1)
    solver.EnableOutput()
    solver.Solve()
    indices = [i for (i, variable) in enumerate(variables) if variable.SolutionValue()]
    return points[indices]

points = np.array(
[[ 7.32837882, 12.12765786, 15.01412241],
 [ 8.25164031, 11.14830379, 15.01412241],
 [ 8.21790113, 13.05647987, 13.05647987],
 [ 7.30031002, 13.08276009, 14.05452502],
 [ 9.18056467, 12.0800735 , 13.05183844],
 [ 9.17929647, 11.11270337, 14.03027534],
 [ 7.64737905, 11.48906945, 15.34274827],
 [ 7.01315886, 12.77870699, 14.70301668],
 [ 8.88132414, 10.81243313, 14.68685022],
 [ 7.60617372, 13.39792166, 13.39792166],
 [ 8.85967682, 12.72946394, 12.72946394],
 [ 9.50060705, 11.43361294, 13.37866092],
 [ 8.21790113, 12.08471494, 14.02824481],
 [ 7.32837882, 12.12765786, 16.98587759],
 [ 8.25164031, 11.14830379, 16.98587759],
 [ 7.30031002, 13.08276009, 17.94547498],
 [ 8.21790113, 13.05647987, 18.94352013],
 [ 9.17929647, 11.11270337, 17.96972466],
 [ 9.18056467, 12.0800735 , 18.94816156],
 [ 7.64737905, 11.48906945, 16.65725173],
 [ 7.01315886, 12.77870699, 17.29698332],
 [ 8.88132414, 10.81243313, 17.31314978],
 [ 7.60617372, 13.39792166, 18.60207834],
 [ 8.85967682, 12.72946394, 19.27053606],
 [ 9.50060705, 11.43361294, 18.62133908],
 [ 8.21790113, 12.08471494, 17.97175519],
 [ 7.32837882, 15.01412241, 12.12765786],
 [ 8.25164031, 15.01412241, 11.14830379],
 [ 7.30031002, 14.05452502, 13.08276009],
 [ 9.18056467, 13.05183844, 12.0800735 ],])
检查最小距离:

from scipy.spatial.distance import cdist
dist = cdist(subset1, subset1, metric='euclidean')
# Delete diagonal
res = dist[~np.eye(dist.shape[0],dtype=bool)].reshape(dist.shape[0],-1)
print(np.min(res))
# Output: 1.3285513450926985
from scipy.spatial.distance import cdist
dist = cdist(subset2, subset2, metric='euclidean')
# Delete diagonal
res = dist[~np.eye(dist.shape[0],dtype=bool)].reshape(dist.shape[0],-1)
print(np.min(res))
# Output: 2.0612041004376223
将预期的最小距离更改为2:

subset2 = subset_David_Eisenstat(points, r=2.)
print(len(subset2))
# Output: 10
检查最小距离:

from scipy.spatial.distance import cdist
dist = cdist(subset1, subset1, metric='euclidean')
# Delete diagonal
res = dist[~np.eye(dist.shape[0],dtype=bool)].reshape(dist.shape[0],-1)
print(np.min(res))
# Output: 1.3285513450926985
from scipy.spatial.distance import cdist
dist = cdist(subset2, subset2, metric='euclidean')
# Delete diagonal
res = dist[~np.eye(dist.shape[0],dtype=bool)].reshape(dist.shape[0],-1)
print(np.min(res))
# Output: 2.0612041004376223

你对近似感兴趣还是结果必须是最优的?同样,这个问题也可以恰当地描述为“在一组欧几里德3D点的单位圆(球?)图中找到最大独立集”。作者在Jallu,R.K.&Das,G.K.“单位圆图上最大独立集的改进算法”中提出了这个问题(在2D中,意味着3D)是NP难的,引用了Garey,M.,Johnson,D.“计算机和难处理性:NP完全性理论指南”一书作为源。一个足够快的近似值对我来说是好的,不需要是最优的。我知道在给定300点的情况下,可能要花很长时间才能找到全局最优值。@Yatin没关系。我只是发现David的答案在最小距离不是1的情况下不起作用,所以不需要将第一次更新放回。我在答案中发布了一个新的更新谢谢,但我知道如何计算距离。我更喜欢使用
np.linalg.norm
:)OP在他们的问题(rev)中添加了一些细节,试图证明他们为什么接受你的答案。这是文章本身的元评论,不应该是问题的一部分(因此我删除了它)。因为输出来自运行代码,所以您可以将这些详细信息添加到您的答案中。这样所有相关方都会满意。你能检查一下我的新测试结果吗?由于某种原因,您的代码似乎仅在最小距离为1时有效。我尝试了您的代码。结果不错,但我花了很长时间从1000个点取样。此外,我需要一个明确计算距离的代码,因为在我的实际情况中,我需要考虑周期性边界条件。因此,我无法使用
KDTree
问题在于行
解算器。添加(变量[I]+变量[j]我明白了。现在它工作了