通过设置重新排列for循环的顺序

时间:2015-09-19 07:52:42

标签: python numpy macros bitstring

我正在使用具有以下结构/条目的数组(对于量子信息游戏中的主人项目); 第一列条目{0,1},第二列{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

我使用以下函数构建此数组:

for-loops

现在我希望能够做到的,很容易选择列中的条目开始计数的顺序。 (从左侧的右侧列开始。)

例如,假设Id像第一列开始计数,然后是第3列,然后是第4列,最后是第2列。我可以通过置换函数中的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]]

给出了:

solution/approach

在函数中置换for循环的顺序,但是我必须编写24种不同的情况来覆盖所有的排列。任何人都知道一般来说会有更好的{{1}}?

3 个答案:

答案 0 :(得分:1)

你正在计算的东西被称为"笛卡尔积?"并且通过机会流行需求,标准库中的itertools module具有在没有所有显式循环的情况下构造它的功能。通过置换给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

答案 1 :(得分:0)

G的每一列都是由4个维度组成,分别扩展到2243个单位。这些4维度可以通过24种方式进行排列。要形成G的每一列,可以4 = 24方式使用permutations(24,4)10626置换维度中的10626个。

因此,如果我正确地完成了所有这些操作,您将拥有G10626个版本。因此,为了节省内存,使用循环来运行这些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) 方法是有意义的。这是实现所有谈话的实现 -

<textarea id="my_comp" class="tex_inp01" style="width:88%; height:100px; font-size:14pt;"></textarea>

答案 2 :(得分: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)}。