Matrix cg的视图实现!关于矩阵

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

我正在尝试使用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[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添加另一个定义,它接受一个
::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