统一生成不同整数的随机对

时间:2018-01-10 21:40:38

标签: python numpy random probability

任务:

  • 生成一对随机数(i,j)(顺序无关紧要:(i,j)相当于(j,i))。
  • 该对必须包含两个不同的值:i != j
  • 对必须均匀分布。换句话说,所有可能的对的概率都相同。
  • 在恒定时间执行此操作。

第一次尝试

恒定时间? 即可。均匀分布?

x = np.random.randint(low=0, high=10 - 1)
y = np.random.randint(low=x + 1, high=10)

可视化样本(忽略顺序):

Samples visualization (not uniformly distributed)

您可以轻松地将y限制为大于x的效果,这意味着更高的对具有更高的概率(此处不透明度表示密度)。

第二次尝试

恒定时间? 即可。均匀分布?的

x = np.random.randint(low=0, high=nbr_values)
y = np.random.randint(low=0, high=nbr_values)

while x == y:
  y = np.random.randint(low=0, high=nbr_values)

可视化样本:

Samples visualization (uniformly distributed)

PS:这不是作业,我正在尝试使用交换操作使用随机邻居生成的随机优化技术。

3 个答案:

答案 0 :(得分:8)

这个怎么样?

x = np.random.randint(low=0, high=nbr_values)
y = np.random.randint(low=0, high=nbr_values - 1)
if y == x:
    y = nbr_values

x的值在所有可能的值中均匀分布,y的值在所有剩余的值中均匀分布,当前值为x代表最大值(也可以是最小值,在这种情况下只使用low=1)。

图形逼近:

range                 0 - - - - - - - - - - - - - MAX
distribution for x    + + + + + + + + + + + + + + +
random value for x                x
distribution for y    + + + + + +   + + + + + + + +
                                  \-------------->

0..5范围内随机分配1,000,000对

0       33425   33147   33411   33340   33365
33206   0       33537   33568   33679   33317
33307   33284   0       33423   33121   33189
33235   33303   32970   0       33347   33316
33233   33946   33257   33272   0       33504
33517   33203   33394   33221   32963   0

我们也可以将x max的所有值移至y,即y >= x,而不是将if y >= x: y += 1def draw(low, high, k): drawn = [] for i in range(k): y = random.randint(low, high - i) for x in sorted(drawn): if y >= x: y += 1 drawn.append(y) return drawn 进行交换,从而产生相同的分布。这样,通过将当前值与所有先前值进行比较并相应地将其向上移动,上述也可以推广到两个以上的值。这需要对绘制的值进行排序,因此复杂度要高一些,大约为O(k²logk)。

low

使用highk的小值以及1,000,000次迭代再次对此进行测试,结果看起来是正确的。

或者,您可以使用random.sample(range(low, high+1), k)。我不知道这是如何实现的,但是它非常快,即使对于上限的大值和接近最大值的select COALESCE(t1.State, t2.State, t3.State) AS 'State', max(t1.DMECount), max(t2.TransCount), Max(t3.ProCount) from #TestTable t1 FULL OUTER JOIN #TestTable2 t2 ON t1.State = t2.State FULL OUTER JOIN #TestTable3 t3 ON t2.State = t3.State GROUP BY COALESCE(t1.State, t2.State, t3.State) ORDER BY COALESCE(t1.State, t2.State, t3.State) 也是如此。

答案 1 :(得分:4)

我将上面的@tobias_k方法扩展为k值。

def uni_repl(n, k, s = 1000):
    x = np.empty((k, s), dtype = int)
    for i in range(k):
        x[i] = np.random.randint(low = 0, high = n - k + i + 1, size = s)
    for i in range(1, k):
        x[:i][x[:i] == x[i]] = n - k + i
    return x

测试:

test = np.zeros((5,5,5))

np.add.at(test, list(uni_repl(5, 3)), 1)

test
Out[85]: 
array([[[     0.,      0.,      0.,      0.,      0.],
        [     0.,      0.,  16304.,  16767.,  16622.],
        [     0.,  16418.,      0.,  16631.,  16517.],
        [     0.,  16688.,  16607.,      0.,  16495.],
        [     0.,  16663.,  16544.,  16877.,      0.]],

       [[     0.,      0.,  16736.,  16767.,  16668.],
        [     0.,      0.,      0.,      0.,      0.],
        [ 16862.,      0.,      0.,  16634.,  16632.],
        [ 16791.,      0.,  16689.,      0.,  16557.],
        [ 16566.,      0.,  16843.,  16864.,      0.]],

       [[     0.,  16737.,      0.,  16638.,  16437.],
        [ 16741.,      0.,      0.,  16545.,  16617.],
        [     0.,      0.,      0.,      0.,      0.],
        [ 16804.,  16923.,      0.,      0.,  16598.],
        [ 16756.,  16850.,      0.,  16778.,      0.]],

       [[     0.,  16777.,  16675.,      0.,  16760.],
        [ 16454.,      0.,  16792.,      0.,  16669.],
        [ 16476.,  16709.,      0.,      0.,  16677.],
        [     0.,      0.,      0.,      0.,      0.],
        [ 16680.,  16863.,  16640.,      0.,      0.]],

       [[     0.,  16459.,  16446.,  16756.,      0.],
        [ 16637.,      0.,  16626.,  16756.,      0.],
        [ 16481.,  16773.,      0.,  16762.,      0.],
        [ 16754.,  16531.,  16681.,      0.,      0.],
        [     0.,      0.,      0.,      0.,      0.]]])

与使用np.argpartition的方法相比,只要k < 0.4 * n

,这似乎更快
def uni_part(n, k, s = 1000):
    x = np.random.rand(n, s)
    return np.argpartition(x, k, axis = 0)[:k]

%timeit uni_part(100, 40)
100 loops, best of 3: 3.93 ms per loop

%timeit uni_repl(100, 40)
100 loops, best of 3: 3.76 ms per loop

%timeit uni_part(100, 10)
100 loops, best of 3: 3.55 ms per loop

%timeit uni_repl(100, 10)
1000 loops, best of 3: 425 µs per loop

%timeit uni_part(100, 50)
100 loops, best of 3: 4.08 ms per loop

%timeit uni_repl(100, 50)
100 loops, best of 3: 4.89 ms per loop

答案 2 :(得分:0)

从Numpy 1.7.0开始,您可以将np.choicereplace=False结合使用:

np.random.choice(10, 2, replace=False)
array([2, 6])

这是10000个样本的分布:

enter image description here