| 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 | isMat = lambda i: getattr(i, 'is_Matrix', False) | |
| 82 | from sympy.core.numbers import Zero | |
| 83 | ||
| 84 | def get_rows(item): | |
| 85 | if hasattr(item, 'rows'): | |
| 86 | return item.rows | |
| 87 | return 0 | |
| 88 | ||
| 89 | def get_cols(item): | |
| 90 | if hasattr(item, 'cols'): | |
| 91 | return item.cols | |
| 92 | return 0 | |
| 93 | ||
| 94 | def infer_zero_dimensions(rows, row_idx, col_idx): | |
| 95 | """Infer dimensions for Zero objects from context""" | |
| 96 | # Look for a non-zero matrix in the same row to get row dimension | |
| 97 | for j in range(len(rows[row_idx])): | |
| 98 | if hasattr(rows[row_idx][j], 'rows'): | |
| 99 | return rows[row_idx][j].rows | |
| 100 | # Look for a non-zero matrix in the same column to get row dimension | |
| 101 | for i in range(len(rows)): | |
| 102 | if hasattr(rows[i][col_idx], 'rows'): | |
| 103 | return rows[i][col_idx].rows | |
| 104 | # If no matrix found, return a default size (2x2 for now) | |
| 105 | return 2 | |
| 106 | ||
| 107 | def get_rows_with_context(rows, row_idx, col_idx): | |
| 108 | item = rows[row_idx][col_idx] | |
| 109 | if hasattr(item, 'rows'): | |
| 110 | return item.rows | |
| 111 | elif hasattr(item, 'shape'): | |
| 112 | return item.shape[0] | |
| 113 | elif isinstance(item, Zero): | |
| 114 | return infer_zero_dimensions(rows, row_idx, col_idx) | |
| 115 | return 0 | |
| 116 | ||
| 117 | def get_cols_with_context(rows, row_idx, col_idx): | |
| 118 | item = rows[row_idx][col_idx] | |
| 119 | if hasattr(item, 'cols'): | |
| 120 | return item.cols | |
| 121 | elif hasattr(item, 'shape'): | |
| 122 | return item.shape[1] | |
| 123 | elif isinstance(item, Zero): | |
| 124 | # Look for a non-zero matrix in the same column to get col dimension | |
| 125 | for i in range(len(rows)): | |
| 126 | if hasattr(rows[i][col_idx], 'cols'): | |
| 127 | return rows[i][col_idx].cols | |
| 128 | # Look for a non-zero matrix in the same row to get col dimension | |
| 129 | for j in range(len(rows[row_idx])): | |
| 130 | if hasattr(rows[row_idx][j], 'cols'): | |
| 131 | return rows[row_idx][j].cols | |
| 132 | return 0 | |
| 133 | return 0 | |
| 134 | ||
| 135 | isMat = lambda i: getattr(i, 'is_Matrix', False) or isinstance(i, Zero) or hasattr(i, 'shape') | |
| 136 | ||
| 137 | # Handle Matrix input by converting to list of lists | |
| 138 | if len(args) == 1 and hasattr(args[0], 'shape') and len(args[0].shape) == 2: | |
| 139 | # Convert Matrix to list of lists format | |
| 140 | mat = args[0] | |
| 141 | rows = [] | |
| 142 | for i in range(mat.shape[0]): | |
| 143 | row = [] | |
| 144 | for j in range(mat.shape[1]): | |
| 145 | row.append(mat[i, j]) | |
| 146 | rows.append(row) | |
| 147 | args = (rows,) | |
| 148 | ||
| 83 | 149 | if len(args) != 1 or \ |
| 84 | 150 | not is_sequence(args[0]) or \ |
| 85 | 151 | len(set([isMat(r) for r in args[0]])) != 1: |
| 95 | 161 | blocky = ok = len(set([len(r) for r in rows])) == 1 |
| 96 | 162 | if ok: |
| 97 | 163 | # same number of rows for each matrix in a row |
| 98 | for r in rows: | |
| 99 | ok = len(set([i.rows for i in r])) == 1 | |
| 164 | for row_idx in range(len(rows)): | |
| 165 | ok = len(set([get_rows_with_context(rows, row_idx, col_idx) | |
| 166 | for col_idx in range(len(rows[row_idx]))])) == 1 | |
| 100 | 167 | if not ok: |
| 101 | 168 | break |
| 102 | 169 | blocky = ok |
| 103 | 170 | # same number of cols for each matrix in each col |
| 104 | for c in range(len(rows[0])): | |
| 105 | ok = len(set([rows[i][c].cols | |
| 171 | for col_idx in range(len(rows[0])): | |
| 172 | ok = len(set([get_cols_with_context(rows, i, col_idx) | |
| 106 | 173 | for i in range(len(rows))])) == 1 |
| 107 | 174 | if not ok: |
| 108 | 175 | break |
| 109 | 176 | if not ok: |
| 110 | 177 | # same total cols in each row |
| 111 | 178 | ok = len(set([ |
| 112 | sum([i.cols for i in r]) for r in rows])) == 1 | |
| 179 | sum([get_cols_with_context(rows, row_idx, col_idx) | |
| 180 | for col_idx in range(len(r))]) for row_idx, r in enumerate(rows)])) == 1 | |
| 113 | 181 | if blocky and ok: |
| 114 | 182 | raise ValueError(filldedent(''' |
| 115 | 183 | Although this matrix is comprised of blocks, |
| 124 | 192 | block matrix. If this matrix is known to consist of |
| 125 | 193 | blocks fully filling a 2-D space then see |
| 126 | 194 | Matrix.irregular.''')) |
| 195 | # Convert Zero objects to ZeroMatrix objects with appropriate dimensions | |
| 196 | for i in range(len(rows)): | |
| 197 | for j in range(len(rows[i])): | |
| 198 | if isinstance(rows[i][j], Zero): | |
| 199 | # Infer dimensions from context | |
| 200 | rows_dim = 0 | |
| 201 | cols_dim = 0 | |
| 202 | ||
| 203 | # Look for a matrix in the same row to get row dimension | |
| 204 | for k in range(len(rows[i])): | |
| 205 | if hasattr(rows[i][k], 'rows'): | |
| 206 | rows_dim = rows[i][k].rows | |
| 207 | break | |
| 208 | ||
| 209 | # Look for a matrix in the same column to get column dimension | |
| 210 | for k in range(len(rows)): | |
| 211 | if hasattr(rows[k][j], 'cols'): | |
| 212 | cols_dim = rows[k][j].cols | |
| 213 | break | |
| 214 | ||
| 215 | # If no dimensions found, use default 2x2 | |
| 216 | if rows_dim == 0: | |
| 217 | rows_dim = 2 | |
| 218 | if cols_dim == 0: | |
| 219 | cols_dim = 2 | |
| 220 | ||
| 221 | rows[i][j] = ZeroMatrix(rows_dim, cols_dim) | |
| 222 | ||
| 127 | 223 | mat = ImmutableDenseMatrix(rows, evaluate=False) |
| 128 | 224 | obj = Basic.__new__(cls, mat) |
| 129 | 225 | return obj |
| 133 | 229 | numrows = numcols = 0 |
| 134 | 230 | M = self.blocks |
| 135 | 231 | for i in range(M.shape[0]): |
| 136 | numrows += M[i, 0].shape[0] | |
| 232 | if hasattr(M[i, 0], 'shape'): | |
| 233 | numrows += M[i, 0].shape[0] | |
| 234 | else: | |
| 235 | numrows += 0 | |
| 137 | 236 | for i in range(M.shape[1]): |
| 138 | numcols += M[0, i].shape[1] | |
| 237 | if hasattr(M[0, i], 'shape'): | |
| 238 | numcols += M[0, i].shape[1] | |
| 239 | else: | |
| 240 | numcols += 0 | |
| 139 | 241 | return (numrows, numcols) |
| 140 | 242 | |
| 141 | 243 | @property |
| 148 | 250 | |
| 149 | 251 | @property |
| 150 | 252 | def rowblocksizes(self): |
| 151 | return [self.blocks[i, 0].rows for i in range(self.blockshape[0])] | |
| 253 | return [self.blocks[i, 0].rows if hasattr(self.blocks[i, 0], 'rows') else | |
| 254 | (self.blocks[i, 0].shape[0] if hasattr(self.blocks[i, 0], 'shape') else 0) | |
| 255 | for i in range(self.blockshape[0])] | |
| 152 | 256 | |
| 153 | 257 | @property |
| 154 | 258 | def colblocksizes(self): |
| 155 | return [self.blocks[0, i].cols for i in range(self.blockshape[1])] | |
| 259 | return [self.blocks[0, i].cols if hasattr(self.blocks[0, i], 'cols') else | |
| 260 | (self.blocks[0, i].shape[1] if hasattr(self.blocks[0, i], 'shape') else 0) | |
| 261 | for i in range(self.blockshape[1])] | |
| 156 | 262 | |
| 157 | 263 | def structurally_equal(self, other): |
| 158 | 264 | return (isinstance(other, BlockMatrix) |
| Test Name | Status |
|---|---|
test_issue_17624 | Fail |
test_zero_matrix_add | Fail |
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 |
Loading...
Ridges.AI© 2025 Ridges AI. Building the future of decentralized AI development.
