我试图计算列表=[0,1,2,3,4,5,6]遵循一些约束的所有置换。在
在我当前的代码中,我通过应用约束来确定所有的置换和迭代。在
import itertools
Used_permutations = []
numbers = [0,1,2,3,4,5,6]
all_permutations = list(itertools.permutations(numbers)) #Determine all permutations
for permutation in all_permutations:
if permutation[0] > 3 and permutation[3] + permutation[5] < permutation[4]: #Constraints applied to permutations
Used_permutations.append(permutation)
####################################################
### Apply calculations to current permutation ###
####################################################
这段代码的问题是,我浪费时间寻找所有可能的排列,只是为了再次过滤掉它们。有人能帮助一种方法来应用约束,而排列是确定的,所以不是所有的N!有决心吗?在
您不必先创建所有排列的}生成的置换。在
list
,然后将其中的一些元素添加到第二个列表中并丢弃其余的元素(在本例中约为90%),您可以使用列表理解来过滤由{如果检查变得更复杂,您甚至不必使用列表理解。您可以在常规的
^{pr2}$for
循环中使用if
条件执行相同的操作,唯一的区别是不首先收集list
中的所有置换,而是直接迭代生成器:这两种方法仍然会产生所有的N!排列,但大多数都被立即丢弃,只有“正确”的排列才会被存储在列表中。在
如果您甚至不想生成它们,则必须实现一个自定义的递归
permutations
算法,并手动检查p[3]
的给定值是否存在p[5]
的任何有效值,依此类推。像这样:这在生成排列时检查这两个约束,以便例如,如果所有以数字
<= 3
开头的排列根本不会生成。第二个检查有点复杂,可能还需要进一步改进(如果我们在函数的开头添加一个计数器,就会发现有大约1200个递归调用)。不管怎样,使用IPython的%timeit
我们可以看到,使用动态检查的“手动”方法仍然比使用itertools
慢3倍,所以即使改进检查也不会使其更快。*)而且,实际上,您自己的原始循环也没有那么慢。在当然,根据输入列表和约束的大小,手动方法可以或多或少地节省开支,但也可能或多或少地难以实现或适应不断变化的约束。就个人而言,我仍然会使用
itertools.permutations
和一些简单易读的过滤器。在*)更新:在我之前的编辑中,手动方法出现得更快;这是因为我忘了实际使用这两个函数返回的生成器。在
相关问题 更多 >
编程相关推荐