Python 使用设置重新排列for循环的顺序

Python 使用设置重新排列for循环的顺序,python,numpy,macros,bitstring,Python,Numpy,Macros,Bitstring,我正在使用具有以下类型结构/条目的阵列(用于量子信息游戏的大师级项目); 第一列条目{0,1},第二列{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

我正在使用具有以下类型结构/条目的阵列(用于量子信息游戏的大师级项目); 第一列条目
{0,1}
,第二列
{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
现在我想做的是,轻松选择列中的条目开始计数的顺序。(位于其上方,从右栏到左。)

例如,假设我希望第一列开始计数,然后是第三列,然后是第四列,最后是第二列。我可以通过在函数中为循环排列
来实现这一点:

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种不同的情况来涵盖所有排列。任何人都知道通常更好的
解决方案/方法是什么?

每列
G
由4个维度组成,分别扩展到
2
2
4
3
单位。这些
4
维度可以以24种方式排列。为了形成
G
的每一列,可以以
置换(24,4)
=
10626
的方式使用那些
24
置换维度中的任何
4

因此,如果我正确理解了所有这些,您将拥有
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)

我认为你的问题有一个前后矛盾的问题。我想你指的是第三列{0,2**(d-1)-1},而不是{0,2**(d-1)}。

你正在计算的东西被称为“笛卡尔积”,碰巧来自标准库的流行需求有一个函数来构造它,而不需要所有显式循环。通过排列给定给
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(范围(4))
可以轻松获得所有可能的置换


作为奖励,这里有一种方法可以让这个操作执行得更快,只需Numpy(对于更大的
d
):


那不是应该是24个排列吗?你是对的,谢谢,关于编程有什么想法吗?好吧,看起来你会有
10626
这样的方法来做。看起来你只是排列列的顺序,很难判断你使用的复杂数组,请再看一看我原来的问题。@balletpiraat看看编辑后的答案是否有意义,是否对你有用?非常感谢,这太棒了!
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
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