对角化稀疏酉矩阵

时间:2017-02-27 19:31:10

标签: julia sparse-matrix eigenvalue

我必须收集稀疏酉矩阵的特征值。 基本上每个都只有一个不同于零的元素 行和列(它是某些马尔可夫过程的传递矩阵)。

我的问题是如何进行,什么是最好的选择 在所有功能套件中。我看过eigs可以帮忙, 但我也看到必须选择初始向量

1 个答案:

答案 0 :(得分:2)

以下代码最终定义pdeig,它返回矩阵的特征值,该矩阵是pdmatrix,即置换和对角矩阵的乘积,或者换句话说,像问题描述的矩阵。快速计算特征向量也是可能的(它们有一个明确的公式):

issquare(m) = all(x->x==size(m,1),size(m))
isunique(v) = v == unique(v)
permmatrix(sigma) = 
  [i==sigma[j] ? 1.0 : 0.0 for i=1:length(sigma),j=1:length(sigma)]
mat2perm(m) = [findfirst(m[:,i]) for i=1:size(m,1)]

function ispdmatrix(m)      # used to verify input matrix form
  (r,c,v) = findnz(m)
  return issquare(m) && isunique(r) && isunique(c)
end

function pdfact(m::Matrix)  # factor into permutation/dilation
  ispdmatrix(m) || error("input matrix must be a PD matrix")
  n = size(m,1)
  p = mat2perm(m)
  d = [p[i]>0 ? m[p[i],i] : zero(eltype(m)) for i=1:n]
  return (p,d)
end

# return eigenvalues from factored pdmatrix
function pdeig(p::Vector{Int},d::Vector)
  n = length(p)
  active = trues(n)
  eigv = Vector{Complex{eltype(d)}}(0)
  for i=1:n
    if !active[i]
      continue
    end
    if p[i]>0
      j=1
      cump = d[i]
      k=p[i]
      active[i]=false
      while active[k] > 0
        j+=1
        cump *= d[k]
        active[k] = false
        k=p[k]
      end
      append!(eigv,[cump^(1.0/j)*exp(2*im*π*m/j) for m=1:j])
    else
      push!(eigv,0.0 + 0.0im)
    end
  end
  return eigv
end

pdeig(m::Matrix) = pdeig(pdfact(m)...)

n = 4   # testing vector to matrix transformation of permutations
σ=randperm(n)
@assert mat2perm(permmatrix(σ))==σ

例如,以下内容:

m = [ 0.0 1.0 0.0 ; 2.0 0.0 0.0 ; 0.0 0.0 0.0 ]
pdeig(m)

输出:

    3-element Array{Complex{Float64},1}:
 -1.41421+1.73191e-16im 
  1.41421-3.46382e-16im 
              0.0+0.0im

由于这些矩阵是可对角化的,因此特征值应该提供对角矩阵(只需在它们上使用diagm)。

这些矩阵非常有条理,适当的Julia处理将为这些矩阵定义一个类型,然后定义各种线性代数函数以便在这种类型上进行调度。

如果出现错误,只需添加评论,我会尝试修复它们(或者如果我碰巧看到一个很好的重构,那么我就会编辑)。

BTW计算引入了小的数值误差,这些不应该是一个问题,可以通过适当的舍入来消除(因此不需要害怕-1.0-1.0+1.234234e-16im