2D numpy中的所有二元组合

发布于 2025-01-17 14:26:03 字数 732 浏览 3 评论 0原文

我正在尝试创建一个代码,该代码可以在不包括旋转的Numpy矩阵中生成所有可能的组合。 我是什么意思旋转?我的意思是,以下矩阵数据实际上是相同的,因为它具有相同的数据,但旋转了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)

非常感谢!

I am trying to create a code that could generate all possible combinations of 0 and 1 in a numpy matrix excluding rotations.
What do I mean rotation? I mean that below matrix data are in fact the same because it has the same data but rotated 90º, 180º and 270º.

enter image description here

I have been trying below code but I think i am not getting all combinations and I have some of them missing. Do you have any idea if this is the right way? Do you know if there is any more efficient way?

For example, considering dx=3 and 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)

Thank you very much!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

骄兵必败 2025-01-24 14:26:03

这是一个矢量化解决方案,可以适用于小矩阵尺寸;代码中的评论说明了3乘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 b n b n binary矩阵的“点产品”与n by n矩阵一起使用,该矩阵由n矩阵组成,该矩阵由2的第一个n^2 powers组成(我称为后者得分矩阵)。当我们这样做时,我们将为每个可能的二进制矩阵获得一个唯一的整数。

为了说明旋转,我们可以使用“分数”矩阵4旋转的“点产品”,并将每个二进制矩阵与四个结果的最小值相关联。我们可以将此最小值称为二进制矩阵的分数。

最后,我们可以使用np.nique为每个唯一分数选择一个矩阵。例如,这是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]]])

作为一项理智检查,二进制矩阵的数量直至旋转,此OEIS序列 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

Here is a vectorized solution that can work for small matrix sizes; comments in the code illustrate a 3 by 3 case:

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,...]

The main idea is that we can take a "dot product" of an N by N binary matrix with an N by N matrix consisting of first N^2 powers of 2 (I call the latter the score matrix). When we do this, we get a unique integer for each possible binary matrix.

To account for rotations, we can take a "dot product" with 4 rotations of the "score" matrix, and associate each binary matrix to the minimum of the four results. We can refer to this minimum as a score of a binary matrix.

Finally, we can pick a matrix for each unique score with np.unique. For example, here is the output for 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]]])

As a sanity check, the number of binary matrices up to rotation lines up with this OEIS sequence for n up to 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
爱已欠费 2025-01-24 14:26:03

我不确定我的答案是否是最有效的方法,但是无论如何。

我们可以使用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

I am not sure if my answer is most efficient way, but anyways.

We can rotate each matrix using numpy.rot90 function.

Lets Create two different dictionaries, one to store the main matrices, the other one to store main matrices' rotations, so we can verify if a new matrix is just a rotation of previously found matrices.

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
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文