From 5e0d7448f55257242d697fafc82210f64175b8b5 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Wed, 26 Jul 2023 21:17:27 -0700 Subject: [PATCH 1/6] sage.matrix.seymour_decomposition: Show dimensions in repr --- src/sage/matrix/matrix_cmr_sparse.pyx | 32 ++++++++--------- src/sage/matrix/seymour_decomposition.pyx | 42 ++++++++++++++--------- 2 files changed, 42 insertions(+), 32 deletions(-) diff --git a/src/sage/matrix/matrix_cmr_sparse.pyx b/src/sage/matrix/matrix_cmr_sparse.pyx index f5738c68605..57cbdbe4f2f 100644 --- a/src/sage/matrix/matrix_cmr_sparse.pyx +++ b/src/sage/matrix/matrix_cmr_sparse.pyx @@ -838,7 +838,7 @@ cdef class Matrix_cmr_chr_sparse(Matrix_cmr_sparse): sage: result, certificate = MFR2cmr._is_binary_linear_matroid_regular( ....: certificate=True) sage: result, certificate - (False, (OneSumNode with 2 children, NotImplemented)) + (False, (OneSumNode (6×14) with 2 children, NotImplemented)) sage: certificate[0].summands()[0].parent_rows_and_columns() ((0, 1, 2), (0, 4, 5, 6, 2, 3, 1)) sage: certificate[0].summands()[1].parent_rows_and_columns() @@ -852,13 +852,13 @@ cdef class Matrix_cmr_chr_sparse(Matrix_cmr_sparse): sage: result, certificate = MFR2cmr._is_binary_linear_matroid_regular( ....: certificate=True, complete_tree=True) sage: result, certificate - (False, (OneSumNode with 2 children, NotImplemented)) + (False, (OneSumNode (6×14) with 2 children, NotImplemented)) sage: unicode_art(certificate[0]) - ╭OneSumNode with 2 children─╮ - │ │ - SeriesParallelReductionNode SeriesParallelReductionNode - │ │ - ThreeConnectedIrregularNode ThreeConnectedIrregularNode + ╭OneSumNode (6×14) with 2 children╮ + │ │ + SeriesParallelReductionNode (3×7) SeriesParallelReductionNode (3×7) + │ │ + ThreeConnectedIrregularNode (3×4) ThreeConnectedIrregularNode (3×4) TESTS: @@ -879,20 +879,20 @@ cdef class Matrix_cmr_chr_sparse(Matrix_cmr_sparse): sage: result, certificate = M._is_binary_linear_matroid_regular( ....: certificate=True, complete_tree=True) sage: result, certificate - (True, GraphicNode) + (True, GraphicNode (11×11)) sage: unicode_art(certificate) - GraphicNode + GraphicNode (11×11) sage: result, certificate = M._is_binary_linear_matroid_regular( ....: certificate=True, complete_tree=True, ....: use_direct_graphicness_test=False) sage: result, certificate - (True, TwoSumNode with 2 children) + (True, TwoSumNode (11×11) with 2 children) sage: unicode_art(certificate) - ╭─────TwoSumNode with 2 children - │ │ - GraphicNode SeriesParallelReductionNode - │ - GraphicNode + ╭──────────TwoSumNode (11×11) with 2 children + │ │ + GraphicNode (7×8) SeriesParallelReductionNode (5×4) + │ + GraphicNode (4×4) """ cdef bool result cdef CMR_REGULAR_PARAMETERS params @@ -954,7 +954,7 @@ cdef class Matrix_cmr_chr_sparse(Matrix_cmr_sparse): sage: M.is_totally_unimodular() True sage: M.is_totally_unimodular(certificate=True) - (True, GraphicNode) + (True, GraphicNode (3×2)) sage: MF = matroids.named_matroids.Fano(); MF Fano: Binary matroid of rank 3 on 7 elements, type (3, 0) diff --git a/src/sage/matrix/seymour_decomposition.pyx b/src/sage/matrix/seymour_decomposition.pyx index 8e8661641bd..d67237bc619 100644 --- a/src/sage/matrix/seymour_decomposition.pyx +++ b/src/sage/matrix/seymour_decomposition.pyx @@ -31,6 +31,15 @@ cdef class DecompositionNode(SageObject): def __hash__(self): return self._dec + def nrows(self): + return CMRdecNumRows(self._dec) + + def ncols(self): + return CMRdecNumColumns(self._dec) + + def dimensions(self): + return self.nrows(), self.ncols() + @cached_method def matrix(self): r""" @@ -44,14 +53,14 @@ cdef class DecompositionNode(SageObject): [ 0 1] sage: result, certificate = M.is_totally_unimodular(certificate=True) sage: result, certificate - (True, GraphicNode) + (True, GraphicNode (3×2)) sage: certificate.matrix() is None True sage: result, certificate = M.is_totally_unimodular(certificate=True, ....: construct_matrices=True) sage: result, certificate - (True, GraphicNode) + (True, GraphicNode (3×2)) sage: certificate.matrix() [ 1 0] [-1 1] @@ -95,9 +104,9 @@ cdef class DecompositionNode(SageObject): sage: result, certificate = M2cmr.is_totally_unimodular(certificate=True, ....: construct_matrices=True) sage: result, certificate - (True, OneSumNode with 2 children) + (True, OneSumNode (6×4) with 2 children) sage: C = certificate.summands(); C - (GraphicNode, GraphicNode) + (GraphicNode (3×2), GraphicNode (3×2)) sage: C[0].parent_rows_and_columns() ((0, 1, 2), (0, 1)) sage: C[1].parent_rows_and_columns() @@ -133,11 +142,11 @@ cdef class DecompositionNode(SageObject): sage: result, certificate = M2cmr.is_totally_unimodular(certificate=True, ....: construct_matrices=True) sage: T = certificate.as_ordered_tree(); T - OneSumNode with 2 children[GraphicNode[], GraphicNode[]] + OneSumNode (6×4) with 2 children[GraphicNode (3×2)[], GraphicNode (3×2)[]] sage: unicode_art(T) - ╭─────OneSumNode with 2 children - │ │ - GraphicNode GraphicNode + ╭───────────OneSumNode (6×4) with 2 children + │ │ + GraphicNode (3×2) GraphicNode (3×2) """ from sage.combinat.ordered_tree import LabelledOrderedTree return LabelledOrderedTree([child.as_ordered_tree() for child in self._children()], @@ -185,16 +194,16 @@ cdef class DecompositionNode(SageObject): [ 0 0| 0 0| 1 0] [ 0 0| 0 0| 0 1] sage: result, certificate = M.is_totally_unimodular(certificate=True); certificate - OneSumNode with 4 children + OneSumNode (6×6) with 4 children sage: certificate._children() - (GraphicNode, GraphicNode, GraphicNode, GraphicNode) + (GraphicNode (2×2), GraphicNode (2×2), GraphicNode (1×1), GraphicNode (1×1)) sage: M2 = Matrix_cmr_chr_sparse(MatrixSpace(ZZ, 2, 2, sparse=True), ....: [[1, 1], [-1, 0]]); M2 [ 1 1] [-1 0] sage: result, certificate = M2.is_totally_unimodular(certificate=True); certificate - GraphicNode + GraphicNode (2×2) sage: certificate._children() () """ @@ -204,7 +213,8 @@ cdef class DecompositionNode(SageObject): key=lambda node: node.parent_rows_and_columns())) def _repr_(self): - return f'{self.__class__.__name__}' + nrows, ncols = self.dimensions() + return f'{self.__class__.__name__} ({nrows}×{ncols})' def _unicode_art_(self): return self.as_ordered_tree()._unicode_art_() @@ -249,7 +259,7 @@ cdef class OneSumNode(SumNode): sage: from sage.matrix.matrix_cmr_sparse import Matrix_cmr_chr_sparse sage: M = Matrix_cmr_chr_sparse.one_sum([[1, 0], [-1, 1]], [[1, 1], [-1, 0]]) sage: result, certificate = M.is_totally_unimodular(certificate=True); certificate - OneSumNode with 2 children + OneSumNode (4×4) with 2 children sage: certificate.summand_matrices() ( [ 1 0] [ 1 1] @@ -274,7 +284,7 @@ cdef class OneSumNode(SumNode): [ 0 0| 0 0| 1 0] [ 0 0| 0 0| 0 1] sage: result, certificate = M3.is_totally_unimodular(certificate=True); certificate - OneSumNode with 4 children + OneSumNode (6×6) with 4 children sage: certificate.summand_matrices() ( [ 1 0] [ 1 1] @@ -319,7 +329,7 @@ cdef class BaseGraphicNode(DecompositionNode): [ 0 1] sage: result, certificate = M.is_totally_unimodular(certificate=True) sage: result, certificate - (True, GraphicNode) + (True, GraphicNode (3×2)) sage: G = certificate.graph(); G Graph on 4 vertices sage: G.vertices(sort=True) @@ -342,7 +352,7 @@ cdef class BaseGraphicNode(DecompositionNode): [ 0 1] sage: result, certificate = M.is_totally_unimodular(certificate=True) sage: result, certificate - (True, GraphicNode) + (True, GraphicNode (3×2)) sage: certificate.forest_edges() ((1, 2), (7, 1)) """ From e1899495d3d825c614e3d2b2b13ba55ed5877fb0 Mon Sep 17 00:00:00 2001 From: J S Date: Thu, 27 Jul 2023 18:31:05 -0700 Subject: [PATCH 2/6] this time i saved the changes --- src/sage/matrix/matrix_cmr_sparse.pyx | 148 +++++++++++++++++++++- src/sage/matrix/seymour_decomposition.pyx | 41 +++++- 2 files changed, 180 insertions(+), 9 deletions(-) diff --git a/src/sage/matrix/matrix_cmr_sparse.pyx b/src/sage/matrix/matrix_cmr_sparse.pyx index ca97e16d0b3..07b929c05e2 100644 --- a/src/sage/matrix/matrix_cmr_sparse.pyx +++ b/src/sage/matrix/matrix_cmr_sparse.pyx @@ -438,8 +438,106 @@ cdef class Matrix_cmr_chr_sparse(Matrix_cmr_sparse): sum.set_immutable() return sum - def three_sum(self, other, *args): - raise NotImplementedError + def three_sum(first_mat, second_mat, first_col_index1, first_col_index2, second_col_index1, second_col_index2): + fc = len(first_mat.columns()) + sc = len(second_mat.columns()) + fr = len(first_mat.rows()) + sr = len(second_mat.rows()) + if any([fc < 3, sc < 3, fr < 2, sr < 2]): + raise ValueError('Some matrix is not large enough to perform a 3-sum') + if any([first_col_index1 >= fc, first_col_index2 >= fc, second_col_index1 >= sc, second_col_index2 >= sc]): + raise ValueError('Some column indicated exceeds its matrix size') + first_col1 = first_mat.columns()[first_col_index1] + first_col2 = first_mat.columns()[first_col_index2] + second_col1 = second_mat.columns()[second_col_index1] + second_col2 = second_mat.columns()[second_col_index2] + fir_nrows = range(fr) + sec_nrows = range(sr) + valid1 = False + valid2 = False + for i in fir_nrows: + if (first_col1[i] == 1 and first_col2[i] == 0) or (first_col1[i] == 0 and first_col2[i] == 1): + subcol1 = tuple(first_col1[k] for k in fir_nrows if k != i) + subcol2 = tuple(first_col2[k] for k in fir_nrows if k != i) + if subcol1 == subcol2: + valid1 = True + first_row_index = i + break + for i in sec_nrows: + if (second_col1[i] == 1 and second_col2[i] == 0) or (second_col1[i] == 0 and second_col2[i] == 1): + subcol1 = tuple(second_col1[k] for k in sec_nrows if k != i) + subcol2 = tuple(second_col2[k] for k in sec_nrows if k != i) + if subcol1 == subcol2: + valid2 = True + second_row_index = i + break + if not (valid1 and valid2): + raise ValueError('indicated columns of Matrices are not of appropriate form for 3-sum') + first_subcol = first_mat.delete_rows([first_row_index]).columns()[first_col_index1] + second_subcol = first_mat.delete_rows([second_row_index]).columns()[second_col_index1] + first_submat = first_mat.delete_columns([first_col_index1, first_col_index2]) + second_submat = second_mat.delete_columns([second_col_index1, second_col_index2]) + return first_submat + first_row = first_submat.rows()[first_row_index] + second_row = second_submat.rows()[second_row_index] + first_submat = first_submat.delete_rows([first_row_index]) + second_submat = second_submat.delete_rows([second_row_index]) + first_subrows = first_submat.rows() + second_subrows = second_submat.rows() + upper_right_rows = first_subcol.tensor_product(second_row).rows() + lower_left_rows = second_subcol.tensor_product(first_row).rows() + n1 = len(first_submat.rows()) + n2 = len(second_submat.rows()) + row_list = [] + for i in range(n1): + l1 = [] + r = first_subrows[i] + u = upper_right_rows[i] + for k in range(len(r)): + l.append(r[k]) + for k in range(len(u)): + l1.append(u[k]) + row_list.append(l1) + for i in range(n2): + l2 = [] + r = second_subrows[i] + u = lower_left_rows[i] + for k in range(len(r)): + l2.append(r[k]) + for k in range(len(u)): + l2.append(u[k]) + row_list.append(l2) + return Matrix_cmr_chr_sparse._from_data(upper_rows) + + def delete_rows(self, indices): + rows = self.rows() + row_list = [] + n = len(rows) + for i in indices: + if i >= n: + raise ValueError('Found index greater than matrix size') + rows.pop(i) + for r in rows: + x = [] + for i in range(len(r)): + x.append(r[i]) + row_list.append(x) + return Matrix_cmr_chr_sparse._from_data(row_list) + + def delete_columns(self, indices): + rows = self.rows() + n = len(rows) + row_list = [] + for i in indices: + if i >= n: + raise ValueError('Found index greater than matrix size') + for r in rows: + x = [] + for k in range(len(r)): + if not (k in indices): + x.append(r[k]) + row_list.append(x) + return Matrix_cmr_chr_sparse._from_data(row_list) def is_unimodular(self): r""" @@ -718,7 +816,51 @@ cdef class Matrix_cmr_chr_sparse(Matrix_cmr_sparse): return False, NotImplemented # submatrix TBD def is_cographic(self, *, time_limit=60.0, certificate=False): - raise NotImplementedError + r""" + EXAMPLES:: + + sage: from sage.matrix.matrix_cmr_sparse import Matrix_cmr_chr_sparse + sage: M = Matrix_cmr_chr_sparse(MatrixSpace(ZZ, 4, 9, sparse=True), [[1, 0, 0, 0, 1, -1, 1, 0, 0], + ....: [0, 1, 0, 0, 0, 1, -1, 1, 0], [0, 0, 1, 0, 0, 0, 1, -1, 1], + ....: [0, 0, 0, 1, 1, 0, 0, 1, -1]]); M + [ 1 0 0 0 1 -1 1 0 0] + [ 0 1 0 0 0 1 -1 1 0] + [ 0 0 1 0 0 0 1 -1 1] + [ 0 0 0 1 1 0 0 1 -1] + sage: M.is_cographic() + True + """ + cdef bool result + cdef CMR_GRAPH *graph = NULL + cdef CMR_GRAPH_EDGE* forest_edges = NULL + cdef CMR_GRAPH_EDGE* coforest_edges = NULL + cdef CMR_SUBMAT* submatrix = NULL + cdef CMR_GRAPHIC_STATISTICS stats + + sig_on() + try: + if certificate: + CMR_CALL(CMRtestCographicMatrix(cmr, self._mat, &result, &graph, &forest_edges, + &coforest_edges, &submatrix, &stats, time_limit)) + else: + CMR_CALL(CMRtestCographicMatrix(cmr, self._mat, &result, NULL, NULL, + NULL, NULL, &stats, time_limit)) + finally: + sig_off() + + if not certificate: + return result + + if result: + sage_graph = _sage_graph(graph) + sage_forest_edges = tuple(_sage_edge(graph, forest_edges[row]) + for row in range(self.nrows())) + sage_coforest_edges = tuple(_sage_edge(graph, coforest_edges[column]) + for column in range(self.ncols())) + return True, (sage_graph, sage_forest_edges, sage_coforest_edges) + + return False, NotImplemented # submatrix TBD + def is_network_matrix(self, *, time_limit=60.0, certificate=False): r""" diff --git a/src/sage/matrix/seymour_decomposition.pyx b/src/sage/matrix/seymour_decomposition.pyx index d67237bc619..157441db07e 100644 --- a/src/sage/matrix/seymour_decomposition.pyx +++ b/src/sage/matrix/seymour_decomposition.pyx @@ -305,9 +305,33 @@ cdef class OneSumNode(SumNode): cdef class TwoSumNode(SumNode): - - pass + r""" + EXAMPLES:: + sage: from sage.matrix.matrix_cmr_sparse import Matrix_cmr_chr_sparse + M = Matrix_cmr_chr_sparse(MatrixSpace(ZZ, 5, 5, sparse=True), + ....: [[1, 1, 1, 1, 1], [1, 1, 1, 0, 0], [1, 0, 1, 1, 0] + ....: ,[1, 0, 0, 1, 1], [1, 1, 0, 0, 1]]); M2 + [1 1 1 1 1] + [1 1 1 0 0] + [1 0 1 1 0] + [1 0 0 1 1] + [1 1 0 0 1] + sage: M3 = Matrix_cmr_chr_sparse.two_sum(M2, M2, 0, 1); M3 + [1 1 1 1|1 1 1 0 0] + [1 1 0 0|1 1 1 0 0] + [0 1 1 0|1 1 1 0 0] + [0 0 1 1|1 1 1 0 0] + [1 0 0 1|1 1 1 0 0] + [-------+---------] + [0 0 0 0|1 1 1 1 1] + [0 0 0 0|1 0 1 1 0] + [0 0 0 0|1 0 0 1 1] + [0 0 0 0|1 1 0 0 1] + sage: result, certificate = M3.is_totally_unimodular(certificate=True); certificate + TwoSumNode (9×9) with 2 children + """ + pass cdef class ThreeSumNode(SumNode): @@ -375,13 +399,18 @@ cdef class GraphicNode(BaseGraphicNode): cdef class CographicNode(BaseGraphicNode): - - pass + @cached_method + def graph(self): + r""" + Actually the cograph of matrix, in the case where it is not graphic. + """ + return _sage_graph(CMRdecCograph(self._dec)) cdef class PlanarNode(BaseGraphicNode): - - pass + @cached_method + def cograph(self): + return _sage_graph(CMRdecCograph(self._dec)) cdef class SeriesParallelReductionNode(DecompositionNode): From 070308644319ae86ce53f3f068403583e0b19255 Mon Sep 17 00:00:00 2001 From: J S Date: Thu, 27 Jul 2023 18:34:08 -0700 Subject: [PATCH 3/6] typo --- src/sage/matrix/matrix_cmr_sparse.pyx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sage/matrix/matrix_cmr_sparse.pyx b/src/sage/matrix/matrix_cmr_sparse.pyx index 07b929c05e2..be2291e76c1 100644 --- a/src/sage/matrix/matrix_cmr_sparse.pyx +++ b/src/sage/matrix/matrix_cmr_sparse.pyx @@ -494,7 +494,7 @@ cdef class Matrix_cmr_chr_sparse(Matrix_cmr_sparse): r = first_subrows[i] u = upper_right_rows[i] for k in range(len(r)): - l.append(r[k]) + l1.append(r[k]) for k in range(len(u)): l1.append(u[k]) row_list.append(l1) From f85ebf6058e095778076a8260962df4bd8c6c318 Mon Sep 17 00:00:00 2001 From: J S Date: Fri, 28 Jul 2023 07:49:58 -0700 Subject: [PATCH 4/6] some typo fixes --- src/sage/matrix/matrix_cmr_sparse.pyx | 31 ++++++++++----------------- 1 file changed, 11 insertions(+), 20 deletions(-) diff --git a/src/sage/matrix/matrix_cmr_sparse.pyx b/src/sage/matrix/matrix_cmr_sparse.pyx index be2291e76c1..d855efdf744 100644 --- a/src/sage/matrix/matrix_cmr_sparse.pyx +++ b/src/sage/matrix/matrix_cmr_sparse.pyx @@ -477,7 +477,6 @@ cdef class Matrix_cmr_chr_sparse(Matrix_cmr_sparse): second_subcol = first_mat.delete_rows([second_row_index]).columns()[second_col_index1] first_submat = first_mat.delete_columns([first_col_index1, first_col_index2]) second_submat = second_mat.delete_columns([second_col_index1, second_col_index2]) - return first_submat first_row = first_submat.rows()[first_row_index] second_row = second_submat.rows()[second_row_index] first_submat = first_submat.delete_rows([first_row_index]) @@ -490,24 +489,16 @@ cdef class Matrix_cmr_chr_sparse(Matrix_cmr_sparse): n2 = len(second_submat.rows()) row_list = [] for i in range(n1): - l1 = [] - r = first_subrows[i] - u = upper_right_rows[i] - for k in range(len(r)): - l1.append(r[k]) - for k in range(len(u)): - l1.append(u[k]) - row_list.append(l1) + r = list(first_subrows[i]) + u = list(upper_right_rows[i]) + r.extend(u) + row_list.append(r) for i in range(n2): - l2 = [] - r = second_subrows[i] - u = lower_left_rows[i] - for k in range(len(r)): - l2.append(r[k]) - for k in range(len(u)): - l2.append(u[k]) - row_list.append(l2) - return Matrix_cmr_chr_sparse._from_data(upper_rows) + r = list(lower_left_subrows[i]) + u = list(second_rows[i]) + r.extend(u) + row_list.append(r) + return Matrix_cmr_chr_sparse._from_data(row_list, immutable = False) def delete_rows(self, indices): rows = self.rows() @@ -522,7 +513,7 @@ cdef class Matrix_cmr_chr_sparse(Matrix_cmr_sparse): for i in range(len(r)): x.append(r[i]) row_list.append(x) - return Matrix_cmr_chr_sparse._from_data(row_list) + return Matrix_cmr_chr_sparse._from_data(row_list, immutable = False) def delete_columns(self, indices): rows = self.rows() @@ -537,7 +528,7 @@ cdef class Matrix_cmr_chr_sparse(Matrix_cmr_sparse): if not (k in indices): x.append(r[k]) row_list.append(x) - return Matrix_cmr_chr_sparse._from_data(row_list) + return Matrix_cmr_chr_sparse._from_data(row_list, immutable = False) def is_unimodular(self): r""" From 22cb0ec7a1a01a5fbaaa77ab34df6e268757433c Mon Sep 17 00:00:00 2001 From: Javier Santillan Date: Fri, 28 Jul 2023 08:04:41 -0700 Subject: [PATCH 5/6] three_sum seems to work --- src/sage/matrix/matrix_cmr_sparse.pyx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/sage/matrix/matrix_cmr_sparse.pyx b/src/sage/matrix/matrix_cmr_sparse.pyx index d855efdf744..db889b3fc4c 100644 --- a/src/sage/matrix/matrix_cmr_sparse.pyx +++ b/src/sage/matrix/matrix_cmr_sparse.pyx @@ -494,8 +494,8 @@ cdef class Matrix_cmr_chr_sparse(Matrix_cmr_sparse): r.extend(u) row_list.append(r) for i in range(n2): - r = list(lower_left_subrows[i]) - u = list(second_rows[i]) + r = list(lower_left_rows[i]) + u = list(second_subrows[i]) r.extend(u) row_list.append(r) return Matrix_cmr_chr_sparse._from_data(row_list, immutable = False) From d8f028c614051dd702acf9c318a1818ca183c153 Mon Sep 17 00:00:00 2001 From: Javier Santillan Date: Fri, 28 Jul 2023 08:15:11 -0700 Subject: [PATCH 6/6] added an example to three_sum --- src/sage/matrix/matrix_cmr_sparse.pyx | 35 +++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/src/sage/matrix/matrix_cmr_sparse.pyx b/src/sage/matrix/matrix_cmr_sparse.pyx index db889b3fc4c..e033097a9f0 100644 --- a/src/sage/matrix/matrix_cmr_sparse.pyx +++ b/src/sage/matrix/matrix_cmr_sparse.pyx @@ -439,6 +439,41 @@ cdef class Matrix_cmr_chr_sparse(Matrix_cmr_sparse): return sum def three_sum(first_mat, second_mat, first_col_index1, first_col_index2, second_col_index1, second_col_index2): + r""" + Return the 3-sum matrix constructed from the given matrices ``first_mat`` and ``second_mat``, with 'first_col_index1' + and 'first_col_index2' being the indices of the column vectors of the matrix, which are identical except for one row + having a 0 in one column and the other a non-zero entry in that row. The method assumes the nonzero entry is one. The same assumptions + are made for 'second_mat' and its input index variables. + + EXAMPLES:: + + sage: from sage.matrix.matrix_cmr_sparse import Matrix_cmr_chr_sparse + sage: M1 = Matrix_cmr_chr_sparse(MatrixSpace(ZZ, 5, 5, sparse=True), + ....: [[1, 0, -1, 0, 1], [1, 1, 0, -1, 1], [0, 0, 1, 1, 1], + ....: [1, 1, -1, 0, 0], [-1, -1, 0, 0,1]]); M1 + [ 1 0 -1 0 1] + [ 1 1 0 -1 1] + [ 0 0 1 1 1] + [ 1 1 -1 0 0] + [-1 -1 0 0 1] + sage: M2 = Matrix_cmr_chr_sparse(MatrixSpace(ZZ, 5, 5, sparse=True), + ....: [[1, 1, 1, 1, 1], [1, 1, 1, 0, 0], [1, 0, 1, 1, 0], + ....: [0, 0, 0, 1, 1], [1, 1, 0, 0, 1]]); M2 + [1 1 1 1 1] + [1 1 1 0 0] + [1 0 1 1 0] + [0 0 0 1 1] + [1 1 0 0 1] + sage: M3 = Matrix_cmr_chr_sparse.three_sum(M1, M2, 0, 1, 0, 1); M3 + [ 0 -1 1 1 1 0] + [ 1 1 1 0 0 0] + [-1 0 0 1 1 0] + [ 0 0 1 -1 -1 0] + [-1 0 1 1 1 1] + [-1 0 1 1 0 0] + [-1 0 1 0 1 1] + [ 1 0 -1 0 0 1] + """ fc = len(first_mat.columns()) sc = len(second_mat.columns()) fr = len(first_mat.rows())