|
1 | 1 | function proper_length_coloring( |
2 | | - A::AbstractMatrix, color::AbstractVector{<:Integer}; verbose::Bool |
| 2 | + A::AbstractMatrix, color::AbstractVector{<:Integer}; verbose::Bool=false |
3 | 3 | ) |
4 | | - if length(color) != size(A, 2) |
| 4 | + m, n = size(A) |
| 5 | + if length(color) != n |
5 | 6 | if verbose |
6 | | - @warn "$(length(color)) colors provided for $(size(A, 2)) columns." |
| 7 | + @warn "$(length(color)) colors provided for $n columns." |
7 | 8 | end |
8 | 9 | return false |
9 | 10 | end |
10 | 11 | return true |
11 | 12 | end |
12 | 13 |
|
| 14 | +function proper_length_bicoloring( |
| 15 | + A::AbstractMatrix, |
| 16 | + row_color::AbstractVector{<:Integer}, |
| 17 | + column_color::AbstractVector{<:Integer}; |
| 18 | + verbose::Bool=false, |
| 19 | +) |
| 20 | + m, n = size(A) |
| 21 | + bool = true |
| 22 | + if length(row_color) != m |
| 23 | + if verbose |
| 24 | + @warn "$(length(row_color)) colors provided for $m rows." |
| 25 | + end |
| 26 | + bool = false |
| 27 | + end |
| 28 | + if length(column_color) != n |
| 29 | + if verbose |
| 30 | + @warn "$(length(column_color)) colors provided for $n columns." |
| 31 | + end |
| 32 | + bool = false |
| 33 | + end |
| 34 | + return bool |
| 35 | +end |
| 36 | + |
13 | 37 | """ |
14 | 38 | structurally_orthogonal_columns( |
15 | | - A::AbstractMatrix, color::AbstractVector{<:Integer} |
| 39 | + A::AbstractMatrix, color::AbstractVector{<:Integer}; |
16 | 40 | verbose=false |
17 | 41 | ) |
18 | 42 |
|
|
56 | 80 | ) |
57 | 81 |
|
58 | 82 | Return `true` if coloring the columns of the symmetric matrix `A` with the vector `color` results in a partition that is symmetrically orthogonal, and `false` otherwise. |
59 | | - |
60 | | -A partition of the columns of a symmetrix matrix `A` is _symmetrically orthogonal_ if, for every nonzero element `A[i, j]`, either of the following statements holds: |
| 83 | +
|
| 84 | +A partition of the columns of a symmetric matrix `A` is _symmetrically orthogonal_ if, for every nonzero element `A[i, j]`, either of the following statements holds: |
61 | 85 |
|
62 | 86 | 1. the group containing the column `A[:, j]` has no other column with a nonzero in row `i` |
63 | 87 | 2. the group containing the column `A[:, i]` has no other column with a nonzero in row `j` |
@@ -102,6 +126,57 @@ function symmetrically_orthogonal_columns( |
102 | 126 | return true |
103 | 127 | end |
104 | 128 |
|
| 129 | +""" |
| 130 | + structurally_biorthogonal( |
| 131 | + A::AbstractMatrix, row_color::AbstractVector{<:Integer}, column_color::AbstractVector{<:Integer}; |
| 132 | + verbose=false |
| 133 | + ) |
| 134 | +
|
| 135 | +Return `true` if bicoloring of the matrix `A` with the vectors `row_color` and `column_color` results in a bipartition that is structurally biorthogonal, and `false` otherwise. |
| 136 | +
|
| 137 | +A bipartition of the rows and columns of a matrix `A` is _structurally biorthogonal_ if, for every nonzero element `A[i, j]`, either of the following statements holds: |
| 138 | +
|
| 139 | +1. the group containing the column `A[:, j]` has no other column with a nonzero in row `i` |
| 140 | +2. the group containing the row `A[i, :]` has no other row with a nonzero in column `j` |
| 141 | +
|
| 142 | +!!! warning |
| 143 | + This function is not coded with efficiency in mind, it is designed for small-scale tests. |
| 144 | +""" |
| 145 | +function structurally_biorthogonal( |
| 146 | + A::AbstractMatrix, |
| 147 | + row_color::AbstractVector{<:Integer}, |
| 148 | + column_color::AbstractVector{<:Integer}; |
| 149 | + verbose::Bool=false, |
| 150 | +) |
| 151 | + if !proper_length_bicoloring(A, row_color, column_color; verbose) |
| 152 | + return false |
| 153 | + end |
| 154 | + column_group = group_by_color(column_color) |
| 155 | + row_group = group_by_color(row_color) |
| 156 | + for i in axes(A, 1), j in axes(A, 2) |
| 157 | + iszero(A[i, j]) && continue |
| 158 | + ci, cj = row_color[i], column_color[j] |
| 159 | + gi, gj = row_group[ci], column_group[cj] |
| 160 | + A_gj_rowi = view(A, i, gj) |
| 161 | + A_gi_columnj = view(A, gi, j) |
| 162 | + nonzeros_gj_rowi = count(!iszero, A_gj_rowi) |
| 163 | + nonzeros_gi_columnj = count(!iszero, A_gi_columnj) |
| 164 | + if nonzeros_gj_rowi > 1 && nonzeros_gi_columnj > 1 |
| 165 | + if verbose |
| 166 | + gj_incompatible_columns = gj[findall(!iszero, A_gj_rowi)] |
| 167 | + gi_incompatible_rows = gi[findall(!iszero, A_gi_columnj)] |
| 168 | + @warn """ |
| 169 | + For coefficient (i=$i, j=$j) with row color ci=$ci and column color cj=$cj: |
| 170 | + - In row color ci=$ci, rows $gi_incompatible_rows all have nonzeros in column j=$j. |
| 171 | + - In column color cj=$cj, columns $gj_incompatible_columns all have nonzeros in row i=$i. |
| 172 | + """ |
| 173 | + end |
| 174 | + return false |
| 175 | + end |
| 176 | + end |
| 177 | + return true |
| 178 | +end |
| 179 | + |
105 | 180 | """ |
106 | 181 | directly_recoverable_columns( |
107 | 182 | A::AbstractMatrix, color::AbstractVector{<:Integer} |
|
0 commit comments