itertools删除等效元素

时间:2017-01-25 14:28:37

标签: python itertools symmetry

我在python中使用itertools生成所有vectors respecting some symmetry groups

基本上所有只是x,y,z轴和符号的排列。我不确定什么是确保等效载体不重复的最佳方法。

  1. 0 = -0因此[1, 2, 0]的签名应该只是[[1, 2, 0], [1, -2, 0], [-1, 2, 0], [-1, -2, 0]]
  2. itertools.permutations( 'AAB' )应该生成[('A', 'B', 'A'), ('B', 'A', 'A'), ('A', 'A', 'B')],即不通过交换等价A
  3. 来复制每个元素

    我目前的解决方案:

    删除dumplicate我将其传递给像set这样的lst = list(set(lst))。但是我不想制造大量垃圾,这些垃圾会在以后过滤掉。它也随意改变元素的顺序。此外,它可以创建只需要转换的形式可用元素(例如元组,但不是列表或numpy数组)。

    # using itertools.product and set filer
    def signPermut( t ):
        lst = []
        n = len(t)
        for signs in itertools.product( [-1,1], repeat=n):
            p = [ ti*si for ti,si in zip(t,signs) ]
            lst.append(tuple(p))
        #return lst
        return list(set(lst))
    

    此函数通过检查零来执行符号置换,但它可能非常低效:

    def permutSign( t ):
        lst = [ [] ]
        for c in t:
            lst_ = []
            if c != 0:
                for p in lst:
                    lst_.append(p+[ c]) 
                    lst_.append(p+[-c])
            else:
                for p in lst:
                    lst_.append( p+[c])
            lst = lst_
        return lst
    

    它正在工作,但我想也许有预制的东西...更高效,更简单和 pythonic

3 个答案:

答案 0 :(得分:2)

也许这有点像Pythonic:

import itertools

def signProducts(vector):
    svector = [[x,-x] if x != 0 else [x] for x in vector]
    return itertools.product(*svector)

#test:
v = [1,2,0]
for w in signProducts(v): print(w)

输出:

(1, 2, 0)
(1, -2, 0)
(-1, 2, 0)
(-1, -2, 0)

答案 1 :(得分:1)

如何创建带有标志的列表并使用itertools.product来表示:

from itertools import product

lst = [1, 2, 0]

signs = [(1, -1) if item != 0 else (1, ) for item in lst]
print(signs)  # [(1, -1), (1, -1), (1,)]

res = []
for sign in product(*signs):
    res.append([s*n for s, n in zip(sign, lst)])

print(res)  # [[1, 2, 0], [1, -2, 0], [-1, 2, 0], [-1, -2, 0]]

或一气呵成:

from itertools import product

sgn_lst =  [(n, -n) if n != 0 else (0, ) for n in lst]
print(sgn_lst)  # [(1, -1), (2, -2), (0,)]

res = []
for item in product(*sgn_lst):
    res.append(item)

print(res)  # [(1, 2, 0), (1, -2, 0), (-1, 2, 0), (-1, -2, 0)]
这样,循环内部的工作量就会减少很多。

答案 2 :(得分:0)

我认为无论你使用itertools,集合还是迭代器有多聪明,最重要的是以易于理解的方式编写代码,例如:为了更好地命名变量并且明显地增加向量,它不会受到伤害:

import itertools
import operator

def genAxes(n):
    return itertools.product((-1, 1), repeat=n)

def multiplyVectors(x, y):
    return itertools.imap(operator.mul, x, y)

def signPermutation(v):
    n = len(v)
    axes = genAxes(n)
    permut = map(lambda a: tuple(multiplyVectors(v, a)), axes)
    return list(set(permut))

v = [0, 1, 2]
print signPermutation(v)

这只是一个如何让我们更容易关注恕我直言的例子。