生成部分有序的随机数字列表
Posted
技术标签:
【中文标题】生成部分有序的随机数字列表【英文标题】:Generating a partially ordered random list of numbers 【发布时间】:2014-04-22 03:20:52 【问题描述】:我想生成一个大小为 500 的随机数列表,其中该列表正好 30% 排序(我知道如何生成一个至少 30% 排序的列表),但这不是我想要的,我该怎么做生成一个“正好” 30% 的文件?我卡住了,怎么办?
这里是确切的措辞 “对于排序,您应该构建三个不同大小的文件:有序、逆序的键,最后一个其中 30% 的键是有序的。后一个文件不应包含排序为 30% 的文件完整,而是在其中 30% 的键相对于彼此正确放置但不一定连续的文件中。
【问题讨论】:
30% 排序是什么意思,能举个例子吗? “30% 已排序”是什么意思?如果随机数列表已经按排序顺序出现怎么办? 我创建了一个包含 500 个随机数的列表。我随机取出 150 个数字到另一个数组中并对其进行排序,排序后我将其放回原始数组中。但这不是 Exactly 30%,至少是 30%,我该怎么做才能让它正好 30% 排序? 好的。你认为 500 个随机数的列表会有什么属性? 假设我给了你一个数字列表。您能否列出您将申请的测试,以确定它是否符合您的目的? 【参考方案1】:对于百分比排序,我可以看到 2 个主要想法:
只是元素数量不合适。
Once 应该能够通过排序获得估计的排序百分比,然后对其进行迭代,并保持每个元素与所需的概率百分比相同,否则将其与随机剩余元素交换(所以,如果我们想要30% 排序后,我们将以 30% 的概率保持元素相同,并以 70% 的概率将其交换)。
如果需要一个确切的数字,可以使用上述结果并(智能)交换随机元素,直到获得所需的百分比。
inversions的数量。
倒置是序列中的一对位置,其中这些位置上的元素不符合其自然顺序。
一个想法是首先对其进行排序,然后交换随机元素,使我们更接近所需的排序百分比,直到我们到达那里。
仅交换使我们更接近预期结果的元素是困难的(至少这样做很有效)。
一种非常暴力的方法是计算每对交换会导致的反转次数的变化,然后随机选择一个使我们更接近目标的次数。
李>另一个想法是只生成随机对并计算反转的数量,直到我们找到一个让我们更接近的。
第三个选项是选择一个随机元素。如果它大于元素的一半,请尝试将其向左移动(理想情况下增加反转次数)。如果它更小,请尝试将其向右移动。在尝试向左/向右移动时,我们可以(分别)寻找一个更小/更大的元素来交换它并计算反转的变化(我们只需要在计算反转的变化时考虑交换元素之间的元素) .
起初我们可能只是随机交换元素,因为我们可能倾向于更多的反转。
如果百分比高于 50%,我们也可以从一个反向数组开始,即 100% 未排序。
【讨论】:
【参考方案2】:存在将排列映射到 0 x 0, 1 x 0, 1, 2 x ... x 0, 1, ... n - 1 的一一对应关系,其中 codomain 中元组的第 j 个元素是涉及位置 j 和 i
这里有一个Gibbs sampling 的实例来解决这个问题。初始化一个元组求和到所需的排列数量。重复选择两个不同的索引,并在所有具有相同总和的可能性中均匀随机化。当你厌倦了等待时停下来(分布收敛于均匀但永远不会到达那里;也许明天我会找出一个 Propp--Wilson 风格的精确样本技术)。
在 Python 中(未经测试):
import random
def gibbs(n, target):
perm = [0] * n
for i in range(n):
perm[i] = min(target, i)
target -= i
assert target == 0
while ???:
i = random.randrange(n)
j = random.randrange(n)
if i == j: continue
total = perm[i] + perm[j]
perm[i] = random.randrange(max(total - j, 0), i + 1)
perm[j] = total - perm[i]
for j in range(n):
perm[j] = j - perm[j]
for i in range(j):
if perm[i] >= perm[j]: perm[i] += 1
return perm
也可以通过动态规划和条件概率获得精确的样本,但是从这里来看,500 的运行时间看起来有点令人望而却步。
【讨论】:
以上是关于生成部分有序的随机数字列表的主要内容,如果未能解决你的问题,请参考以下文章