You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python构建含2X2子矩阵的稀疏矩阵报错,求解决方案

构造分块稀疏矩阵的问题解决

问题背景

要构建一个2J×2J的分块矩阵C,其中每个子块都是2×2矩阵:

[ 0 A 0 0 0 0 ...       0 0 
  B 0 A 0 0 0 ...       0 0
  0 B 0 A 0 0 ...       0 0
  0 0 B 0 A 0 ....      0 0
            ..........
  0 0 0 0 0   ....      B 0]

这里的0是全零2×2矩阵,A、B是给定的2×2矩阵,分别位于分块的上对角线和下对角线。

尝试用scipy稀疏矩阵实现时,写出了如下代码(J=5):

def TheMatrix(J,alpha):
    A = [[0.5, alpha],[ alpha,0.5]]
    B =[[0.5,-alpha],[-alpha,0.5]]

    upperDiag = A*np.ones(J-1)
    lowerDiag = B*np.ones(J-1)

    diagonals = [upperDiag, lowerDiag]  # non-zero diagonals
    ASparse = sps.diags(diagonals,offsets=[1, -1])
    ASparse = sps.csc_matrix(ASparse)

运行后触发报错:

File "myprg.py", line 16, in TheMatrix(J,alpha)
upperDiag = A*np.ones(J-1)
            ~^~~~~~~~~~~~~
ValueError: operands could not be broadcast together with shapes (2,2) (5,)

问题原因

直接用列表形式的A、B和一维numpy数组相乘,无法实现“重复J-1次分块”的效果——numpy广播规则不支持(2,2)和(J-1,)形状的数组相乘。

解决方案

以下两种方法可以解决这个问题,分别适合不同场景:

方法1:用克罗内克积快速生成分块结构

利用numpy.kron(克罗内克积)可以快速生成重复的分块矩阵,再转为稀疏矩阵:

import numpy as np
import scipy.sparse as sps

def TheMatrix(J, alpha):
    # 将A、B转为numpy数组(必须,列表无法参与克罗内克积计算)
    A = np.array([[0.5, alpha], [alpha, 0.5]])
    B = np.array([[0.5, -alpha], [-alpha, 0.5]])
    
    # 生成分块上对角线:J-1个A沿上对角线排列
    upper_blocks = np.kron(np.eye(J, k=1), A)
    # 生成分块下对角线:J-1个B沿下对角线排列
    lower_blocks = np.kron(np.eye(J, k=-1), B)
    
    # 合并后转为稀疏矩阵
    return sps.csc_matrix(upper_blocks + lower_blocks)

说明:np.eye(J, k=1)是J×J的单位矩阵,上对角线为1,和A做克罗内克积后,就会把每个1的位置替换成A矩阵,正好对应分块上对角线的结构。

方法2:直接构造稀疏矩阵的索引与数据(内存高效)

如果J很大,先生成全矩阵会占用过多内存,可以直接构造稀疏矩阵的data、row、col数组:

import numpy as np
import scipy.sparse as sps

def TheMatrix(J, alpha):
    A = np.array([[0.5, alpha], [alpha, 0.5]])
    B = np.array([[0.5, -alpha], [-alpha, 0.5]])
    
    # 分块对角线的偏移量是±2(每个子块是2×2,所以元素级偏移为2)
    upper_offset = 2
    lower_offset = -2
    
    # 生成上对角线的所有元素:把A展平后重复J-1次
    upper_data = np.tile(A.flatten(), J-1)
    # 生成下对角线的所有元素:把B展平后重复J-1次
    lower_data = np.tile(B.flatten(), J-1)
    
    # 计算上对角线元素的行、列索引
    upper_rows = []
    upper_cols = []
    for i in range(J-1):
        # 第i个A块的行起始位置是i*2,列起始位置是i*2 + upper_offset
        block_rows = np.arange(i*2, i*2 + 2)
        block_cols = block_rows + upper_offset
        upper_rows.extend(block_rows)
        upper_cols.extend(block_cols)
    
    # 计算下对角线元素的行、列索引
    lower_rows = []
    lower_cols = []
    for i in range(J-1):
        # 第i个B块的行起始位置是i*2 + 2,列起始位置是i*2
        block_rows = np.arange(i*2 + 2, i*2 + 4)
        block_cols = block_rows + lower_offset
        lower_rows.extend(block_rows)
        lower_cols.extend(block_cols)
    
    # 合并所有数据和索引
    all_data = np.concatenate([upper_data, lower_data])
    all_rows = np.concatenate([upper_rows, lower_rows])
    all_cols = np.concatenate([upper_cols, lower_cols])
    
    # 构造稀疏矩阵
    return sps.csc_matrix((all_data, (all_rows, all_cols)), shape=(2*J, 2*J))

说明:这种方法只存储非零元素的位置和值,内存占用远低于全矩阵,适合J较大的场景。

内容的提问来源于stack exchange,提问作者jim

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.18 16:40:53