有效实施包容-排除

时间:2019-05-26 09:42:08

标签: python algorithm combinatorics

我正在尝试针对以下值有效实施inclusion-exclusion

2/5, 2/5, 2/10, 2/10, 2/15, 2/15, ...

当然,该程序不能无限长地运行,所以我想对术语数量设置可配置的限制。

例如,假设我将计算范围限制为:

2/5, 2/5, 2/10, 2/10

那么计算将是:

+ 2/5 + 2/5 + 2/10 + 2/10                  # choose 1 out of 4 terms
- 4/25 - 4/50 - 4/50 - 4/50 - 4/50 - 4/100 # choose 2 out of 4 terms
+ 8/250 + 8/250 + 8/500 + 8/500            # choose 3 out of 4 terms
- 16/2500                                  # choose 4 out of 4 terms

我发现以迭代方式“从y中选择x”有点复杂。

这是我当前的实现方式:

from decimal import Decimal
from decimal import getcontext

getcontext().prec = 100

def getBits(num):
    bit = 0
    bits = []
    while num > 0:
        if num & 1:
            bits.append(bit)
        bit += 1
        num >>= 1
    return bits

def prod(arr):
    res = Decimal(1)
    for val in arr:
        res *= val
    return res

SIZE = 20
sums = [Decimal(0) for k in range(SIZE)]
temp = [Decimal(2)/(5*k) for k in range(1,SIZE)]
probabilities = [p for pair in zip(temp,temp) for p in pair][:SIZE]

for n in range(1,1<<SIZE):
    bits = getBits(n)
    sums[len(bits)-1] += prod([probabilities[bit] for bit in bits])

total = 0
for k in range(SIZE):
    total += sums[k]*(-1)**k
print(total)

如您所见,我通过生成12 ** SIZE之间的每种可能的位组合,然后在{{1}中选择项,来“从y个词中选择x个” }数组,它们位于当前位组合中标记为probabilities的位置。

我本质上是在寻找一种更有效的方法,因为迭代次数以1的值呈指数增长。

我知道可能不可行,因为包含-排除表达式中的项总数在技术上是指数的(Pascal三角形中一行的总和)。

但是,由于SIZE中的值都是已知的并且是“不错的”(即2的幂除以5的乘积),因此我发现这里可能存在“快捷方式”,我忽略了。

非常感谢您提供任何想法!

0 个答案:

没有答案