在空心方形薄片内生成随机均匀分布点的 Pythonic 方法 [英] Pythonic way to generate random uniformly distributed points within hollow square lamina

查看:53
本文介绍了在空心方形薄片内生成随机均匀分布点的 Pythonic 方法的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

假设我们有一个大小为 n 的中空方形薄片.也就是说,我们有一个 nxn 正方形,从中删除了一个 k*1 矩形(1<=k,l<=n-2).我想计算这种空心方形薄片内 2 个随机、均匀分布的点之间距离的平均值.为简单起见,让我们考虑 n=3、k=l=1 或一个 3x3 的正方形,其中心已经去除了一个单位正方形

Suppose we have a hollow square lamina of size n. That is, we have a nxn square from which a k*l rectangle has been removed (1<=k,l<=n-2). I want to calculate an average of distances between 2 random, uniformly distributed points within such hollow square lamina. For the sake of simplicity let's consider n=3, k=l=1, or a 3x3 square from whose center a unit square has been removed

我为 numpy 编写了这段代码,但它至少有 2 个问题:我必须丢弃大约 1/9 的所有生成的点并且删除 numpy.array 元素需要大量 RAM:

I wrote this code for numpy, but it has at least 2 problems: I have to throw away approximately 1/9 of all generated points and removing the numpy.array elements requires lots of RAM:

    x,y = 3*np.random.random((2,size,2))
x = x[
    np.logical_not(np.logical_and(
        np.logical_and(x[:,0] > 1, x[:,0] < 2),
        np.logical_and(x[:,1] > 1, x[:,1] < 2)
        ))
    ]
y = y[
    np.logical_not(np.logical_and(
        np.logical_and(y[:,0] > 1, y[:,0] < 2),
        np.logical_and(y[:,1] > 1, y[:,1] < 2)
        ))
    ]
n = min(x.shape[0], y.shape[0])

UPD:这里的size 是我要计算平均值的样本大小.有没有一种优雅的方法可以立即生成这些点,而不删除不合适的点?

UPD:Here size is the sample size of which I'm going to calculate average. Is there an elegant way to generate those points right away, without removing the unfit ones?

UPD:这里是完整的代码,仅供参考:

UPD: Here is the full code just for the reference:

def calc_avg_dist(size):
    x,y = 3*np.random.random((2,size,2))
    x = x[
        np.logical_not(np.logical_and(
        np.logical_and(x[:,0] > 1, x[:,0] < 2),
        np.logical_and(x[:,1] > 1, x[:,1] < 2)
        ))
    ]
    y = y[
        np.logical_not(np.logical_and(
        np.logical_and(y[:,0] > 1, y[:,0] < 2),
        np.logical_and(y[:,1] > 1, y[:,1] < 2)
        ))
    ]
    n = min(x.shape[0], y.shape[0])
    diffs = x[:n,:] - y[:n,:]
    return np.sum(np.sqrt(np.einsum('ij,ij->i',diffs,diffs)))/n

推荐答案

去掉中心后,有 8 个区域应该包含点.这些是它们的左下角:

With the center removed, there are 8 regions that should contain points. These are their lower-left corners:

In [350]: llcorners = np.array([[0, 0], [1, 0], [2, 0], [0, 1], [2, 1], [0, 2], [1, 2], [2, 2]])

这些区域是 1x1,因此它们具有相同的面积,并且包含给定随机点的可能性相同.下面选择size左下角:

The regions are 1x1, so they have the same area and are equally likely to contain a given random point. The following chooses size lower-left corners:

In [351]: corner_indices = np.random.choice(len(llcorners), size=size)

现在在单位正方形中生成size(x,y)坐标:

Now generate size (x,y) coordinates in the unit square:

In [352]: unit_coords = np.random.random(size=(size, 2))

将这些添加到之前选择的左下角:

Add those to the lower-left corners chosen previously:

In [353]: pts = unit_coords + llcorners[corner_indices]

pts 具有形状 (size, 2).这是一个情节,size = 2000:

pts has shape (size, 2). Here's a plot, with size = 2000:

In [363]: plot(pts[:,0], pts[:,1], 'o')
Out[363]: [<matplotlib.lines.Line2D at 0x11000f950>]

更新以解决更新的问题...

Update to address the updated question...

以下函数将上述想法推广到包含矩形空心的矩形形状.矩形仍然被认为是九个区域,中间区域是空心.随机点在区域内的概率由区域的面积决定;numpy.random.multinomial 用于选择每个区域的点数.

The following function generalizes the above idea to a rectangular shape containing a rectangular hollow. The rectangle is still considered to be nine regions, with the middle region being the hollow. The probability of a random point being in a region is determined by the area of the region; numpy.random.multinomial is used to select the number of points in each region.

(我确信这段代码有优化的空间.)

(I'm sure there is room for optimization of this code.)

from __future__ import division

import numpy as np


def sample_hollow_lamina(size, outer_width, outer_height, a, b, inner_width, inner_height):
    """
    (a, b) is the lower-left corner of the "hollow".
    """
    llcorners = np.array([[0, 0], [a, 0], [a+inner_width, 0],
                          [0, b], [a+inner_width, b],
                          [0, b+inner_height], [a, b+inner_height], [a+inner_width, b+inner_height]])
    top_height = outer_height - (b + inner_height)
    right_width = outer_width - (a + inner_width)
    widths = np.array([a, inner_width, right_width, a, right_width, a, inner_width, right_width])
    heights = np.array([b, b, b, inner_height, inner_height, top_height, top_height, top_height])
    areas = widths * heights
    shapes = np.column_stack((widths, heights))

    regions = np.random.multinomial(size, areas/areas.sum())
    indices = np.repeat(range(8), regions)
    unit_coords = np.random.random(size=(size, 2))
    pts = unit_coords * shapes[indices] + llcorners[indices]

    return pts

例如

In [455]: pts = sample_hollow_lamina(2000, 5, 5, 1, 1, 2, 3)

In [456]: plot(pts[:,0], pts[:,1], 'o', alpha=0.75)
Out[456]: [<matplotlib.lines.Line2D at 0x116da0a50>]

In [457]: grid()

请注意,参数不必是整数:

Note that the arguments do not have to be integers:

In [465]: pts = sample_hollow_lamina(2000, 3, 3, 0.5, 1.0, 1.5, 0.5)

In [466]: plot(pts[:,0], pts[:,1], 'o', alpha=0.75)
Out[466]: [<matplotlib.lines.Line2D at 0x116e60390>]

In [467]: grid()

这篇关于在空心方形薄片内生成随机均匀分布点的 Pythonic 方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆