julia - 如何计算将矩阵保存为向量的矩阵乘法
问题描述
我有两个对称矩阵A
和B
一个向量X
。的维数A
是 n×n,的维数B
是 n×n,的维数是 n×1。设矩阵的第 1 行第 1 列X
的元素记为。i
j
A
A[i,j]
由于是对称的,所以只保存A
上三角矩阵的每一列。A
矩阵A
保存为数组:</p>
Vector_A = [A[1,1],
A[1,2], A[2,2],
A[1,3], A[2,3], A[3,3],
A[1,4], A[2,4], A[3,4], A[4,4],
...,
A[1,n], A[2,n], ..., A[n,n]]
矩阵B
以与 matrix 相同的格式保存A
。现在我想计算ABA
而不转换Vector_A
,Vector_B
回到矩阵A, B
。由于ABA
也是对称的,我想以ABA
与数组相同的方式保存。我怎样才能在 Julia 中做到这一点?
我还想在X'AX
不转换Vector_A
回表示的矩阵的A
情况下进行计算。我怎样才能在 Julia 中做到这一点?X'
transpose(X)
解决方案
您需要实现从该AbstractMatrix
类型继承的自己的数据结构。
例如,这可以这样做:
struct SymmetricM{T} <: AbstractMatrix{T}
data::Vector{T}
end
所以我们有一个对称矩阵,它只使用一个向量来存储它的数据。现在您需要实现函数,使其实际上表现得像一个矩阵,这样您就可以让 Julia 魔法发挥作用。
我们首先提供新矩阵数据类型的大小。
function Base.size(m::SymmetricM)
n = ((8*length(m.data)+1)^0.5-1)/2
nr = round(Int, n)
@assert n ≈ nr "The vector length must match the number of triang matrix elements"
(nr,nr)
end
在此代码nr
中,每次checkbounds
在矩阵上完成时都会计算。也许在您的生产实现中,您可能希望将其移动为SymmetricM
. 您会失去一些弹性并多存储 8 个字节,但会提高速度。
现在我们需要的下一个函数是根据矩阵索引计算向量的位置。这是一种可能的实现。
function getix(idx)::Int
n = size(m)[1]
row, col = idx
#assume left/lower triangular
if col > row
row = col
col = idx[1]
end
(row-1)*row/2 + col
end
现在我们可以实现getindex
和setindex
功能:
@inline function Base.getindex(m::SymmetricM, idx::Vararg{Int,2})
@boundscheck checkbounds(m, idx...)
m.data[getix(idx)]
end
@inline function Base.getindex(m::SymmetricM{T}, v::T, idx::Vararg{Int,2}) where T
@boundscheck checkbounds(m, idx...)
m.data[getix(idx)] = v
end
现在让我们测试这个东西:
julia> m = SymmetricM(collect(1:10))
4×4 SymmetricM{Int64}:
1 2 4 7
2 3 5 8
4 5 6 9
7 8 9 10
你可以看到我们只提供了一个三角形的元素(无论是下部还是上部——它们都是一样的)——我们得到了完整的矩阵!
这确实是一个完全有效的 Julia 矩阵,因此所有矩阵代数都应该在它上面工作:
julia> m * SymmetricM(collect(10:10:100))
4×4 Array{Int64,2}:
700 840 1010 1290
840 1020 1250 1630
1010 1250 1580 2120
1290 1630 2120 2940
请注意,乘法的结果是 Matrix 而不是SymmetricM
- 要获得 aSymmetricM
您需要重载*
运算符以接受 2 个SymmetricM
参数。出于说明目的,让我们展示一个带有减号的自定义运算符重载-
:
import Base.-
-(m1::SymmetricM, m2::SymmetricM) = SymmetricM(m1.data .- m2.data)
现在您将看到减法SymmetricM
将返回另一个SymmetricM
:
julia> m-m
4×4 SymmetricM{Int64}:
0 0 0 0
0 0 0 0
0 0 0 0
0 0 0 0
通过这种方式,您可以在 Julia 中构建一个完整的三角矩阵代数系统。
但是请注意,该getix
函数有一个if
语句,因此在不使用该字段的情况下访问SymmetricM
元素data
将比常规矩阵慢得多,因此也许您应该尝试重载项目所需的尽可能多的运算符。
推荐阅读
- haskell - 是否可以定义您自己的 Persistent / Esqueleto 镜片?
- elasticsearch - Search Guard 5 - ][WARN][cfscPrivilegesEvaluator] 无法处理复合请求
- php - 内连接3个不同的表codeigniter
- c# - 从模型错误中获取数据
- python - Flatlib - bdist_wheel 错误
- r - 计算R中数据框中每一列的百分位数
- c# - 在 App.xaml 的 EventSetter 上出现错误 CS1061
- scala - 使用 nth 进行 2D 插值
- css - CSS 没有完全应用在影子 DOM 上
- excel - 在excel中使用Find方法后如何访问相邻单元格数据?