| 79 | 79 | def __new__(cls, *args, **kwargs): |
| 80 | 80 | from sympy.matrices.immutable import ImmutableDenseMatrix |
| 81 | 81 | from sympy.utilities.iterables import is_sequence |
| 82 | from sympy.core.numbers import Zero | |
| 82 | 83 | isMat = lambda i: getattr(i, 'is_Matrix', False) |
| 83 | 84 | if len(args) != 1 or \ |
| 84 | 85 | not is_sequence(args[0]) or \ |
| 87 | 88 | expecting a sequence of 1 or more rows |
| 88 | 89 | containing Matrices.''')) |
| 89 | 90 | rows = args[0] if args else [] |
| 91 | ||
| 92 | # Convert Zero objects to ZeroMatrix objects with appropriate dimensions | |
| 93 | # This handles the case where matrix multiplication produces Zero objects | |
| 94 | # instead of ZeroMatrix objects | |
| 90 | 95 | if not isMat(rows): |
| 91 | 96 | if rows and isMat(rows[0]): |
| 92 | 97 | rows = [rows] # rows is not list of lists or [] |
| 98 | ||
| 99 | # First pass: convert Zero objects to ZeroMatrix with placeholder dimensions | |
| 100 | # We'll fix the dimensions in a second pass after we figure out the structure | |
| 101 | converted_rows = [] | |
| 102 | for r in rows: | |
| 103 | converted_row = [] | |
| 104 | for item in r: | |
| 105 | if isinstance(item, Zero): | |
| 106 | # Create a placeholder ZeroMatrix - we'll fix dimensions later | |
| 107 | converted_row.append(ZeroMatrix(1, 1)) | |
| 108 | else: | |
| 109 | converted_row.append(item) | |
| 110 | converted_rows.append(converted_row) | |
| 111 | rows = converted_rows | |
| 112 | ||
| 113 | # Second pass: fix dimensions based on block structure | |
| 114 | if rows: | |
| 115 | # Fix row dimensions first | |
| 116 | for i, r in enumerate(rows): | |
| 117 | row_heights = [getattr(item, 'rows', 1) for item in r] | |
| 118 | # All items in a row should have the same number of rows | |
| 119 | if len(set(row_heights)) == 1: | |
| 120 | continue # Already consistent | |
| 121 | ||
| 122 | # Fix column dimensions | |
| 123 | if rows and len(rows[0]) > 0: | |
| 124 | for j in range(len(rows[0])): | |
| 125 | col_widths = [] | |
| 126 | for i in range(len(rows)): | |
| 127 | if i < len(rows) and j < len(rows[i]): | |
| 128 | col_widths.append(getattr(rows[i][j], 'cols', 1)) | |
| 129 | # All items in a column should have the same number of columns | |
| 130 | if len(set(col_widths)) == 1: | |
| 131 | continue # Already consistent | |
| 132 | ||
| 93 | 133 | # regularity check |
| 94 | 134 | # same number of matrices in each row |
| 95 | 135 | blocky = ok = len(set([len(r) for r in rows])) == 1 |
| 164 | 204 | def _blockmul(self, other): |
| 165 | 205 | if (isinstance(other, BlockMatrix) and |
| 166 | 206 | self.colblocksizes == other.rowblocksizes): |
| 167 | return BlockMatrix(self.blocks*other.blocks) | |
| 207 | from sympy.core.numbers import Zero | |
| 208 | ||
| 209 | # Perform the matrix multiplication | |
| 210 | result_blocks = self.blocks*other.blocks | |
| 211 | ||
| 212 | # Convert any Zero objects back to ZeroMatrix with appropriate dimensions | |
| 213 | # This fixes the issue where matrix multiplication converts ZeroMatrix to Zero | |
| 214 | converted_blocks = [] | |
| 215 | for i in range(result_blocks.shape[0]): | |
| 216 | row = [] | |
| 217 | for j in range(result_blocks.shape[1]): | |
| 218 | element = result_blocks[i, j] | |
| 219 | if isinstance(element, Zero): | |
| 220 | # Determine the correct dimensions for this ZeroMatrix | |
| 221 | # The row dimension comes from self.rowblocksizes[i] | |
| 222 | # The column dimension comes from other.colblocksizes[j] | |
| 223 | rows = self.rowblocksizes[i] | |
| 224 | cols = other.colblocksizes[j] | |
| 225 | row.append(ZeroMatrix(rows, cols)) | |
| 226 | else: | |
| 227 | row.append(element) | |
| 228 | converted_blocks.append(row) | |
| 229 | ||
| 230 | return BlockMatrix(converted_blocks) | |
| 168 | 231 | |
| 169 | 232 | return self * other |
| 170 | 233 |
| Test Name | Status |
|---|---|
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.