Matrix cg的视图实现!关于矩阵
我正在尝试使用cg!IterativeSolvers.jl上的函数,用于求解矩阵线性系统,即A、X、B适当大小的矩阵的AX=B。考虑到索引的工作方式,Matrix cg的视图实现!关于矩阵,matrix,julia,Matrix,Julia,我正在尝试使用cg!IterativeSolvers.jl上的函数,用于求解矩阵线性系统,即A、X、B适当大小的矩阵的AX=B。考虑到索引的工作方式,X[:,i]独立于除B[:,i]之外的所有函数,因此这实际上归结为n不同的线性解。在这种情况下,通过\直接求解会自动工作,但像CG这样的迭代解算器不会。我可以很容易地做到这一点,在外面的循环,但我还没有能够得到在适当的操作工作。目前,我的代码如下所示: for j=1:size(u,2) u[freenode,j],ch = cg!(u[fre
X[:,i]
独立于除B[:,i]
之外的所有函数,因此这实际上归结为n
不同的线性解。在这种情况下,通过\
直接求解会自动工作,但像CG这样的迭代解算器不会。我可以很容易地做到这一点,在外面的循环,但我还没有能够得到在适当的操作工作。目前,我的代码如下所示:
for j=1:size(u,2)
u[freenode,j],ch = cg!(u[freenode,j],lhs,Dinv.*rhs(u,i)[:,j]) # Requires Vector, need to change rhs
end
这就给出了相应的左手边和右手边的CG解。但它不到位的原因归结为这个简单的示例抛出了一个错误:
using IterativeSolvers
y = view(ones(4,2),:,2)
A=rand(4,4)
cg!(y,A,view(zeros(4,2),:,2))
即:
ERROR: MethodError: no method matching init!
(::IterativeSolvers.KrylovSubspace{Float64,Array{Float64,2}}, ::SubArray{Float64,1,Array{Float64,2},Tuple{Colon,Int64},true})
Closest candidates are:
init!{T}(::IterativeSolvers.KrylovSubspace{T,OpT}, ::Array{T,1}) at C:\Users\Chris\.julia\v0.5\IterativeSolvers\src\krylov.jl:66
in #cg!#23 at C:\Users\Chris\.julia\v0.5\IterativeSolvers\src\cg.jl:7 [inlined]
in cg!(::SubArray{Float64,1,Array{Float64,2},Tuple{Colon,Int64},true}, ::Array{Float64,2}, ::SubArray{Float64,1,Array{Float64,2},Tuple{Colon,Int64},true}, ::Int64) at C:\Users\Chris\.julia\v0.5\IterativeSolvers\src\cg.jl:6 (repeats 2 times)
问题似乎不在于视图,你是对的,这本身不是“视图”问题,问题似乎在于init代码>方法似乎没有以可以接受“视图”(即子数组类型)的方式定义。错误表明“最接近的候选人是”
(即,子阵列没有方法定义,仅适用于普通阵列,并且似乎没有可依赖的通用函数/基本情况)
如果您先“收集”阵列,那么它(大概)会按预期工作:
julia> cg!( collect(y), A, view(zeros(4,2),:,2))
([0.0752658,-0.693794,0.330172,0.437474],IterativeSolvers.ConvergenceHistory{Float64,Array{Float64,1}}(false,0.0,5,[0.249856,0.392572,0.401496,0.463142]))
但很明显,这对你没有用,因为你并没有真正按照预期的方式改变y
如果你想把y
作为一个视图保留到那一点,我看到的唯一方法就是暂时将它“破解”到cg内的一个普通数组中代码>使用复合语句:
cg!((y = collect(y); y),A,view(zeros(4,2),:,2))
但是,很明显,此时它不再是一个视图,因此您必须手动将它作为一个视图更新为原始数组…我怀疑您是否能够避免分配,因为init!函数实现为
function init!{T}(K::KrylovSubspace{T}, v::Vector{T})
# K.v = Vector{T}[all(v.==zero(T)) ? v : v/norm(v)]
K.v = Vector{T}[copy(v)]
end
因此无论如何都有一份副本。尽管如此,如果您希望此函数接受视图,只需将向量
修改为抽象向量
就不成问题。(函数非常简单,如果您不想修改包,您可以自己添加一个更通用的方法。)问题是我试图避免额外的分配。我理解,因此我的评论是“解释”对您没有真正的帮助。然而,除了自己修改krylov.jl
sourcefile之外,在我看来,您似乎无法让它在视图中“本地”工作。显然,纯粹从“方便”而非“效率”的角度来看,您可以为cg添加另一个定义会话中的code>,它接受一个::SubArray
参数并调用模块的内置版本的cg
具有必要的转换和内存管理功能。是的,A
或lhs
是稀疏的。将Array
更改为AbstractArray
并调用该函数可能是一个更好的主意。此外,@tasopapastylianou,在子数组上定义方法通常不是一个好主意,因为大多数这样的方法都足够通用,可以扩展到AbstractArray
。只需指出rhs
可以是一个视图。只有lhs
受init影响代码>方法rhs
和lhs
不需要就位,它是x
(或者在我的示例中是u
)rhs
是B,而lhs
是A
(这是相当标准的符号)。但这里显示的是,就地版本显然复制了X
,这将破坏就地版本的用途。对AbstractVector的更改应该放在他们的回购协议上,同时也应该删除副本。这听起来像是回购协议的一个问题。谢谢
function init!{T}(K::KrylovSubspace{T}, v::Vector{T})
# K.v = Vector{T}[all(v.==zero(T)) ? v : v/norm(v)]
K.v = Vector{T}[copy(v)]
end