|
| 1 | +""" |
| 2 | + check_structurally_orthogonal_columns(A, colors; verbose=false) |
| 3 | +
|
| 4 | +Return `true` if coloring the columns of the matrix `A` with the vector `colors` results in a partition that is structurally orthogonal, and `false` otherwise. |
| 5 | + |
| 6 | +Def 3.2: A partition of the columns of a matrix `A` is _structurally orthogonal_ if, for every nonzero element `A[i, j]`, the group containing column `A[:, j]` has no other column with a nonzero in row `i`. |
| 7 | +
|
| 8 | +Thm 3.5: The function [`distance2_column_coloring`](@ref) applied to the [`BipartiteGraph`](@ref) of `A` should return a suitable coloring. |
| 9 | +""" |
| 10 | +function check_structurally_orthogonal_columns( |
| 11 | + A::AbstractMatrix, colors::AbstractVector{<:Integer}; verbose=false |
| 12 | +) |
| 13 | + for c in unique(colors) |
| 14 | + js = filter(j -> colors[j] == c, axes(A, 2)) |
| 15 | + Ajs = @view A[:, js] |
| 16 | + nonzeros_per_row = count(!iszero, Ajs; dims=2) |
| 17 | + if maximum(nonzeros_per_row) > 1 |
| 18 | + verbose && @warn "Color $c has columns $js sharing nonzeros" |
| 19 | + return false |
| 20 | + end |
| 21 | + end |
| 22 | + return true |
| 23 | +end |
| 24 | + |
| 25 | +""" |
| 26 | + check_structurally_orthogonal_rows(A, colors; verbose=false) |
| 27 | +
|
| 28 | +Return `true` if coloring the rows of the matrix `A` with the vector `colors` results in a partition that is structurally orthogonal, and `false` otherwise. |
| 29 | + |
| 30 | +Def 3.2: A partition of the rows of a matrix `A` is _structurally orthogonal_ if, for every nonzero element `A[i, j]`, the group containing row `A[i, :]` has no other row with a nonzero in column `j`. |
| 31 | +
|
| 32 | +Thm 3.5: The function [`distance2_row_coloring`](@ref) applied to the [`BipartiteGraph`](@ref) of `A` should return a suitable coloring. |
| 33 | +""" |
| 34 | +function check_structurally_orthogonal_rows( |
| 35 | + A::AbstractMatrix, colors::AbstractVector{<:Integer}; verbose=false |
| 36 | +) |
| 37 | + for c in unique(colors) |
| 38 | + is = filter(i -> colors[i] == c, axes(A, 1)) |
| 39 | + Ais = @view A[is, :] |
| 40 | + nonzeros_per_column = count(!iszero, Ais; dims=1) |
| 41 | + if maximum(nonzeros_per_column) > 1 |
| 42 | + verbose && @warn "Color $c has rows $is sharing nonzeros" |
| 43 | + return false |
| 44 | + end |
| 45 | + end |
| 46 | + return true |
| 47 | +end |
| 48 | + |
| 49 | +""" |
| 50 | + check_symmetrically_orthogonal(A, colors; verbose=false) |
| 51 | +
|
| 52 | +Return `true` if coloring the columns of the symmetric matrix `A` with the vector `colors` results in a partition that is symmetrically orthogonal, and `false` otherwise. |
| 53 | + |
| 54 | +Def 4.2: A partition of the columns of a symmetrix matrix `A` is _symmetrically orthogonal_ if, for every nonzero element `A[i, j]`, either |
| 55 | +
|
| 56 | +1. the group containing the column `A[:, j]` has no other column with a nonzero in row `i` |
| 57 | +2. the group containing the column `A[:, i]` has no other column with a nonzero in row `j` |
| 58 | +""" |
| 59 | +function check_symmetrically_orthogonal( |
| 60 | + A::AbstractMatrix, colors::AbstractVector{<:Integer}; verbose=false |
| 61 | +) |
| 62 | + for i in axes(A, 2), j in axes(A, 2) |
| 63 | + if !iszero(A[i, j]) |
| 64 | + group_i = filter(i2 -> (i2 != i) && (colors[i2] == colors[i]), axes(A, 2)) |
| 65 | + group_j = filter(j2 -> (j2 != j) && (colors[j2] == colors[j]), axes(A, 2)) |
| 66 | + A_group_i_column_j = @view A[group_i, j] |
| 67 | + A_group_j_column_i = @view A[group_j, i] |
| 68 | + nonzeros_group_i_column_j = count(!iszero, A_group_i_column_j) |
| 69 | + nonzeros_group_j_column_i = count(!iszero, A_group_j_column_i) |
| 70 | + if nonzeros_group_i_column_j > 0 && nonzeros_group_j_column_i > 0 |
| 71 | + verbose && @warn """ |
| 72 | + For coefficient $((i, j)), both of the following have confounding zeros: |
| 73 | + - color $(colors[j]) with group $group_j |
| 74 | + - color $(colors[i]) with group $group_i |
| 75 | + """ |
| 76 | + return false |
| 77 | + end |
| 78 | + end |
| 79 | + end |
| 80 | + return true |
| 81 | +end |
0 commit comments