简体   繁体   English

电源设置太慢 python

[英]Power Sets too slow python

I am using the following function to find the subsets of a list L. However, when converting the output of the function powerset into a list it takes way too long.我正在使用以下 function 来查找列表 L 的子集。但是,当将 function powerset 的output转换为长列表时,它需要的方式太长了。 Any suggestion?有什么建议吗?

For clarification, this powerset function does not output the empty subset and the subset L itself (it is intentional).为澄清起见,此powerset function 不 output 空子集和子集 L 本身(这是故意的)。

My list L:我的清单 L:

L = [0, 3, 5, 6, 8, 9, 11, 13, 16, 18, 19, 20, 23, 25, 28, 29, 30, 32, 33, 35, 36, 38, 42, 43, 44, 45, 49, 50, 51, 53, 54, 56, 57, 62, 63, 64, 65, 66, 67, 71, 76, 78, 79, 81, 82, 84, 86, 87, 90, 92, 96, 97, 98, 100, 107]

The code:编码:

def powerset(s):
    x = len(s)
    masks = [1 << i for i in range(x)]
    for i in range(1, (1 << x)-1):
        yield [ss for mask, ss in zip(masks, s) if i & mask]

my_Subsets = list(powerset(L)) # <--- THIS TAKES WAY TOO LONG

Your set has 55 elements.你的集合有 55 个元素。 Meaning 2^55=36028797018963968 subsets.意思是 2^55=36028797018963968 个子集。

There's no way, in any language, any algorithm to make that fast.在任何语言中,任何算法都无法做到这一点。 Because for each subset you need at least one allocation, and that single operation repeated 2^55 times will run forever.因为对于每个子集,您至少需要一个分配,并且重复 2^55 次的单个操作将永远运行。 For example if we were to run one allocation per nanosecond (in reality this is orders of magnitude slower) we are looking at something over a year (if my calculations are correct).例如,如果我们要每纳秒运行一次分配(实际上这要慢几个数量级),我们正在研究一年多的事情(如果我的计算是正确的)。 In Python probably 100 years.在 Python 大概 100 年。 :P :P

Not to mention that the final result is unlikely to fit in the entire world's data storage (ram + hard drives) currently available.更不用说最终结果不太可能适合目前可用的整个世界数据存储(ram + 硬盘驱动器)。 And definitely not in a single machine's storage.而且绝对不在一台机器的存储中。 And so final list(...) conversion will fail with 100% probability, even if you wait those years.所以最终list(...)转换将以 100% 的概率失败,即使你等待那些年。

Whatever you are trying to achieve (this is likely an XY problem) you are doing it the wrong way.无论您试图实现什么(这可能是一个 XY 问题),您都以错误的方式进行操作。

What you could do is create a class that will behave like a list but would only compute the items as needed and not actually store them:您可以做的是创建一个 class ,它的行为类似于列表,但只会根据需要计算项目而不实际存储它们:

class Powerset:

    def __init__(self,base):
        self.base = base

    def __len__(self):
        return 2**len(self.base)-2 # - 2 you're excluding empty and full sets

    def __getitem__(self,index):
        if isinstance(index,slice):
            return [ self.__getitem__(i) for i in range(len(self))[index] ]
        else:
            return [ss for bit,ss in enumerate(self.base) if (1<<bit) & (index+1)]


L = [0, 3, 5, 6, 8, 9, 11, 13, 16, 18, 19, 20, 23, 25, 28, 29, 30, 32, 33, 35, 36, 38, 42, 43, 44, 45, 49, 50, 51, 53, 54, 56, 57, 62, 63, 64, 65, 66, 67, 71, 76, 78, 79, 81, 82, 84, 86, 87, 90, 92, 96, 97, 98, 100, 107]


P = Powerset(L)

print(len(P)) # 36028797018963966
print(P[:10]) # [[0], [3], [0, 3], [5], [0, 5], [3, 5], [0, 3, 5], [6], [0, 6], [3, 6]]
print(P[3:6]) # [[5], [0, 5], [3, 5]]
print(P[-3:]) # [[5, 6, 8, 9, 11, 13, 16, 18, 19, 20, 23, 25, 28, 29, 30, 32, 33, 35, 36, 38, 42, 43, 44, 45, 49, 50, 51, 53, 54, 56, 57, 62, 63, 64, 65, 66, 67, 71, 76, 78, 79, 81, 82, 84, 86, 87, 90, 92, 96, 97, 98, 100, 107], [0, 5, 6, 8, 9, 11, 13, 16, 18, 19, 20, 23, 25, 28, 29, 30, 32, 33, 35, 36, 38, 42, 43, 44, 45, 49, 50, 51, 53, 54, 56, 57, 62, 63, 64, 65, 66, 67, 71, 76, 78, 79, 81, 82, 84, 86, 87, 90, 92, 96, 97, 98, 100, 107], [3, 5, 6, 8, 9, 11, 13, 16, 18, 19, 20, 23, 25, 28, 29, 30, 32, 33, 35, 36, 38, 42, 43, 44, 45, 49, 50, 51, 53, 54, 56, 57, 62, 63, 64, 65, 66, 67, 71, 76, 78, 79, 81, 82, 84, 86, 87, 90, 92, 96, 97, 98, 100, 107]]

Obviously, if the next thing you do is a sequential search or traversal of the powerset, it will still take forever.显然,如果你接下来要做的是顺序搜索或遍历 powerset,它仍然需要很长时间。

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

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