寻找更好的算法来解决这种概率/组合游戏

时间:2011-11-08 02:50:11

标签: algorithm

假设我们有1到10的10个整数。

我们也有一些玩家,每个玩家都有不同的随机数。

现在玩家开始说出有关他或她号码的信息:我的号码在a subset of initial 1 to 10 set。例如my number is 8,9 or 10

我们想对那些没有说什么的球员做出假设(当然,对于给出初始信息的每个无声球员的假设是相同的)

让我们说我们有5名球员,前3名球员一个接一个地说:

  1. 我的是8,9或10
  2. 我的是7或6
  3. 我的是7,6,9或10
  4. 现在我们需要计算下一位玩家拥有特定数字的几率(概率),例如下一位玩家在7中拥有数字的几率。

    它只是一个当然的例子,每个玩家可以以任何形式提供信息(如1 or 101 through 10等)

    这是一个众所周知的问题,还是有人看到了一个好方法? 我真的希望这是高效的,所以强盗并不好。我认为它可以与贝叶斯定理直接相关,但不是100%确定它可以在这里应用。

    示例:

    简单案例2玩家和12345号码。第一位玩家有4或5。 然后对于第二个玩家,他有25%有1,但只有12.5%有4,因为在第一个玩家说出有关他手牌的信息后有2个可能的结果。

    1234或1235,我们可以看到1是(1/4 * 2) /2 =1/4而4是(1/4 * 1) / 2= 1/8 这就是我所说的蛮力解决方案,计算所有可能的组合并通过分析它们来推导出数概率。

    更新

    Mr.Wizard建议的解决方案。

    如果你好奇的话,这是代码:

    class Program
        {
            static void Main()
            {
                int length = 5;
                double[][] matrix = new double[length][];
                for (int i = 0; i < length; i++) {
                    matrix[i] = new double[length];
                }
    
                for (int i = 0; i < length; i++) {
                    for (int j = 0; j < length; j++) {
                        matrix[i][j] = 1;
                    }
                }
    
                matrix[0] = new double[] { 0, 0, 0, 1, 1 };
                matrix[1] = new double[] { 0, 0, 1, 1, 0 };
                matrix[2] = new double[] { 0, 0, 0, 0, 1 };
    
                DumpMatrix(matrix);
                while(true)
                {
                    NormalizeColumns(matrix);
                    DumpMatrix(matrix);
                    NormalizeRows(matrix);
                    DumpMatrix(matrix);
                    Console.ReadLine();
                }
            }
    
            private static void NormalizeRows(double[][] matrix)
            {
                for (int i = 0; i < matrix.Length; i++)
                {
                    double sum = matrix[i].Sum();
                    for (int j = 0; j < matrix.Length; j++) {
                        matrix[i][j] = matrix[i][j] / sum;
                    }
                }
            }
    
            private static void NormalizeColumns(double[][] matrix)
            {
                for (int j = 0; j < matrix.Length; j++)
                {
                    double columnSum = 0;
                    for (int i = 0; i < matrix.Length; i++)
                    {
                        columnSum += matrix[i][j];
                    }
                    for (int i = 0; i < matrix.Length; i++) {
                        matrix[i][j] = matrix[i][j] / columnSum;
                    }
                }
            }
    
            private static void DumpMatrix(double[][] matrix)
            {
                for (int i = 0; i < matrix.Length; i++) {
                    for (int j = 0; j < matrix.Length; j++) {
                        Console.Write(matrix[i][j].ToString("0.#####").PadRight(8));
                    }
                    Console.WriteLine();
                }
                Console.WriteLine();
            }
    
        }
    

    虽然从这个例子可以清楚地看出它接近最后的结果并不是很快。

    这里玩家3正好有5个,玩家一个和两个分别可以有4 or 53 or 4,这意味着玩家一个有4个因为玩家3得到5而玩家2有3个因为玩家2得到了但是,经过多次迭代后,我们在匹配列中为玩家1和2接近1值。

4 个答案:

答案 0 :(得分:4)

尝试构建一个图表,其中一方是玩家,另一方是数字。当且仅当玩家可以根据他们所说的内容获得该数字时,玩家和数字之间存在优势。对于每个边缘,您希望均匀随机完美匹配包含该边缘的概率。

不幸的是,如果这个问题有一个精确的多项式时间算法,那么#P,一个包含NP(实际上是整个polynomial hierarchyToda's theorem)的类是相等的到P。

至少在理论上,可以通过由Jerrum, Sinclair, and Vigoda引起的复杂算法来估计概率。我不确定有没有人实现过该算法。

答案 1 :(得分:2)

您应该构建probability tree diagram

对于你的例子:

__
  |___ 0.5 A=4 __
  |              |___ 0.25 B=1
  |              |___ 0.25 B=2
  |              |___ 0.25 B=3
  |              |___ 0.25 B=5
  |___ 0.5 A=5 __
                 |___ 0.25 B=1
                 |___ 0.25 B=2
                 |___ 0.25 B=3
                 |___ 0.25 B=4

树表示诸如p(B = 1 | A = 4)= 0.25

之类的语句

所以

  

p(B = 1 | A = 4或A = 5)= p(B = 1 | A = 4)+ p(B = 1 | A = 5)= 0.5 * 0.25 + 0.5 * 0.25 = 0.25 < / p>

  

p(B = 4 | A = 4或A = 5)= p(B = 4 | A = 4)+ p(B = 4 | A = 5)= 0 + 0.5 * 0.25 = 0.125

您可以在游戏的任何阶段动态地消耗树,并相应地计算每个假设的概率。

我认为,对于一般情况,没有捷径。

答案 2 :(得分:1)

我可能在这方面做得很好,但我认为每个行和列的重复规范化过程都会收敛到正确的值。

如果你从一个n * n矩阵开始,其中零代表不可能的东西,代表什么可以代表你的例子:

0   0   0   1   1
1   1   1   1   1
1   1   1   1   1
1   1   1   1   1
1   1   1   1   1

意思是,代表玩家#1的第1行只能是4或5,而其他任何事物都不知道。然后,如果我们将每行标准化为总和为1,我们得到:

0.  0.  0.  0.5 0.5
0.2 0.2 0.2 0.2 0.2
0.2 0.2 0.2 0.2 0.2
0.2 0.2 0.2 0.2 0.2
0.2 0.2 0.2 0.2 0.2

然后,对于每一栏:

0.      0.      0.      0.384615    0.384615
0.25    0.25    0.25    0.153846    0.153846
0.25    0.25    0.25    0.153846    0.153846
0.25    0.25    0.25    0.153846    0.153846
0.25    0.25    0.25    0.153846    0.153846

重复此过程15次,我们得到:

0.      0.      0.      0.5     0.5
0.25    0.25    0.25    0.125   0.125
0.25    0.25    0.25    0.125   0.125
0.25    0.25    0.25    0.125   0.125
0.25    0.25    0.25    0.125   0.125

如果原始参数不可能,则最终矩阵中的每一行和每列应总和为〜= 1.

我没有提供证据证明这是正确的,但如果您已经有一个强大的工作实施,那么应该很容易检查结果的相关性。

答案 3 :(得分:0)

目前还不确定具体的计算方法,但我认为你可以比完整的树更容易实现。

在简单的例子中: 有5个数字,你想知道B有3:

的概率
  • 总有4个可能的数字,因为已经有一个
  • 在任何情况下都不能使用3,所以无论A做什么,3都是4个数字中的一个。

从这些陈述中我们可以直接说出概率是1/4 = 25%

对于1和2它是相同的,对于4和5你只有50%的机会在池中出现数字,所以它减少到0.25 * 0.5 = 0.125


更大的例子: 如上所述,1到10,5名球员。

现在说你想知道6的可能性。

两个没有说什么的玩家都有相同的概率。 一个说他有一个6和25%,一个说他有一个6和50% 我现在还不确定这是怎么做到的,但你现在可以计算出其中一个人有6&#34;的概率。一个人有50%,另外25%加上它,它应该是60%或者其他东西。 (不只是添加它们......两次50%是一个很好的机会,但没有确定的命中。)

让我们假设这个例子是60%。现在我们有10个数字,其中有3个数字,我们有7个选择= 1 / 7~14%。 因此,对于任何可用的数字,我们有14%。但是现在6只是在池中的40%,所以我认为我们有0.14 * 0.4 = 0.056,这意味着5.6%我们有6。

无论您拥有什么信息,您都可以计算出您想要知道的数字的概率,以及确切地击中X左边的数字并将它们相乘的概率。