我正在处理具有以下类型结构/条目的数组(用于量子信息游戏中的大师项目(;第一列条目{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
现在我想做的是,很容易地选择列中的条目开始计数的顺序。(从右栏到左。(
例如,我希望第一列开始计数,然后第三列,然后第四列,最后第二列。我可以通过在函数中排列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
吗?
您正在计算的东西被称为"笛卡尔乘积",根据chance的流行需求,标准库中的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
G
的每列由4个维度组成,分别扩展到2
、2
、4
和3
单元。这些CCD_ 17维度可以通过24种方式进行排列。为了形成G
的每一列,可以以permutations(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)
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
我认为你的问题存在前后矛盾的问题。我想你指的是第三列{0,2**(d-1(-1},而不是{0,2***(d-1,d-1(}。