I’m wondering if there is any Julia eigensolver specialized for complex companion matrices of moderate size, say up to 30x30.
Thanks,
-Arrigo
I’m wondering if there is any Julia eigensolver specialized for complex companion matrices of moderate size, say up to 30x30.
Thanks,
-Arrigo
It would be helpful if you defined what you mean by ‘companion matrices’. Is this what you’re referring to?
Have you looked at
Yes, here is it for clarity:
where c_i \in \mathbb{C}^n
Thanks for the link Sheehan. If this package supports trigonometric polynomials that’s exactly what I’m looking for.
Here’s a toy implementation:
using LinearAlgebra, Polynomials
struct CompanionMatrix{T} <: AbstractMatrix{T}
p::Poly{T}
function CompanionMatrix(p::Poly{T}) where {T}
@assert (coeffs(p))[end] ≈ one(T)
new{T}(p)
end
end
function Base.size(cm::CompanionMatrix)
L = length(coeffs(cm.p)) - 1
(L, L)
end
Base.size(cm::CompanionMatrix, i::Integer) = size(cm)[i]
function Base.length(cm::CompanionMatrix)
(length(coeffs(cm.p)) - 1)^2
end
function Base.getindex(cm::CompanionMatrix{T}, i::Integer, j::Integer) where {T}
if i == j + 1
one(T)
elseif j == size(cm, 1)
coeffs(cm.p)[i]
else
zero(T)
end
end
function LinearAlgebra.eigvals(cm::CompanionMatrix)
roots(cm.p)
end
now at the REPL
julia> cm = CompanionMatrix(Poly([1,2,3,4,5,1]))
5×5 CompanionMatrix{Int64}:
0 0 0 0 1
1 0 0 0 2
0 1 0 0 3
0 0 1 0 4
0 0 0 1 5
julia> eigvals(cm)
5-element Array{Complex{Float64},1}:
-4.192725723692124 + 0.0im
-0.5640990957045247 - 0.3909026378974719im
-0.5640990957045247 + 0.3909026378974719im
0.1604619575505869 - 0.6932715588679903im
0.1604619575505869 + 0.6932715588679903im
and as @dlfivefifty suggests, using FastPolynomialRoots.jl would be advisable as this doesn’t seem to be any faster than using eigvals
on collect(cm)
for the sizes you care about.
I don’t understand why you say trigonometric polynomials. The eigenvalues of a companion matrix are precisely the roots of a polynomial.
I believe FastPolynomialRoots.jl uses the AMVW algorithm, which is based on orthogonal conjugation of companion matrices.
Alternatively, you can just use a Hessenberg matrix and the relevant LAPACK routine, see
https://github.com/JuliaApproximation/ApproxFunBase.jl/blob/master/src/LinearAlgebra/hesseneigs.jl
This may be faster at smaller dimensions (the complexity is worse than AMVW though).
It may be appropriate to add any of the implementations suggested by @dlfivefifty and @Mason to Companion
in SpecialMatrices.jl.
I’m not sure if anything I wrote above is worth contributing to SpecialMatrices.jl, but I hereby give permission to anyone to use any of the code I wrote above in this thread for whatever purpose they desire with no obligation to credit me. I offer no warranty, guarantee or recourse that I didn’t do something stupid or wrong.
I see your point, I just mentioned “trigonometric” polynomials since that’s the kind of polynomials I’m working with.