|
1 | 1 | """ |
2 | 2 | check_structurally_orthogonal_columns( |
3 | | - A::AbstractMatrix, colors::AbstractVector{<:Integer} |
| 3 | + A::AbstractMatrix, color::AbstractVector{<:Integer} |
4 | 4 | verbose=false |
5 | 5 | ) |
6 | 6 |
|
7 | | -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. |
| 7 | +Return `true` if coloring the columns of the matrix `A` with the vector `color` results in a partition that is structurally orthogonal, and `false` otherwise. |
8 | 8 | |
9 | 9 | 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`. |
10 | 10 |
|
11 | 11 | !!! warning |
12 | 12 | This function is not coded with efficiency in mind, it is designed for small-scale tests. |
| 13 | +
|
| 14 | +# References |
| 15 | +
|
| 16 | +> [_What Color Is Your Jacobian? Graph Coloring for Computing Derivatives_](https://epubs.siam.org/doi/10.1137/S0036144504444711), Gebremedhin et al. (2005) |
13 | 17 | """ |
14 | 18 | function check_structurally_orthogonal_columns( |
15 | | - A::AbstractMatrix, colors::AbstractVector{<:Integer}; verbose::Bool=true |
| 19 | + A::AbstractMatrix, color::AbstractVector{<:Integer}; verbose::Bool=false |
16 | 20 | ) |
17 | | - groups = color_groups(colors) |
18 | | - for (c, g) in enumerate(groups) |
19 | | - Ag = @view A[:, g] |
| 21 | + if length(color) != size(A, 2) |
| 22 | + if verbose |
| 23 | + @warn "$(length(color)) colors provided for $(size(A, 2)) columns" |
| 24 | + end |
| 25 | + return false |
| 26 | + end |
| 27 | + group = color_groups(color) |
| 28 | + for (c, g) in enumerate(group) |
| 29 | + Ag = view(A, :, g) |
20 | 30 | nonzeros_per_row = dropdims(count(!iszero, Ag; dims=2); dims=2) |
21 | 31 | max_nonzeros_per_row, i = findmax(nonzeros_per_row) |
22 | 32 | if max_nonzeros_per_row > 1 |
23 | | - verbose && @warn "Columns $g (with color $c) share nonzeros in row $i" |
24 | | - return false |
25 | | - end |
26 | | - end |
27 | | - return true |
28 | | -end |
29 | | - |
30 | | -""" |
31 | | - check_structurally_orthogonal_rows( |
32 | | - A::AbstractMatrix, colors::AbstractVector{<:Integer}; |
33 | | - verbose=false |
34 | | - ) |
35 | | -
|
36 | | -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. |
37 | | - |
38 | | -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`. |
39 | | -
|
40 | | -!!! warning |
41 | | - This function is not coded with efficiency in mind, it is designed for small-scale tests. |
42 | | -""" |
43 | | -function check_structurally_orthogonal_rows( |
44 | | - A::AbstractMatrix, colors::AbstractVector{<:Integer}; verbose::Bool=true |
45 | | -) |
46 | | - groups = color_groups(colors) |
47 | | - for (c, g) in enumerate(groups) |
48 | | - Ag = @view A[g, :] |
49 | | - nonzeros_per_col = dropdims(count(!iszero, Ag; dims=1); dims=1) |
50 | | - max_nonzeros_per_col, j = findmax(nonzeros_per_col) |
51 | | - if max_nonzeros_per_col > 1 |
52 | | - verbose && @warn "Rows $g (with color $c) share nonzeros in column $j" |
| 33 | + if verbose |
| 34 | + incompatible_columns = g[findall(!iszero, view(Ag, i, :))] |
| 35 | + @warn "In color $c, columns $incompatible_columns all have nonzeros in row $i" |
| 36 | + end |
53 | 37 | return false |
54 | 38 | end |
55 | 39 | end |
56 | 40 | return true |
57 | 41 | end |
58 | 42 |
|
59 | 43 | """ |
60 | | - check_symmetrically_orthogonal( |
61 | | - A::AbstractMatrix, colors::AbstractVector{<:Integer}; |
| 44 | + check_symmetrically_orthogonal_columns( |
| 45 | + A::AbstractMatrix, color::AbstractVector{<:Integer}; |
62 | 46 | verbose=false |
63 | 47 | ) |
64 | 48 |
|
65 | | -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. |
| 49 | +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. |
66 | 50 | |
67 | | -A partition of the columns of a symmetrix matrix `A` is _symmetrically orthogonal_ if, for every nonzero element `A[i, j]`, either |
| 51 | +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: |
68 | 52 |
|
69 | 53 | 1. the group containing the column `A[:, j]` has no other column with a nonzero in row `i` |
70 | 54 | 2. the group containing the column `A[:, i]` has no other column with a nonzero in row `j` |
71 | 55 |
|
72 | 56 | !!! warning |
73 | 57 | This function is not coded with efficiency in mind, it is designed for small-scale tests. |
| 58 | +
|
| 59 | +# References |
| 60 | +
|
| 61 | +> [_What Color Is Your Jacobian? Graph Coloring for Computing Derivatives_](https://epubs.siam.org/doi/10.1137/S0036144504444711), Gebremedhin et al. (2005) |
74 | 62 | """ |
75 | | -function check_symmetrically_orthogonal( |
76 | | - A::AbstractMatrix, colors::AbstractVector{<:Integer}; verbose::Bool=true |
| 63 | +function check_symmetrically_orthogonal_columns( |
| 64 | + A::AbstractMatrix, color::AbstractVector{<:Integer}; verbose::Bool=false |
77 | 65 | ) |
78 | 66 | checksquare(A) |
| 67 | + if length(color) != size(A, 2) |
| 68 | + if verbose |
| 69 | + @warn "$(length(color)) colors provided for $(size(A, 2)) columns" |
| 70 | + end |
| 71 | + return false |
| 72 | + end |
79 | 73 | issymmetric(A) || return false |
80 | | - groups = color_groups(colors) |
| 74 | + group = color_groups(color) |
81 | 75 | for i in axes(A, 2), j in axes(A, 2) |
82 | 76 | iszero(A[i, j]) && continue |
83 | | - ki, kj = colors[i], colors[j] |
84 | | - gi, gj = groups[ki], groups[kj] |
| 77 | + ci, cj = color[i], color[j] |
| 78 | + gi, gj = group[ci], group[cj] |
85 | 79 | A_gj_rowi = view(A, i, gj) |
86 | 80 | A_gi_rowj = view(A, j, gi) |
87 | 81 | nonzeros_gj_rowi = count(!iszero, A_gj_rowi) |
88 | 82 | nonzeros_gi_rowj = count(!iszero, A_gi_rowj) |
89 | 83 | if nonzeros_gj_rowi > 1 && nonzeros_gi_rowj > 1 |
90 | | - verbose && @warn """ |
91 | | - For coefficient $((i, j)): |
92 | | - - columns $gj (with color $kj) share nonzeros in row $i |
93 | | - - columns $gi (with color $ki) share nonzeros in row $j |
94 | | - """ |
| 84 | + if verbose |
| 85 | + gj_incompatible_columns = gj[findall(!iszero, A_gj_rowi)] |
| 86 | + gi_incompatible_columns = gi[findall(!iszero, A_gi_rowj)] |
| 87 | + @warn """ |
| 88 | + For coefficient (i=$i, j=$j) with column colors (ci=$ci, cj=$cj): |
| 89 | + - in color ci=$ci, columns $gi_incompatible_columns all have nonzeros in row j=$j |
| 90 | + - in color cj=$cj, columns $gj_incompatible_columns all have nonzeros in row i=$i |
| 91 | + """ |
| 92 | + end |
95 | 93 | return false |
96 | 94 | end |
97 | 95 | end |
|
0 commit comments