Skip to content

Commit fa8604a

Browse files
committed
LinearAlgebra.det improvements
Still broken for `LinearAlgebra.Symmetric` polynomial matrices, producing a `MethodError` because of a missing `oneunit` method. This, however, seems like a separate matter that would better be addressed by a separate pull request. Performance comparison: ``` $ ./julia -t 8 _ _ _ _(_)_ | Documentation: https://docs.julialang.org (_) | (_) (_) | _ _ _| |_ __ _ | Type "?" for help, "]?" for Pkg help. | | | | | | |/ _` | | | | |_| | | | (_| | | Version 1.11.0-DEV.972 (2023-11-23) _/ |\__'_|_|_|\__'_| | Commit 9884e447e79 (1 day old master) |__/ | julia> using LinearAlgebra, DynamicPolynomials julia> @PolyVar a b c d e (a, b, c, d, e) julia> const m = diagm( -2 => fill(a, 14), -1 => fill(b, 15), 0 => fill(c, 16), 2 => fill(e, 14), 1 => fill(d, 15)) 16×16 Matrix{Polynomial{DynamicPolynomials.Commutative{DynamicPolynomials.CreationOrder}, Graded{LexOrder}, Int64}}: c d e 0 0 0 0 0 0 0 0 0 0 0 0 0 b c d e 0 0 0 0 0 0 0 0 0 0 0 0 a b c d e 0 0 0 0 0 0 0 0 0 0 0 0 a b c d e 0 0 0 0 0 0 0 0 0 0 0 0 a b c d e 0 0 0 0 0 0 0 0 0 0 0 0 a b c d e 0 0 0 0 0 0 0 0 0 0 0 0 a b c d e 0 0 0 0 0 0 0 0 0 0 0 0 a b c d e 0 0 0 0 0 0 0 0 0 0 0 0 a b c d e 0 0 0 0 0 0 0 0 0 0 0 0 a b c d e 0 0 0 0 0 0 0 0 0 0 0 0 a b c d e 0 0 0 0 0 0 0 0 0 0 0 0 a b c d e 0 0 0 0 0 0 0 0 0 0 0 0 a b c d e 0 0 0 0 0 0 0 0 0 0 0 0 a b c d e 0 0 0 0 0 0 0 0 0 0 0 0 a b c d 0 0 0 0 0 0 0 0 0 0 0 0 0 a b c julia> @time det(m); 9.301086 seconds (162.91 M allocations: 5.968 GiB, 9.55% gc time, 1.93% compilation time) julia> @time det(m); 9.197843 seconds (162.88 M allocations: 5.967 GiB, 10.97% gc time) julia> @time det(m); 9.628294 seconds (162.88 M allocations: 5.967 GiB, 10.74% gc time) ``` The above REPL session is with this commit applied. The same computation with MultivariatePolynomials v0.5.3 ran for multiple minutes before I decided to just kill it. Fixes #281
1 parent fcb1b29 commit fa8604a

File tree

1 file changed

+39
-10
lines changed

1 file changed

+39
-10
lines changed

src/det.jl

+39-10
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,42 @@
1-
function LinearAlgebra.det(M::Matrix{<:AbstractPolynomialLike})
2-
m = size(M)[1]
3-
if m > 2
4-
return sum(
5-
(-1)^(i - 1) * M[i, 1] * LinearAlgebra.det(M[1:end.!=i, 2:end]) for
6-
i in 1:m
7-
)
8-
elseif m == 2
9-
return M[1, 1] * M[2, 2] - M[2, 1] * M[1, 2]
1+
# Scalar determinant, used for recursive computation of the determinant
2+
LinearAlgebra.det(p::AbstractPolynomialLike{<:Number}) = p
3+
4+
element_det(e) = LinearAlgebra.det(e)*one(Int8)
5+
6+
# Matrix determinant by cofactor expansion, adapted from
7+
# `LinearAlgebraX.cofactor_det`.
8+
9+
function det_impl(A::AbstractMatrix{T}) where {T}
10+
r = (first size)(A)
11+
if 1 < r
12+
total = (element_det zero)(T)
13+
for i Base.OneTo(r)
14+
a = element_det(A[i, 1])
15+
if !iszero(a)
16+
ii = Base.OneTo(r) .!= i
17+
jj = 2:r
18+
B = A[ii, jj]
19+
sign = let o = one(Int8)
20+
iseven(i) ? -o : o
21+
end
22+
total += sign * a * det_impl(B)
23+
end
24+
end
25+
total
26+
elseif isone(r)
27+
element_det(A[1, 1])
1028
else
11-
return M[1, 1]
29+
error("unexpected")
30+
end
31+
end
32+
33+
collect_if_not_already_matrix(m::Matrix) = m
34+
collect_if_not_already_matrix(m::AbstractMatrix) = collect(m)
35+
36+
function LinearAlgebra.det(m::AbstractMatrix{<:AbstractPolynomialLike})
37+
if 0 < LinearAlgebra.checksquare(m)
38+
(det_impl collect_if_not_already_matrix)(m)
39+
else
40+
(element_det one eltype)(m)
1241
end
1342
end

0 commit comments

Comments
 (0)