二维 Numpy 中的所有二进制组合
All binary combinations in a 2d Numpy
我正在尝试创建一个代码,该代码可以在 numpy 矩阵中生成 0 和 1 的所有可能组合,不包括旋转。
旋转是什么意思?我的意思是下面的矩阵数据实际上是相同的,因为它具有相同的数据但旋转了 90º、180º 和 270º。
我一直在尝试下面的代码,但我认为我没有得到所有的组合,而且我还遗漏了一些组合。你知道这是否是正确的方法吗?你知道有没有更有效的方法?
例如,考虑 dx=3 和 dy=3
import numpy as np
def myfunction(data)
print(data)
dx=3
dy=3
data = np.zeros([dx, dy], dtype=np.uint8)
y=0
for x in range(dx):
for r in range(2):
data[x, y] = r
myfunction(data)
for y in range(dy):
for s in range(2):
data[x, y] = s
myfunction(data)
非常感谢!
我不确定我的回答是否是最有效的方式,但无论如何。
我们可以使用 numpy.rot90
函数旋转每个矩阵。
让我们创建两个不同的字典,一个用于存储主矩阵,另一个用于存储主矩阵的旋转,这样我们就可以验证一个新矩阵是否只是先前找到的矩阵的旋转。
def Not_Rotated(dx, dy):
import numpy as np
from itertools import product
Big_Matrix = np.array([[list(i[x:x+dx]) for x in range(0, len(i), dx)] for i in product("01", repeat=dx*dy)]) # Stores all possible combinations
Main = dict() # Stores not rotated
Main_c = 0
Rotations = dict() # Stores rotated
Rotation_c = 0
for i in range(len(Big_Matrix)): # Going through all combinations
flag = 1 # A flag to check if this combination is rotated of previous ones or not. 1= is not rotated of previous ones. 0 = is rotated.
for z in range(Rotation_c):
if np.array_equal(Big_Matrix[i],Rotations[z]): # Checking if this combination is rotated of previous ones or not
flag = 0
if flag: # If this combination is not a rotation of previous ones
Main[Main_c] = Big_Matrix[i]
# Rotate it three times and store the matrices
Rotations[Rotation_c] = np.rot90(Main[Main_c])
Rotations[Rotation_c + 1] = np.rot90(Main[Main_c])
Rotations[Rotation_c + 2] = np.rot90(Main[Main_c])
Rotation_c += 3
Main_c += 1
return Main
这是一个适用于小矩阵大小的矢量化解决方案;代码中的注释说明了 3 x 3 的情况:
def get_binary_mats(n):
# all possible n by n binary matrices up to rotation:
bin_mats = (np.bitwise_and(np.arange(2**(n*n))[:,None], 2 ** np.arange(n*n)) > 0)\
.reshape(-1, n, n)
# define a score for each matrix based on position of ones
score = 2 ** np.arange(n*n).reshape(n,n)
# array([[ 1, 2, 4],
# [ 8, 16, 32],
# [ 64, 128, 256]])
score_arr = np.stack([np.rot90(score, k=k) for k in range(4)])
# array([[[ 1, 2, 4],
# [ 8, 16, 32],
# [ 64, 128, 256]],
# [[ 4, 32, 256],
# [ 2, 16, 128],
# [ 1, 8, 64]],
# [[256, 128, 64],
# [ 32, 16, 8],
# [ 4, 2, 1]],
# [[ 64, 8, 1],
# [128, 16, 2],
# [256, 32, 4]]])
scores = np.einsum("ijk,ljk->il", bin_mats, score_arr)
_, idx = np.unique(scores.min(1), return_index=True)
return bin_mats[idx,...]
主要思想是我们可以对 N×N 二进制矩阵与 N×N 矩阵进行“点积”,该矩阵由 2 的前 N^2 次幂组成(我将后者称为得分矩阵)。当我们这样做时,我们为每个可能的二进制矩阵得到一个唯一的整数。
为了考虑旋转,我们可以采用“分数”矩阵的 4 次旋转的“点积”,并将每个二进制矩阵与四个结果中的最小值相关联。我们可以将这个最小值称为二进制矩阵的分数。
最后,我们可以用 np.unique
为每个唯一分数选择一个矩阵。例如,这里是 n = 2 的输出:
array([[[False, False],
[False, False]],
[[ True, False],
[False, False]],
[[ True, True],
[False, False]],
[[False, True],
[ True, False]],
[[ True, True],
[ True, False]],
[[ True, True],
[ True, True]]])
作为健全性检查,旋转的二进制矩阵的数量与 this OEIS sequence 一致,n 最多为 5:
%time assert [get_binary_mats(k).shape[0] for k in range(1, 6)] == [2, 6, 140, 16456, 8390720]
# takes 20 seconds on my machine
我正在尝试创建一个代码,该代码可以在 numpy 矩阵中生成 0 和 1 的所有可能组合,不包括旋转。 旋转是什么意思?我的意思是下面的矩阵数据实际上是相同的,因为它具有相同的数据但旋转了 90º、180º 和 270º。
我一直在尝试下面的代码,但我认为我没有得到所有的组合,而且我还遗漏了一些组合。你知道这是否是正确的方法吗?你知道有没有更有效的方法?
例如,考虑 dx=3 和 dy=3
import numpy as np
def myfunction(data)
print(data)
dx=3
dy=3
data = np.zeros([dx, dy], dtype=np.uint8)
y=0
for x in range(dx):
for r in range(2):
data[x, y] = r
myfunction(data)
for y in range(dy):
for s in range(2):
data[x, y] = s
myfunction(data)
非常感谢!
我不确定我的回答是否是最有效的方式,但无论如何。
我们可以使用 numpy.rot90
函数旋转每个矩阵。
让我们创建两个不同的字典,一个用于存储主矩阵,另一个用于存储主矩阵的旋转,这样我们就可以验证一个新矩阵是否只是先前找到的矩阵的旋转。
def Not_Rotated(dx, dy):
import numpy as np
from itertools import product
Big_Matrix = np.array([[list(i[x:x+dx]) for x in range(0, len(i), dx)] for i in product("01", repeat=dx*dy)]) # Stores all possible combinations
Main = dict() # Stores not rotated
Main_c = 0
Rotations = dict() # Stores rotated
Rotation_c = 0
for i in range(len(Big_Matrix)): # Going through all combinations
flag = 1 # A flag to check if this combination is rotated of previous ones or not. 1= is not rotated of previous ones. 0 = is rotated.
for z in range(Rotation_c):
if np.array_equal(Big_Matrix[i],Rotations[z]): # Checking if this combination is rotated of previous ones or not
flag = 0
if flag: # If this combination is not a rotation of previous ones
Main[Main_c] = Big_Matrix[i]
# Rotate it three times and store the matrices
Rotations[Rotation_c] = np.rot90(Main[Main_c])
Rotations[Rotation_c + 1] = np.rot90(Main[Main_c])
Rotations[Rotation_c + 2] = np.rot90(Main[Main_c])
Rotation_c += 3
Main_c += 1
return Main
这是一个适用于小矩阵大小的矢量化解决方案;代码中的注释说明了 3 x 3 的情况:
def get_binary_mats(n):
# all possible n by n binary matrices up to rotation:
bin_mats = (np.bitwise_and(np.arange(2**(n*n))[:,None], 2 ** np.arange(n*n)) > 0)\
.reshape(-1, n, n)
# define a score for each matrix based on position of ones
score = 2 ** np.arange(n*n).reshape(n,n)
# array([[ 1, 2, 4],
# [ 8, 16, 32],
# [ 64, 128, 256]])
score_arr = np.stack([np.rot90(score, k=k) for k in range(4)])
# array([[[ 1, 2, 4],
# [ 8, 16, 32],
# [ 64, 128, 256]],
# [[ 4, 32, 256],
# [ 2, 16, 128],
# [ 1, 8, 64]],
# [[256, 128, 64],
# [ 32, 16, 8],
# [ 4, 2, 1]],
# [[ 64, 8, 1],
# [128, 16, 2],
# [256, 32, 4]]])
scores = np.einsum("ijk,ljk->il", bin_mats, score_arr)
_, idx = np.unique(scores.min(1), return_index=True)
return bin_mats[idx,...]
主要思想是我们可以对 N×N 二进制矩阵与 N×N 矩阵进行“点积”,该矩阵由 2 的前 N^2 次幂组成(我将后者称为得分矩阵)。当我们这样做时,我们为每个可能的二进制矩阵得到一个唯一的整数。
为了考虑旋转,我们可以采用“分数”矩阵的 4 次旋转的“点积”,并将每个二进制矩阵与四个结果中的最小值相关联。我们可以将这个最小值称为二进制矩阵的分数。
最后,我们可以用 np.unique
为每个唯一分数选择一个矩阵。例如,这里是 n = 2 的输出:
array([[[False, False],
[False, False]],
[[ True, False],
[False, False]],
[[ True, True],
[False, False]],
[[False, True],
[ True, False]],
[[ True, True],
[ True, False]],
[[ True, True],
[ True, True]]])
作为健全性检查,旋转的二进制矩阵的数量与 this OEIS sequence 一致,n 最多为 5:
%time assert [get_binary_mats(k).shape[0] for k in range(1, 6)] == [2, 6, 140, 16456, 8390720]
# takes 20 seconds on my machine