@@ -105,23 +105,10 @@ function symmetrically_orthogonal_columns(
105105 for i in axes (A, 2 ), j in axes (A, 2 )
106106 iszero (A[i, j]) && continue
107107 ci, cj = color[i], color[j]
108- gi, gj = group[ci], group[cj]
109- A_gj_rowi = view (A, i, gj)
110- A_gi_rowj = view (A, j, gi)
111- nonzeros_gj_rowi = count (! iszero, A_gj_rowi)
112- nonzeros_gi_rowj = count (! iszero, A_gi_rowj)
113- if nonzeros_gj_rowi > 1 && nonzeros_gi_rowj > 1
114- if verbose
115- gj_incompatible_columns = gj[findall (! iszero, A_gj_rowi)]
116- gi_incompatible_columns = gi[findall (! iszero, A_gi_rowj)]
117- @warn """
118- For coefficient (i=$i , j=$j ) with column colors (ci=$ci , cj=$cj ):
119- - In color ci=$ci , columns $gi_incompatible_columns all have nonzeros in row j=$j .
120- - In color cj=$cj , columns $gj_incompatible_columns all have nonzeros in row i=$i .
121- """
122- end
123- return false
124- end
108+ check = _bilateral_check (
109+ A; i, j, ci, cj, row_group= group, column_group= group, verbose
110+ )
111+ ! check && return false
125112 end
126113 return true
127114end
@@ -156,6 +143,62 @@ function structurally_biorthogonal(
156143 for i in axes (A, 1 ), j in axes (A, 2 )
157144 iszero (A[i, j]) && continue
158145 ci, cj = row_color[i], column_color[j]
146+ check = _bilateral_check (A; i, j, ci, cj, row_group, column_group, verbose)
147+ ! check && return false
148+ end
149+ return true
150+ end
151+
152+ function _bilateral_check (
153+ A:: AbstractMatrix ;
154+ i:: Integer ,
155+ j:: Integer ,
156+ ci:: Integer ,
157+ cj:: Integer ,
158+ row_group:: AbstractVector ,
159+ column_group:: AbstractVector ,
160+ verbose:: Bool ,
161+ )
162+ if ci == 0 && cj == 0
163+ if verbose
164+ @warn """
165+ For coefficient (i=$i , j=$j ) with colors (ci=$ci , cj=$cj ):
166+ - Row color ci=$ci is neutral.
167+ - Column color cj=$cj is neutral.
168+ """
169+ end
170+ return false
171+ elseif ci == 0 && cj != 0
172+ gj = column_group[cj]
173+ A_gj_rowi = view (A, i, gj)
174+ nonzeros_gj_rowi = count (! iszero, A_gj_rowi)
175+ if nonzeros_gj_rowi > 1
176+ if verbose
177+ gj_incompatible_columns = gj[findall (! iszero, A_gj_rowi)]
178+ @warn """
179+ For coefficient (i=$i , j=$j ) with colors (ci=$ci , cj=$cj ):
180+ - Row color ci=$ci is neutral.
181+ - In column color cj=$cj , columns $gj_incompatible_columns all have nonzeros in row i=$i .
182+ """
183+ end
184+ return false
185+ end
186+ elseif ci != 0 && cj == 0
187+ gi = row_group[ci]
188+ A_gi_columnj = view (A, gi, j)
189+ nonzeros_gi_columnj = count (! iszero, A_gi_columnj)
190+ if nonzeros_gi_columnj > 1
191+ if verbose
192+ gi_incompatible_rows = gi[findall (! iszero, A_gi_columnj)]
193+ @warn """
194+ For coefficient (i=$i , j=$j ) with colors (ci=$ci , cj=$cj ):
195+ - In row color ci=$ci , rows $gi_incompatible_rows all have nonzeros in column j=$j .
196+ - Column color cj=$cj is neutral.
197+ """
198+ end
199+ return false
200+ end
201+ else
159202 gi, gj = row_group[ci], column_group[cj]
160203 A_gj_rowi = view (A, i, gj)
161204 A_gi_columnj = view (A, gi, j)
@@ -166,7 +209,7 @@ function structurally_biorthogonal(
166209 gj_incompatible_columns = gj[findall (! iszero, A_gj_rowi)]
167210 gi_incompatible_rows = gi[findall (! iszero, A_gi_columnj)]
168211 @warn """
169- For coefficient (i=$i , j=$j ) with row color ci=$ci and column color cj=$cj :
212+ For coefficient (i=$i , j=$j ) with colors ( ci=$ci , cj=$cj ) :
170213 - In row color ci=$ci , rows $gi_incompatible_rows all have nonzeros in column j=$j .
171214 - In column color cj=$cj , columns $gj_incompatible_columns all have nonzeros in row i=$i .
172215 """
@@ -199,12 +242,16 @@ function directly_recoverable_columns(
199242 return false
200243 end
201244 group = group_by_color (color)
202- B = stack (group; dims= 2 ) do g
203- dropdims (sum (A[:, g]; dims= 2 ); dims= 2 )
245+ B = if isempty (group)
246+ similar (A, size (A, 1 ), 0 )
247+ else
248+ stack (group; dims= 2 ) do g
249+ dropdims (sum (A[:, g]; dims= 2 ); dims= 2 )
250+ end
204251 end
205252 A_unique = Set (unique (A))
206253 B_unique = Set (unique (B))
207- if ! issubset (A_unique, B_unique)
254+ if ! issubset (A_unique, push! ( B_unique, zero ( eltype (B))) )
208255 if verbose
209256 @warn " Coefficients $(sort (collect (setdiff (A_unique, B_unique)))) are not directly recoverable."
210257 return false
0 commit comments