对具有总和和最小值约束的实数进行采样
Sampling real numbers with sum and minimum value constraints
如何对 N 个随机值进行采样以满足以下约束条件?
- N 个值加起来为 1.0
- none 的值小于 0.01(或某个其他阈值 T << 1/N)
以下程序是我的第一次尝试。
def proportions(N):
proportions = list()
for value in sorted(numpy.random.random(N - 1) * 0.98 + 0.01):
prop = value - sum(proportions)
proportions.append(prop)
prop = 1.0 - sum(proportions)
proportions.append(prop)
return proportions
* 0.98 + 0.01
位旨在强制实施 ≥ 1% 约束。这适用于边距,但在内部不起作用——如果两个随机值的距离小于 0.01,则它不是 caught/corrected。示例:
>>> numpy.random.seed(2000)
>>> proportions(5)
[0.3397481983960182, 0.14892479749759702, 0.07456518420712799, 0.005868759570153426, 0.43089306032910335]
有什么建议可以修复这种损坏的方法或用更好的方法替换它吗?
这个呢?
- N/2 次,选择一个随机数 x 使得 1/N+x & 1/N-x 符合您的约束条件;添加 1/N+x & 1/N-x
- 如果 N 是奇数,则加 1/N
你可以适应 Mark Dickinson's nice solution:
import random
def proportions(n):
dividers = sorted(random.sample(range(1, 100), n - 1))
return [(a - b) / 100 for a, b in zip(dividers + [100], [0] + dividers)]
print(proportions(5))
# [0.13, 0.19, 0.3, 0.34, 0.04]
# or
# [0.31, 0.38, 0.12, 0.05, 0.14]
# etc
注意这假定 "none of the values is less than 0.01" 是一个固定阈值
UPDATE:如果我们取阈值的倒数并用它来替换建议代码中的 hard-coded 100
值,我们可以概括。
def proportions(N, T=0.01):
limit = int(1 / T)
dividers = sorted(random.sample(range(1, limit), N - 1))
return [(a - b) / limit for a, b in zip(dividers + [limit], [0] + dividers)]
如何对 N 个随机值进行采样以满足以下约束条件?
- N 个值加起来为 1.0
- none 的值小于 0.01(或某个其他阈值 T << 1/N)
以下程序是我的第一次尝试。
def proportions(N):
proportions = list()
for value in sorted(numpy.random.random(N - 1) * 0.98 + 0.01):
prop = value - sum(proportions)
proportions.append(prop)
prop = 1.0 - sum(proportions)
proportions.append(prop)
return proportions
* 0.98 + 0.01
位旨在强制实施 ≥ 1% 约束。这适用于边距,但在内部不起作用——如果两个随机值的距离小于 0.01,则它不是 caught/corrected。示例:
>>> numpy.random.seed(2000)
>>> proportions(5)
[0.3397481983960182, 0.14892479749759702, 0.07456518420712799, 0.005868759570153426, 0.43089306032910335]
有什么建议可以修复这种损坏的方法或用更好的方法替换它吗?
这个呢?
- N/2 次,选择一个随机数 x 使得 1/N+x & 1/N-x 符合您的约束条件;添加 1/N+x & 1/N-x
- 如果 N 是奇数,则加 1/N
你可以适应 Mark Dickinson's nice solution:
import random
def proportions(n):
dividers = sorted(random.sample(range(1, 100), n - 1))
return [(a - b) / 100 for a, b in zip(dividers + [100], [0] + dividers)]
print(proportions(5))
# [0.13, 0.19, 0.3, 0.34, 0.04]
# or
# [0.31, 0.38, 0.12, 0.05, 0.14]
# etc
注意这假定 "none of the values is less than 0.01" 是一个固定阈值
UPDATE:如果我们取阈值的倒数并用它来替换建议代码中的 hard-coded 100
值,我们可以概括。
def proportions(N, T=0.01):
limit = int(1 / T)
dividers = sorted(random.sample(range(1, limit), N - 1))
return [(a - b) / limit for a, b in zip(dividers + [limit], [0] + dividers)]