#arrays #julia
#массивы #джулия
Вопрос:
Я использую функцию eigs() (из пакета Arpack), чтобы найти собственные значения разреженной матрицы (eigen () не работает для запасных матриц). По-видимому, eigs () не может найти все собственные значения, даже в очень простом случае:
using Arpack
M = spdiagm(0 => [1,2,3])
eigs(M, nev = 3)
Вывод последней строки представляет собой вектор, содержащий только 2 собственных значения, «2» и «3» («1» отсутствует). Чего я не понимаю? Существует ли другая функция для вычисления собственных значений разреженной матрицы (фактическая разреженная матрица намного больше, чем указанное выше M).
Ответ №1:
На самом деле это отображается при предупреждении:
julia> eigs(Matrix(M), nev = 3);
┌ Warning: Adjusting nev from 3 to 2
└ @ Arpack c:JuliaPkgJulia1.5.0packagesArpacko35I5srcArpack.jl:82
Глядя на исходный код, это может вернуть максимум LinearAlgebra.checksquare(M) - 1
значений.
Что вы могли бы попытаться сделать, так это использовать BandedMatrix
вместо этого, который также является разреженным:
julia> m=BandedMatrix(0=>1:3)
3×3 BandedMatrix{Int64,Array{Int64,2},Base.OneTo{Int64}}:
1 ⋅ ⋅
⋅ 2 ⋅
⋅ ⋅ 3
julia> eigen(m)
Eigen{Float64,Float64,Array{Float64,2},Array{Float64,1}}
values:
3-element Array{Float64,1}:
1.0
2.0
3.0
vectors:
3×3 Array{Float64,2}:
1.0 0.0 0.0
0.0 1.0 0.0
0.0 0.0 1.0
Комментарии:
1. Спасибо! Поскольку фактическая матрица намного больше 3, и, как отметил Мейсон, мне не нужны все собственные значения (определенно не LinearAlgebra.checksquare(M)), eigs () подойдет просто отлично.
Ответ №2:
eigs
использует итерационный метод, который практичен или рекомендуется только для больших разреженных матриц и когда требуется только небольшое количество собственных значений (небольшое по сравнению с размером матрицы).
Сообщение об ошибке, которое вы получили eigen
, немного неудачно. Желательно было бы также упомянуть, что если ваш массив небольшой, вы должны просто collect
преобразовать его в плотную матрицу, например
julia> using SparseArrays, LinearAlgebra
julia> M = spdiagm(0 => [1,2,3])
3×3 SparseMatrixCSC{Int64,Int64} with 3 stored entries:
[1, 1] = 1
[2, 2] = 2
[3, 3] = 3
julia> eigen(collect(M))
Eigen{Float64,Float64,Array{Float64,2},Array{Float64,1}}
values:
3-element Array{Float64,1}:
1.0
2.0
3.0
vectors:
3×3 Array{Float64,2}:
1.0 0.0 0.0
0.0 1.0 0.0
0.0 0.0 1.0
Если ваша матрица слишком велика, чтобы поместиться в памяти, и вы должны использовать разреженную матрицу, то я подозреваю, что вам не нужны все собственные значения.
Комментарии:
1. Спасибо. Ваше подозрение верно, мне действительно не нужны все собственные значения. Похоже, что это один из тех случаев, когда тестирование вашего кода на небольшом вводе не помогает.