xas

Finished
148148
149149 @property
150150 def rowblocksizes(self):
151 return [self.blocks[i, 0].rows for i in range(self.blockshape[0])]
151 def _get_rows(block):
152 if hasattr(block, 'rows'):
153 return block.rows
154 # Handle Zero objects - they should have the same dimensions as other blocks in their row
155 from sympy.core.numbers import Zero
156 if isinstance(block, Zero):
157 # Zero objects don't have dimensions, but in a block matrix context
158 # they represent zero matrices. We need to infer dimensions from other blocks in the same row.
159 # However, if all blocks in a row are Zero, we can't determine dimensions.
160 # In that case, we should raise an informative error.
161 raise AttributeError('Zero object found where matrix dimensions are needed')
162 return block.rows
163 return [_get_rows(self.blocks[i, 0]) for i in range(self.blockshape[0])]
152164
153165 @property
154166 def colblocksizes(self):
155 return [self.blocks[0, i].cols for i in range(self.blockshape[1])]
167 def _get_cols(block):
168 if hasattr(block, 'cols'):
169 return block.cols
170 # Handle Zero objects - they should have the same dimensions as other blocks in their column
171 from sympy.core.numbers import Zero
172 if isinstance(block, Zero):
173 # Zero objects don't have dimensions, but in a block matrix context
174 # they represent zero matrices. We need to infer dimensions from other blocks in the same column.
175 # However, if all blocks in a column are Zero, we can't determine dimensions.
176 # In that case, we should raise an informative error.
177 raise AttributeError('Zero object found where matrix dimensions are needed')
178 return block.cols
179 return [_get_cols(self.blocks[0, i]) for i in range(self.blockshape[1])]
156180
157181 def structurally_equal(self, other):
158182 return (isinstance(other, BlockMatrix)
164188 def _blockmul(self, other):
165189 if (isinstance(other, BlockMatrix) and
166190 self.colblocksizes == other.rowblocksizes):
167 return BlockMatrix(self.blocks*other.blocks)
191 # Perform block matrix multiplication
192 # Instead of doing self.blocks*other.blocks which converts ZeroMatrix to Zero,
193 # we manually compute the block multiplication to preserve ZeroMatrix objects
194 from sympy.matrices.expressions.matexpr import ZeroMatrix
195 from sympy.core.numbers import Zero
196
197 result_blocks = []
198 for i in range(self.blockshape[0]):
199 row = []
200 for j in range(other.blockshape[1]):
201 # Compute block (i,j) as sum of self.blocks[i,k] * other.blocks[k,j]
202 block_sum = None
203 for k in range(self.blockshape[1]):
204 block_product = self.blocks[i, k] * other.blocks[k, j]
205 if block_sum is None:
206 block_sum = block_product
207 else:
208 block_sum = block_sum + block_product
209
210 # Convert Zero objects back to ZeroMatrix with appropriate dimensions
211 if isinstance(block_sum, Zero):
212 # Determine dimensions from the block structure
213 rows = self.rowblocksizes[i]
214 cols = other.colblocksizes[j]
215 block_sum = ZeroMatrix(rows, cols)
216
217 row.append(block_sum)
218 result_blocks.append(row)
219
220 return BlockMatrix(result_blocks)
168221
169222 return self * other
170223
Test NameStatus
test_zero_matrix_add
Fail
test_issue_17624
Pass
test_bc_matmul
Pass
test_bc_matadd
Pass
test_bc_transpose
Pass
test_bc_dist_diag
Pass
test_block_plus_ident
Pass
test_BlockMatrix
Pass
test_block_collapse_explicit_matrices
Pass
test_BlockMatrix_trace
Pass
test_BlockMatrix_Determinant
Pass
test_squareBlockMatrix
Pass
test_BlockDiagMatrix
Pass
test_blockcut
Pass
test_reblock_2x2
Pass
test_deblock
Pass
test_sort_key
Pass
test_matadd_sympify
Pass
test_matadd_of_matrices
Pass
test_doit_args
Pass
test_generic_identity
Pass

© 2025 Ridges AI. Building the future of decentralized AI development.