生成具有一定强度的随机桥手

时间:2014-09-16 01:54:45

标签: algorithm random

我正在尝试制作一个java程序来处理每只手中具有一定数量的高硬度(Aces,Kings,Queens和Jacks)的桥牌手(来自标准52卡包的13张牌)。

我正在查看以下帖子中提出的问题:https://math.stackexchange.com/questions/3205/choosing-subsets-of-a-set-such-that-the-subsets-satisfy-a-global-constraint,在下面添加:


我们有一套商品C =标准52卡片组中的卡片。这些项目中的每一个都具有我们称之为 p 的值:aces强度为4,kings强度为3,皇后2,jacks 1和所有其他卡0.我们要选择一个子集C,具有13张牌的桥牌,使得牌中物品的 p 值之和超过12.此外,我们希望有效地做到这一点。

我们希望在O(n)时间内完成此任务,但任何多项式时间算法都足够好。我们当然不希望只尝试13的C的每个可能的子集,然后检查它是否满足p值约束。


问题继续说我们希望所选择的子集在所有可能的这样的子集上是均匀随机分布,但是解决方案说这是NP完全的。但是,如果我不需要分配选定的卡片子组以完全统一呢?对我来说,有一个感觉随机的近似解决方案就足够了。有算法可以做到吗?

3 个答案:

答案 0 :(得分:1)

NP-complete与否,数字计算结果使得即使所有四只手的总p值被指定为罕见结果,也可以合理有效地产生交易。

一代策略如下。给定所有四只手的p值,对于2 ^ 16 = 65,536个高卡子集中的每一个,计算在East-West共同保持该子集的情况下存在多少可能性。使用BigInteger算法,根据可能性的数量生成一个随机子集,然后随机地将东西方的高牌在东西方之间划分,并随机分配南北高牌之间的南北高牌并进行交易其余的卡片。

给定一个子集EW,指定东西方持有的高牌,总和,在E的每个可接受的子集EW上指定东方持有的高牌,数量{{ 1}},即在East-West之间分割低牌的方法的数量,因为已知哪些牌由东西方持有。为南北做同样的计算。

对于(26 - |EW|) choose (13 - |E|)的每个选项,在东西和南北之间划分低卡的方法的数量是EW(36 choose (26 - |EW|))的抽样权重应该是这个数量乘以东西的分裂数乘以南北分裂的数量。

程序必须按照3 ^ 16 = 43,046,721的顺序进行处理,这对于计算机来说很多但不是很多。这是一个完全未调整的Python原型,需要大约一分钟才能完成。我希望,通过更好的Java实现,它只需要几分之一秒。

EW

答案 1 :(得分:0)

谁在乎NP是否完整?这种特殊情况仍然可行。

您可以使用标准动态编程解决方案来计算满足您条件的指针数量,然后将其还原以生成随机解决方案。当您继续前进时,您的状态是每个值的剩余卡数。 (每个卡位置只有256种可能的状态,所以这是非常可行的。)

请参阅all solutions to change making with dynamic programming了解如何恢复dp解决方案以选择随机示例。

答案 2 :(得分:0)

如链接问题所述,问题是NP完全,因为" P值"允许输入是任意的,因此甚至不清楚约束是否可满足。制作一系列HCP的桥牌手不是同一个问题。

产生满足约束的均匀分布的随机样本的通常解决方案是拒绝采样:产生均匀分布的随机样本,并且拒绝任何不满足约束的任何样本。此方法为O(n),但常量与满足约束概率的倒数成比例。

在具有12个或更多HCP的桥手的情况下,约束被满足的概率大约为35%,因此平均需要产生略少于三只手以找到满足约束的一只手。这可能是可以接受的。如果你试图用20或更多的HCP(概率1.4%)生成牌,你可能想要尝试一些不太精确的牌,尽管即使在那里你只需要平均生成70手牌,并且应该产生一手牌很快。

生成桥接手的最简单方法是使用油藏采样,在这种情况下,需要13个小的随机数来生成每只手。使用标准的64位PRNG(例如Mersenne twister),您可以从每个PRNG迭代中提取10个6位随机数。 (这适用于Mersenne twister,其中的位是不相关的。不要尝试使用C rand函数。)