4

我正在使用具有以下结构/条目的数组(用于量子信息游戏中的硕士项目);第 1 列条目{0,1},第 2 列{0,1},第 3 列{0,2**(d-1)},最后列{0,d-1}。如下d=3

G = 
[[0 0 0 0]
 [0 0 0 1]
 [0 0 0 2]
 [0 0 1 0]
 [0 0 1 1]
 [0 0 1 2]
 [0 0 2 0]
 [0 0 2 1]
 [0 0 2 2]
 [0 0 3 0]
 [0 0 3 1]
 [0 0 3 2]
 [0 1 0 0]
 [0 1 0 1]
 [0 1 0 2]
 [0 1 1 0]
 [0 1 1 1]
 [0 1 1 2]
 [0 1 2 0]
 [0 1 2 1]
 [0 1 2 2]
 [0 1 3 0]
 [0 1 3 1]
 [0 1 3 2]
 [1 0 0 0]
 [1 0 0 1]
 [1 0 0 2]
 [1 0 1 0]
 [1 0 1 1]
 [1 0 1 2]
 [1 0 2 0]
 [1 0 2 1]
 [1 0 2 2]
 [1 0 3 0]
 [1 0 3 1]
 [1 0 3 2]
 [1 1 0 0]
 [1 1 0 1]
 [1 1 0 2]
 [1 1 1 0]
 [1 1 1 1]
 [1 1 1 2]
 [1 1 2 0]
 [1 1 2 1]
 [1 1 2 2]
 [1 1 3 0]
 [1 1 3 1]
 [1 1 3 2]]

我正在使用以下函数来构建这个数组:

def games(d = 3):
    res = np.empty(0).astype(int)
    for a in range(2):
        for b in range(2):
            for x in range(2**(d-1)):
                for y in range(d):
                    res = np.append(res,[a,b,x,y],axis=0)
    res = np.reshape(res,(-1,4))    
    return res

现在我想做的是轻松选择列中条目开始计数的顺序。(从右列到左上方。)

例如,说我喜欢从第 1 列开始计数,然后是第 3 列,然后是第 4 列,最后是第 2 列。for-loops我可以通过在函数中置换来得到这个:

def games(d = 3):
    res = np.empty(0).astype(int)

    for b in range(2):
        for y in range(d):        
            for x in range(2**(d-1)):
                for a in range(2):
                    res = np.append(res,[a,b,x,y],axis=0)
    res = np.reshape(res,(-1,4))    
    return res

这使:

G=
[[0 0 0 0]
 [1 0 0 0]
 [0 0 1 0]
 [1 0 1 0]
 [0 0 2 0]
 [1 0 2 0]
 [0 0 3 0]
 [1 0 3 0]
 [0 0 0 1]
 [1 0 0 1]
 [0 0 1 1]
 [1 0 1 1]
 [0 0 2 1]
 [1 0 2 1]
 [0 0 3 1]
 [1 0 3 1]
 [0 0 0 2]
 [1 0 0 2]
 [0 0 1 2]
 [1 0 1 2]
 [0 0 2 2]
 [1 0 2 2]
 [0 0 3 2]
 [1 0 3 2]
 [0 1 0 0]
 [1 1 0 0]
 [0 1 1 0]
 [1 1 1 0]
 [0 1 2 0]
 [1 1 2 0]
 [0 1 3 0]
 [1 1 3 0]
 [0 1 0 1]
 [1 1 0 1]
 [0 1 1 1]
 [1 1 1 1]
 [0 1 2 1]
 [1 1 2 1]
 [0 1 3 1]
 [1 1 3 1]
 [0 1 0 2]
 [1 1 0 2]
 [0 1 1 2]
 [1 1 1 2]
 [0 1 2 2]
 [1 1 2 2]
 [0 1 3 2]
 [1 1 3 2]]

在函数中排列 for 循环的顺序是可行的,但我必须编写 24 种不同的情况来涵盖所有排列。任何人都知道通常会更好solution/approach吗?

4

3 回答 3

1

您正在计算的东西称为“笛卡尔积”,并且偶然流行的需求标准库中的itertools 模块具有构建它的功能,而无需所有显式循环。通过排列给定的参数itertools.product的顺序,确定列计数顺序。唯一剩下要做的就是将列重新排列回所需的顺序,但这很容易用 Numpy 完成。

import itertools

def make_games(d=3, perm=[3,2,1,0]):
    entries = [range(2),
               range(2),
               range(2**(d-1)),
               range(d)]
    # Python3 compatibility
    entries = [list(entry) for entry in entries]

    # Cartesian product with columns count-order by `perm`
    permuted_entries = [entries[px] for px in perm[::-1]]
    games_list = list(itertools.product(*permuted_entries))

    # Move the columns around to the original ordering
    sorter = np.argsort(perm[::-1])
    games = np.take(games_list, sorter, axis=1)

    return games

作为示例给出的输出现在可以通过调用来获得make_games(3, [0, 2, 3, 1])。此外,现在可以通过循环轻松获得所有可能的排列itertools.permutations(range(4))


作为奖励,这是一种仅使用 Numpy(对于较大的d)使此操作执行得更快的方法:

def make_games_np(d=3, perm=[3,2,1,0]):
    entries = [range(2),
               range(2),
               range(2**(d-1)),
               range(d)]
    # Python3 compatability
    entries = [list(entry) for entry in entries]

    n = len(entries)
    entries_grid = np.array(np.meshgrid(*entries, indexing='ij'))
    entries_grid = np.rollaxis(entries_grid, 0, n+1)

    order = list(perm)[::-1] + [n]
    games = entries_grid.transpose(*order).reshape(-1, n)

    return games
于 2015-09-20T09:20:59.253 回答
0
import numpy as np
import itertools

def games(d=3):
    res_list=[]
    a=list(itertools.permutations([2,2,2**(d-1),d],4))
    for index in range(len(a)):
        res=np.empty(0).astype(int)
        for i in range(a[index][0]):
            for j in range(a[index][1]):
                for p in range(a[index][2]):
                    for q in range(a[index][3]):
                        res=np.append(res,[i,j,p,q],axis=0)
        res=np.reshape(res,(-1,4))
        res_list.append(res)
    return res_list

我认为您的问题存在不一致问题。我认为您的意思是第 3 列 {0,2**(d-1)-1} 而不是 {0,2**(d-1)}。

于 2015-09-19T09:43:53.487 回答
0

的每一列G由 4 个维度组成,这些维度分别延伸到、2和单位。这些维度可以以 24 种方式排列。要形成 的每一列,可以使用=方式中的任何置换维度。2434G424permutations(24,4)10626

因此,如果我正确理解了所有这些,那么您将拥有10626这样的G版本。10626因此,为了节省内存,使用循环来运行这些方式是有意义的。这是完成所有谈话的实现 -

import itertools

# Create meshes with upto 2,2,4,3 numbers as is the case across G columns
D0,D1,D2,D3 = np.meshgrid(np.arange(2),np.arange(2),np.arange(4),np.arange(3))

# All possible dimension arrangements with 4 dimensions for each of D0,D1,D2,D3
dims = np.asarray(list(itertools.permutations(range(4))))

# All possible arrangements considering the dimension arrangements
dims_row_idx = np.asarray(list(itertools.combinations(range(dims.shape[0]),4)))

# Use dims_row_idx to select rows of dims and subsequently 
# permute dimensions of D0,D1,D2,D3 and stack them as columns
for d in dims_row_idx:
    c0 = D0.transpose(dims[d[0]]).ravel()
    c1 = D1.transpose(dims[d[1]]).ravel()
    c2 = D2.transpose(dims[d[2]]).ravel()
    c3 = D3.transpose(dims[d[3]]).ravel()
    out = np.column_stack((c0,c1,c2,c3))
    # print(out)
于 2015-09-19T08:28:06.470 回答