tl;博士——scipy 的 convolve2d 实际上是如何进行卷积操作的?我找到了通往 Toeplitz 矩阵的方法,但我对如何实际创建 Toeplitz 矩阵感到困惑。
前几天我在阅读康威的[生命游戏](https://en.wikipedia.org/wiki/Conway%27s_Game_of_Life规则),我突然想到游戏中的所有约束都是线性约束,这意味着生命游戏应该符合线性程序形式,因为未来的棋盘状态必须遵循以下线性约束:
def life_step(game_board):
board = np.copy(game_board)
neighbor_sums = sp.signal.convolve2d(game_board, kernel, mode='same', boundary="wrap")
# If fewer than 2 neighbors, cell is dead.
board[neighbor_sums < 2] = 0
# If 2 neighbors, cell stays in its state.
# If 3 neighbors, cell becomes or stays active.
board[neighbor_sums == 3] = 1
# If >3 neighbors, cell dies
board[neighbor_sums > 3] = 0
return board
游戏板是一个 NxM 矩阵。
计算游戏板中每个节点的邻居所需的内核是一个 3x3 矩阵。
因此我们可以将这个内核应用到游戏板上的每个位置,以计算每个节点的存活邻居的数量。然后我们可以对邻居计数应用约束,这将确定给定节点是打开还是关闭并生成下一个板状态。
但是,要使用凸求解器,例如 cvx,您不能传入 convolve2d 之类的函数,而是需要传入该函数对其自身进行编码的矩阵。
为了得到我们的线性算子,我们可以从一个简单的版本开始。我们可以手动提取 game_board 的正确组件(一个 nxm 矩阵)并将其与邻居内核相乘:https ://imgur.com/a/desSZAd 。但这似乎真的很脆弱,需要大量的手工计算。
所以,我想,如果我们把 game_board 展平呢?然后我们仍然需要将我们的内核应用到每个正确的权重上,但这应该有一些关于内核如何移动游戏板的结构。
第一个图像是扁平化。第二个图像是循环和堆叠内核向量以将卷积应用为一个 MM。第三个图像是移位内核与游戏板的乘积。
我又做了几个 Gamma 术语,显然有一些结构,但我没有看到如何以编程方式创建它。
所有这些都让我想到了 Toeplitz 矩阵,这似乎正是我正在寻找的。我正在应用此处找到的方法:https ://stackoverflow.com/a/51865516/8334507但是当我这样做时我没有得到wrap
-ing 功能,它还将我的输出矩阵的维度扩展到(N+2)x(M+2)
所以,一个 8x8 板变成 10x10。