Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix edge case for block diagonalization #323

Merged
merged 1 commit into from
Sep 27, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 10 additions & 8 deletions src/Certificate/Symmetry/block_diag.jl
Original file line number Diff line number Diff line change
Expand Up @@ -180,7 +180,7 @@

function ordered_block_diag(As, d)
U = block_diag(As, d)
U === nothing && return nothing
isnothing(U) && return nothing
iU = U'
@assert iU ≈ inv(U)
Bs = [iU * A * U for A in As]
Expand All @@ -199,7 +199,8 @@
# should work, this trick is similar to [CGT97].
#
# [CGT97] Corless, R. M.; Gianni, P. M. & Trager, B. M.
# A reordered Schur factorization method for zero-dimensional polynomial systems with multiple roots Proceedings of the 1997 international symposium on Symbolic and algebraic computation,
# A reordered Schur factorization method for zero-dimensional polynomial systems with multiple roots
# Proceedings of the 1997 international symposium on Symbolic and algebraic computation,
# 1997, 133-140
R = sum(λ .* refs)
C = sum(λ .* Cs)
Expand Down Expand Up @@ -247,13 +248,14 @@
offset = 0
for v in values(blocks)
@assert iszero(length(v) % d)
if length(v) == d
V = Z[:, v]
else
V = Z[:, v]
if length(v) != d
Cs = [B[v, v] for B in Bs]
V = block_diag(Cs, d)
V === nothing && break
V *= transpose(Z[:, v])
_V = block_diag(Cs, d)
if isnothing(_V)
break

Check warning on line 256 in src/Certificate/Symmetry/block_diag.jl

View check run for this annotation

Codecov / codecov/patch

src/Certificate/Symmetry/block_diag.jl#L256

Added line #L256 was not covered by tests
end
V *= _V
end
U[:, offset.+eachindex(v)] = V
offset += length(v)
Expand Down
10 changes: 5 additions & 5 deletions src/Certificate/Symmetry/wedderburn.jl
Original file line number Diff line number Diff line change
Expand Up @@ -185,14 +185,14 @@
if d > 1
if m > 1
U = ordered_block_diag(S, d)
if isnothing(U)
error(

Check warning on line 189 in src/Certificate/Symmetry/wedderburn.jl

View check run for this annotation

Codecov / codecov/patch

src/Certificate/Symmetry/wedderburn.jl#L188-L189

Added lines #L188 - L189 were not covered by tests
"Could not simultaneously block-diagonalize into $m identical $dx$d blocks",
)
end
else
U = Matrix{T}(LinearAlgebra.I, N, N)
end
if U === nothing
error(
"Could not simultaneously block-diagonalize into $m identical $dx$d blocks",
)
end
# From Example 1.7.3 of
# Sagan, The symmetric group, Springer Science & Business Media, 2001
# we know that there exists `C` such that `Q = kron(C, I)` if we use
Expand Down
23 changes: 23 additions & 0 deletions test/symmetry.jl
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,29 @@ function test_block_diag()
d = 2
U = SumOfSquares.Certificate.Symmetry.ordered_block_diag(A, d)
@test SumOfSquares.Certificate.Symmetry.ordered_block_check(U, A, d)
α = 0.75
A = [
Matrix{Int}(I, 6, 6),
[
1 0 0 0 0 0
0 -1 0 0 0 0
0 0 0 0 1 0
0 0 0 0 0 -1
0 0 1 0 0 0
0 0 0 -1 0 0
],
[
-0.5 α 0 0 0 0
-α -0.5 0 0 0 0
0 0 -0.5 α 0 0
0 0 -α -0.5 0 0
0 0 0 0 -0.5 α
0 0 0 0 -α -0.5
],
]
d = 2
U = SumOfSquares.Certificate.Symmetry.ordered_block_diag(A, d)
@test SumOfSquares.Certificate.Symmetry.ordered_block_check(U, A, d)
end

function runtests()
Expand Down
Loading