简体   繁体   English

枚举 Python 中标记球和标记箱问题中的所有可能组合

[英]Enumerate all possible combinations in labeled balls and labeled bins problem in Python

I'm looking for a Pythonic way of enumerating all possible options for the " labeled balls into labeled bins " problem.我正在寻找一种 Pythonic 方式来枚举“标记的球进入标记的箱子”问题的所有可能选项。 For example, given 2 labeled balls and 2 labeled bins I would like to get:例如,给定 2 个带标签的球和 2 个带标签的箱子,我想得到:

(A, B) (甲,乙)

(AB, ) (AB, )

(,AB) (,AB)

(B, A) (乙,甲)

That is (2^2) 4 options.即 (2^2) 4 个选项。 In case we give 3 balls and 3 bins, there are 27 possibilities 3^3.如果我们给出 3 个球和 3 个箱子,则有 27 种可能性 3^3。 For example:例如:

(A, B, C) (ABC, , ) (, , ABC) (AB, C, ) (C, , AB) (,BC, A) and so on... (A, B, C) (ABC, , ) (, , ABC) (AB, C, ) (C, , AB) (,BC, A) 等等...

I'm considering the solution (AB, ) and (BA, ) the same item.我正在考虑解决方案 (AB, ) 和 (BA, ) 相同的项目。

Counting the objects计算对象

These objects are also called k-partitions in many places.这些对象在很多地方也被称为 k 分区。

We could count them at first, and then use the counting methods to test if we're generating the right amount of objects.我们可以先对它们进行计数,然后使用计数方法来测试我们是否生成了正确数量的对象。

The Stirling numbers of the 2nd kind are counting the number of placements of n balls into b non-empty bins. 第二类斯特林数是计算n球放入b个非空箱的次数。

We can extend that to the following formula to allow for empty bins我们可以将其扩展到以下公式以允许空箱

\sum_{e=0}^{b} {b\choose e} S(n,be) (be)!

在此处输入图像描述

In the sum above, e represents the number of empty bins, so we're allowing between 0 and b empty bins, the term binomial(b,e) will account for any position of the empty bins, while the remaining be non-empty bins are counted by S(n,be) , but we still need to allow for all permutations of the non-empty bins which we're doing through (be)!在上面的总和中, e表示空 bin 的数量,因此我们允许0b个空 bin,术语binomial(b,e)将占空 bin 的任何 position, be其余为非空垃圾箱由S(n,be)计数,但我们仍然需要允许我们通过(be)! . .

We can count this using the following program:我们可以使用以下程序来计算:

#!/usr/bin/python3
from sympy import *
from sympy.functions.combinatorial.numbers import stirling

#
# Counting the number of ways to place n balls into b boxes, allowing
# for empty boxes.
#


def count_k_partitions(n,b):
    ans = 0
    for e in range(0,b+1):
        ans += binomial(b,e) * stirling(n,b-e,kind=2) * factorial(b-e)
    return ans

print("c(2,2):",count_k_partitions(2,2))
print("c(3,3):",count_k_partitions(3,3))
print("c(6,7):",count_k_partitions(6,7))

OUTPUT: OUTPUT:

c(2,2): 4
c(3,3): 27
c(6,7): 117649

See also:也可以看看:

  • This thread derives the same formula该线程得出相同的公式

  • These two threads discuss the probability of having e empty bins after placing the balls link1 , link2这两个线程讨论了放置球后有e空箱的概率link1 , link2

Generating the objects生成对象

Here is a recursive algorithm that generates the placements of balls into bins.这是一个递归算法,可生成将球放置到箱中的位置。 Each ball is placed in one of the bins, then the algorithm recurses further into the remaining balls to place the next ball.每个球被放置在一个箱子中,然后算法进一步递归到剩余的球中以放置下一个球。 When there are no more balls to place, we're printing the contents of all bins.当没有更多的球可以放置时,我们将打印所有垃圾箱的内容。

#!/usr/bin/python3
import string
import copy
#
# This generates all the possible placements of
# balls into boxes (configurations with empty boxes are allowed).
#
class BinPartitions:

    def __init__(self, balls, num_bins):
        self.balls = balls
        self.bins = [{} for x in range(num_bins)]

    def print_bins(self, bins):
        L = []
        for b in bins:
            buf = ''.join(sorted(b.keys()))
            L += [buf]
        print(",".join(L))

    def _gen_helper(self,balls,bins):
        if len(balls) == 0:
            self.print_bins(bins)
        else:
            A,B = balls[0],balls[1:]
            for i in range(len(bins)):
                new_bins = copy.deepcopy(bins)
                new_bins[i].update({A:1})
                self._gen_helper(B,new_bins)

    def get_all(self):
        self._gen_helper(self.balls,self.bins)

BinPartitions(string.ascii_uppercase[:3],3).get_all()
#BinPartitions(string.ascii_uppercase[:2],2).get_all()
#BinPartitions(string.ascii_uppercase[:3],3).get_all()
#BinPartitions(string.ascii_uppercase[:6],3).get_all()

OUTPUT: OUTPUT:

ABC,,
AB,C,
AB,,C
AC,B,
A,BC,
A,B,C
AC,,B
A,C,B
A,,BC
BC,A,
B,AC,
B,A,C
C,AB,
,ABC,
,AB,C
C,A,B
,AC,B
,A,BC
BC,,A
B,C,A
B,,AC
C,B,A
,BC,A
,B,AC
C,,AB
,C,AB
,,ABC

Other algorithms for generating the objects其他生成对象的算法

Partition-based algorithms: link1 ;基于分区的算法: link1 link2链接2

Knuth's Algorithm U: link1 ; Knuth 算法 U: link1 link2 ;链接2 link3链接3

All the code used in this post is also available here这篇文章中使用的所有代码也可以在这里找到

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM