|
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