为“ n”个布尔元素生成所有可能的排列,这些布尔元素最多具有“ m”个元素为1或True

时间:2019-03-06 15:49:15

标签: python algorithm permutation

我想生成一个最多包含两个'1'的4个元素的排列的完整列表。

例如,我有n = 4和m = 2:

我想要所有最多包含两个“ 1”的排列:

[1,0,0,0],[0,1,0,0],[0,0,1,0],[0,0,0,1],  [1,0,1,0],[0,0,1,1],[1,1,0,0],[1,1,0,0],[1,0,0,1]。 ..你明白了。

我试图生成所有排列的完整列表,然后执行SUM <3,然后将其提供给我。当n较小时,效果很好。问题是我需要在n> 30时这样做。

如您所见,迭代将达到2 ^ N,这是不可行的。

由于m较小(我处理的m小于5),所以与所有可能的组合相比,我只需要很小百分比的排列。 迭代的数量级变为N ^ M,因此在这种情况下为N ^ 5。

是否有一种简单的方法来生成此列表?

[编辑:至少写而不是最多写]

3 个答案:

答案 0 :(得分:0)

from itertools import permutations

l = list(permutations([0, 0, 1, 1]))

如果只需要唯一的,则可以将其包装在set中:

set(list(permutations([0, 0, 1, 1])))

如果您只担心计算排列/组合的数量,并且您无需在数据中使用排列的实际实例,只需使用数学即可。所有这些东西都有封闭形式的表达式,请参见combinatorics。

答案 1 :(得分:0)

长度为n且布尔值精确为m的布尔数组的排列集与{{1}的集合的m-组合的集合基本相同}}事物,即n返回的事物。 (在这种情况下,itertools.combinationsn真实值的索引。)

要获得 m个真值的排列,我们只需要将{{1}中m的{​​{1}}个值的组合链接在一起}},可以轻松地通过i完成:

i

将这些索引数组转换为布尔数组有点烦人,但仍然可行:

range(m + 1)

请注意,与您的示例不同,这包括不存在True值的情况。

可能功能过度的up_to_m_of_n_true可能更易读为:

itertools.chain.from_iterable

答案 2 :(得分:0)

不确定这是否符合您的效果期望,这是一种方法:

说明:

  1. n是我们将要生成的二进制序列的统一长度(例如5)。max_ones是最大数目的二进制序列(例如3)
  2. ones是有效排列之一中的1的数目。它的范围从0到max_ones
  3. 对于ones(例如ones == 3)的每个这样的有效值,通过取“种子”(例如(1,1,1,0,0))并进行迭代来生成该序列的排列,从而获得排列。 “种子”序列,最后,将该迭代器传递给set()(这样它会自动避免重复)。表达式(1,)*ones + (0,)*(n-ones)创建“种子”序列。
  4. 由于“ ones”的范围从0到max_ones,我们将获得许多这样的集合。我们最终chain()将所有这些集合在一起。

代码:

import itertools as itr

n = 4
max_ones = 2

my_all_atmost = set(itr.chain.from_iterable([set(itr.permutations(seed_row)) 
                                             for seed_row in {(1,)*ones + (0,)*(n-ones) 
                                                              for ones in range(0,max_ones+1)}]))

输出:(例如n == 4, max_ones == 2)的示例:

print (my_all_atmost)
{(1, 0, 0, 0), (1, 0, 1, 0), (1, 1, 0, 0), 
(0, 0, 0, 1), (1, 0, 0, 1), (0, 0, 1, 0), 
(0, 1, 0, 0), (0, 1, 1, 0), (0, 0, 0, 0), 
(0, 1, 0, 1), (0, 0, 1, 1)}