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

Swift中求解方程组前快速修改SparseMatrix_Double的方法

高效修改SparseMatrix_Double以消除稀疏矩阵奇异性

核心思路:在COO格式阶段预处理(最优方案)

由于SparseMatrix_Double不支持直接索引访问,直接修改已转换后的矩阵效率极低。最优方案是在将坐标形式(COO)转换为SparseMatrix_Double之前完成修改,利用稀疏矩阵非零元数量远小于总元素数的特性,将时间复杂度控制在O(K)(K为非零元数量),远优于O(N*M)的全量遍历。

针对你需要的「指定行列置零+对角加1消除奇异性」场景,具体步骤如下:

  • 过滤COO数组中所有属于待修改行或待修改列的非零元素
  • 为每个待修改的行i,添加(i,i)位置的元素1.0(平凡方程)

代码实现

假设你需要修改的行列数组为targetRows: [Int32] = [2]和targetCols: [Int32] = [2],修改后的完整代码如下:

// 原始COO格式数据
var rows: [Int32] = [0, 0, 1, 1, 2, 1, 2, 3, 2, 3]
var columns: [Int32] = [0, 1, 0, 1, 1, 2, 2, 2, 3, 3 ]
var values: [Double] = [1, 0, 0, 2, -1, -1, 2, -1, -1, 1]

// 需要修改的行列(用Set优化查找效率)
let targetRows: Set<Int32> = [2]
let targetCols: Set<Int32> = [2]

// 步骤1:过滤待修改行/列的非零元素
var filteredRows = [Int32]()
var filteredCols = [Int32]()
var filteredValues = [Double]()

for (idx, row) in rows.enumerated() {
    let col = columns[idx]
    let val = values[idx]
    if !targetRows.contains(row) && !targetCols.contains(col) {
        filteredRows.append(row)
        filteredCols.append(col)
        filteredValues.append(val)
    }
}

// 步骤2:添加平凡方程(对角位置加1)
for row in targetRows {
    filteredRows.append(row)
    filteredCols.append(row)
    filteredValues.append(1.0)
}

// 转换为SparseMatrix_Double
let blockCount = filteredRows.count
let blockSize = 1

let A = SparseConvertFromCoordinate(4, 4,
                                    blockCount, UInt8(blockSize),
                                    SparseAttributes_t(),
                                    &filteredRows, &filteredCols,
                                    &filteredValues)

var b: [Double] = [0,0,0,1]

let factor = SparseFactor(SparseFactorizationQR, A)
defer {
    SparseCleanup(A)
    SparseCleanup(factor)
}

var x = Array(b)

x.withUnsafeMutableBufferPointer { fPtr in
    let xb = DenseVector_Double(count: 4,
                               data: fPtr.baseAddress!)
    SparseSolve(factor, xb)
}

print("x \(x)")

若已持有SparseMatrix_Double的处理方案

如果已经完成了COO到SparseMatrix_Double的转换,可先将矩阵转换回COO格式修改,再重新转换:

// 假设已存在SparseMatrix_Double实例A
var cooRows = [Int32]()
var cooCols = [Int32]()
var cooValues = [Double]()

// 转换回COO格式
SparseConvertToCoordinate(A, &cooRows, &cooCols, &cooValues)

// 执行上述相同的过滤和添加平凡方程操作...

// 重新转换为SparseMatrix_Double
let modifiedA = SparseConvertFromCoordinate(A.rows, A.columns,
                                            cooRows.count, UInt8(blockSize),
                                            SparseAttributes_t(),
                                            &cooRows, &cooCols,
                                            &cooValues)
// 后续求解逻辑...
defer { SparseCleanup(modifiedA) }

关键优势

  • 时间复杂度仅为O(K),K是稀疏矩阵的非零元数量,对于大型稀疏矩阵,K远小于N*M,效率提升显著
  • 避免了对整个矩阵的全量遍历,完全适配超大稀疏矩阵的场景

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.29 00:26:25