python - 一种快速计算非空区域的方法

标签 python performance algorithm

我正在编写一些代码,选择 n 个通过原点的 5 维随机超平面。然后,它在单位球体上均匀地随机采样 no_points 点,并计算超平面创建的区域中有多少至少有一个点。使用以下 Python 代码可以相对简单地完成此操作。

import numpy as np

def points_on_sphere(dim, N, norm=np.random.normal):
    """
    http://en.wikipedia.org/wiki/N-sphere#Generating_random_points
    """
    normal_deviates = norm(size=(N, dim))
    radius = np.sqrt((normal_deviates ** 2).sum(axis=0))
    points = normal_deviates / radius
    return points

n = 100
d = 5
hpoints = points_on_sphere(n, d).T
for no_points in xrange(0, 10000000,100000):
    test_points = points_on_sphere(no_points,d).T 
    #The next two lines count how many of the test_points are in different regions created by the hyperplanes
    signs = np.sign(np.inner(test_points, hpoints))
    print no_points, len(set(map(tuple,signs)))

不幸的是,我计算不同区域有多少点的天真方法很慢。总的来说,该方法需要 O(no_points * n * d) 时间,并且在实践中,一旦 no_points 达到大约 1000000,它就会太慢并且太耗 RAM .特别是它在 no_points = 900,000 时达到 4GB RAM。

是否可以更有效地完成此操作,以便 no_points 可以相当快地达到 10,000,000(实际上,如果它可以达到 10 倍,那就太好了)并且使用不到 4GB 的 RAM ?

最佳答案

存储每个测试点如何相对于每个超平面进行分类是大量数据。我建议对点标签进行隐式基数排序,例如,

import numpy as np


d = 5
n = 100
N = 100000
is_boundary = np.zeros(N, dtype=bool)
tpoints = np.random.normal(size=(N, d))
tperm = np.arange(N)
for i in range(n):
    hpoint = np.random.normal(size=d)
    region = np.cumsum(is_boundary) * 2 + (np.inner(hpoint, tpoints) < 0.0)[tperm]
    region_order = np.argsort(region)
    is_boundary[1:] = np.diff(region[region_order])
    tperm = tperm[region_order]
print(np.sum(is_boundary))

此代码保留测试点的排列 (tperm),以便同一区域中的所有点都是连续的。 boundary 指示每个点是否在排列顺序上与前一个不同的区域。对于每个连续的超平面,我们划分每个现有区域并有效地丢弃空区域以避免存储 2^100 个区域。

实际上,由于您有如此多的点而超平面却如此之少,因此不存储这些点更有意义。以下代码使用二进制编码将区域签名打包为两个 double 值。

import numpy as np


d = 5
hpoints = np.random.normal(size=(100, d))
bits = np.zeros((2, 100))
bits[0, :50] = 2.0 ** np.arange(50)
bits[1, 50:] = 2.0 ** np.arange(50)
N = 100000
uniques = set()
for i in xrange(0, N, 1000):
    tpoints = np.random.normal(size=(1000, d))
    signatures = np.inner(np.inner(tpoints, hpoints) < 0.0, bits)
    uniques.update(map(tuple, signatures))
print(len(uniques))

关于python - 一种快速计算非空区域的方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26179825/

相关文章:

python - 导入python包时跳过目录级别

c# - 限制每分钟、每个方法、每个 IP 对 WCF 服务的调用

C# 联合和数组复制

c - 如何在C中打印带有正确符号的等式

algorithm - 缩放和减少颜色以减小扫描文件的大小

python - 如何在 Statsmodels 中获得稳健回归 (RLM) 的 R 平方?

Python:在 isocalendar 或 strftime 或其他中定义周定义中的起始日

c++ - 通过安排任务最大化分数

python - 将抓取的数据导出到具有特定列的 CSV

java - 在 ArrayList 与 LinkedList 中间插入