如何洗彩球?


10

我有400个球,其中100个是红色,40个是黄色,50个是绿色,60个是蓝色,70个是紫色,80个是黑色。(相同颜色的球是相同的)

我需要一种有效的改组算法,以便在改组后,球在列表中,并且

任何连续的3个球的颜色都不相同。例如,我不能有“红色,红色,红色,黄色...”

并且,所有排列都可能“相等地”发生。(好吧,如果效率与无偏之间的权衡足够好,那么我不介意比无偏有更多的效率)。

我试图改编Fisher-Yates-Knuth,但结果并不理想。

为什么Fisher-Yates不够好?FY采用蒙特卡洛逆变换。输出分配对相同的色球的处理方式有所不同,即它会为我的需求产生偏差的结果。

而且,天真的想法是从整个空间过滤/回溯所有不良排列。例如,当限制非常严格时,如果我们只有300个球,而其中100个是红色的,那么在获得适当的排列之前,将存在太多的反向跟踪/失败。

因此,最终,我希望能够迭代所有好的排列。但是,由于有效排列的数量太大,因此我只能随机抽样其中的一些。我想让其中“一些”的统计特征尽可能类似于人口。


3
您是否尝试根据其他问题改编答案?这两个问题看起来都很相似:)。
Gopi

@Gopi:是的,我希望每个问题的答案都能为另一个问题带来启发。
colinfang 2011年

我想到的最简单的想法是,开始从某种颜色中随机选择一个球,其中每种颜色的选择概率取决于剩余该颜色的球的数量,如果最后两个球具有相同的颜色,则不能在当前迭代中选择它。效率不应该太差,我看不到任何偏差(这并不意味着没有偏差;也许我错过了一些东西)。
乔治,

3
@乔治·B:我们经历了为什么这个过程确实对另一个相关问题有偏见正如David Eppstein在回答该问题时所解释的那样,有一种动态编程算法需要时间,其中k是颜色的数量。效率更高的东西会更好-即使是θ n k / 2θ(nk)kθ(nk/2)
彼得·索尔

2
@乔治B. 即使David Eppstein的方法更便宜,我也会对如何使用MCMC方法解决此问题感兴趣。
彼得·索尔

Answers:


7

马尔可夫链收敛到所有可能的球序列上的均等分布的前提是它是可逆的:从序列移到序列j的概率与在相反方向上移动的概率相同。因此,我建议您使用以下移动(以某种固定的概率分布来选择要进行的移动类型)对所有可能的序列执行马尔可夫链。在下文中,“游程”是相同颜色的球的最大长度的连续子序列。这条马尔可夫链依赖于至少三种颜色。ij

  1. 随机选择两个运行。如果您可以交换它们,但仍然有合法的顺序,请这样做。

  2. 选择两个相邻的运行。如果您可以交换它们,但仍然有合法的顺序,请这样做。

  3. 选择两个相同颜色的运行。在合法的可能范围内,将球重新随机分配(因此,如果单次运行的最大球数为3,并且在所选的两次运行中总共有5个球,则第一个可能获得2或3个球;如果总共有3个球,第一个平均可能得到1或2个球;如果总共有4个球,则1个,2个和3个球都有相同的可能性)。

  4. 随机选择一些颜色。考虑去除了所有颜色为C i的球的球序列S '。现在,在S '中随机选择两个点,相邻的不同颜色的球接触。CiSCiS

    一个。如果在原始序列S的这两个点上有两个颜色,并且两个颜色都不是最大长度,则将一个球从另一个移到另一个,每个方向的概率为½。CiS

    b。如果在原始序列S的这两点上有两个颜色,但一个是最大长度,另一个则不是,则将球从最大长度移动到较短的一个,概率为½。CiS

    C。如果在S的这两个点之一处只有一个颜色奔跑,则有½的可能性将一个球从奔跑移动到另一点。 CiS

    d。如果在这两个点上都没有颜色游标,或者在这两个点上都没有最大长度的游标,则什么也不做。Ci

如果我的分析是正确的,那么这是一条可逆的马尔可夫链,最终收敛到彩球合法序列的均匀分布,因此,如果将此链运行足够长时间,您将非常接近此均匀分布。

您怎么知道何时收敛?我建议您观察此序列的熵,并在它停止增加时停止。您如何计算熵?熵计算中有两个主要术语:行程长度的分布以及每次行程具有的颜色顺序。对于游程长度的分布,假设存在个颜色i的游程长度为k。这些对熵的贡献是 其中,是运行的最大允许长度。现在,让我们考虑颜色序列对熵的贡献。假设有ni,kikrmijijmii=0ilog2jmij

i log2 (kni,kni,1 ni,2  ni,r),
rmi,j放置了一系列颜色,紧接着是颜色(因此)。这对熵的贡献是 其中是颜色数。 ijmi,i=0c
i log2 (jmi,jmi,1 mi,2  mi,c),
c

(出于准确性的考虑,让我注意,我们省略了对熵的许多贡献,包括第一个球的颜色,但是这些是较低阶的术语,应该忽略不计。)

更新:

应该有加快速度的方法。我相信对于步骤c和d,您可以使用分析一次对所有一种颜色的运行执行这两个步骤。对于步骤a和b,这等效于找到一个随机的有色球序列的问题,其约束是没有两个同色球接触。应该有一些解决此问题的好的方法。然后,您仅需将a / b步与c / d步交替使用,其中每个步完全混合了这两个动作。我认为这应该收敛得很快,尽管对此马尔可夫链没有严格的分析。


0

如您所说,不可能确保每个排列的可能性均等,并不能确保颜色均匀分布,因为其中一个排列将所有红色连续排列。

确保颜色均匀分布的一种非常优雅但肯定不明显的方法是利用低差异序列。

假设您有球,编号为到,种子值为。N=4001Ns

确保所有相同颜色的球都已连续编号。也就是说,根据您的情况,让前100个球为红色,接下来的40个球为黄色,接下来的50个绿色,依此类推。

然后,将球的值分配为: 其中kthxk

xk=(s+kϕ)(mod1),
  • ϕ=1+52=1.61803399...,黄金分割率
  • 的操作者需要的参数的小数部分(mod1)
  • s是您想要的任何恒定的“种子”值。

也就是说,将为球中的每一个分配值,该值始终在0到1之间。Nxk

现在,只需根据值按升序对球进行排序。xk

例如,使用的种子值,将对球进行如下排序: s=0B K

{B,R,K,G,R,P,Y,K,B,R,P,G,K,R,B,Y,K,B,R,P,Y,K,B,R,P,G,R,P,Y,K,B,R,P,G,K,R,B,R,K,G,R,P,Y,K,B,R,P,G,K,R,P,Y,K,B,R,P,G,K,B,R,P,G,R,P,Y,K,B,R,P,G,K,R,B,R,K,G,R,P,Y,K,B,R,P,G,K,R,P,Y,K,B,R,P,G,K,R,B,R,K,G,R,P,Y,K,B,R,P,G,K,R,B,Y,K,B,R,P,Y,K,B,R,P,G,R,P,Y,K,B,R,P,G,K,R,B,R,K,G,R,P,Y,K,B,R,P,G,K,R,P,Y,K,B,R,P,G,K,B,R,K,G,R,P,Y,K,B,R,P,G,K,R,B,Y,K,G,R,P,Y,K,B,R,P,G,R,P,Y,K,B,R,P,G,K,R,B,R,K,G,R,P,Y,K,B,R,P,G,K,R,B,Y,K,B,R,P,Y,K,B,R,P,G,R,P,Y,K,B,R,P,G,K,R,B,R,K,G,R,P,Y,K,B,R,P,G,K,R,P,Y,K,B,R,P,G,K,R,B,R,K,G,R,P,Y,K,B,R,P,G,K,R,B,Y,K,B,R,P,Y,K,B,R,P,G,R,P,Y,K,B,R,P,G,K,R,B,R,K,G,R,P,Y,K,B,R,P,G,K,R,P,Y,K,B,R,P,G,K,B,R,P,G,R,P,Y,K,B,R,P,G,K,R,B,R,K,G,R,P,Y,K,B,R,P,G,R,P,Y,K,B,R,P,G,K,R,B,R,K,G,R,P,Y,K,B,R,P,G,K,R,B,Y,K,B,R,P,Y,K,B,R,P,G,R,P,Y,K,B,R,P,G,K,R,B,R,K,G,R,P,Y,K,B,R,P,G,K,R,P,Y,K,B,R,P,G,K}
(其中“B“ =蓝色,” “ =黑色)。K

最后,如果您希望采用其他样本,只需选择其他种子值。s

用于分配 Python代码如下:xk

n=400

phi = (1+pow(5,0.5))/2
x = np.zeros(n)                 
s = np.random.uniform(0,1)
for i in range(n):
    x = (s + phi*(i+1)) %1

print (s)
print (x)
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.