Skip to content

Commit dfb0821

Browse files
author
Release Manager
committed
gh-40276: Avoid hermite_form in solve_right if possible Currently, hermite_form can be randomly very slow (#33418, flintlib/flint#389) When `rank()==ncols()`, the solution is uniquely determined, so that an alternative algorithm is to solve the system over the fraction field, then convert it back to the ring. And computing rank is much faster — the current default algorithm for ℤ picks a random prime p and compute rank modulo p. This PR detects the full-rank case and implement the alternative algorithm. ### 📝 Checklist <!-- Put an `x` in all the boxes that apply. --> - [x] The title is concise and informative. - [x] The description explains in detail what this PR is about. - [x] I have linked a relevant issue or discussion. - [x] I have created tests covering the changes. - [ ] I have updated the documentation and checked the documentation preview. ### ⌛ Dependencies <!-- List all open PRs that this PR logically depends on. For example, --> <!-- - #12345: short description why this is a dependency --> <!-- - #34567: ... --> URL: #40276 Reported by: user202729 Reviewer(s): Travis Scrimshaw
2 parents 7b22571 + c71f7c9 commit dfb0821

File tree

1 file changed

+44
-6
lines changed

1 file changed

+44
-6
lines changed

src/sage/matrix/matrix2.pyx

Lines changed: 44 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -878,6 +878,33 @@ cdef class Matrix(Matrix1):
878878
sage: v = vector(GF(3), [1,1])
879879
sage: m.solve_right(v)
880880
(2, 1)
881+
882+
Test ``extend``::
883+
884+
sage: matrix(ZZ, [[2]]).solve_right(vector(ZZ, [1]), extend=False)
885+
Traceback (most recent call last):
886+
...
887+
ValueError: matrix equation has no solutions
888+
sage: matrix(ZZ, [[2], [2]]).solve_right(vector(ZZ, [1, 1]), extend=False)
889+
Traceback (most recent call last):
890+
...
891+
ValueError: matrix equation has no solutions
892+
sage: matrix(ZZ, [[2], [2]]).solve_right(vector(ZZ, [2, 4]), extend=False)
893+
Traceback (most recent call last):
894+
...
895+
ValueError: matrix equation has no solutions
896+
sage: matrix(ZZ, [[2], [2]]).solve_right(vector(ZZ, [2, 2]), extend=False)
897+
(1)
898+
sage: matrix(QQ, [[2]]).solve_right(vector(QQ, [1]), extend=False)
899+
(1/2)
900+
sage: v = matrix.identity(QQ, 500).solve_right(vector(QQ, [1]*500), extend=True) # <1s
901+
sage: v = matrix.identity(QQ, 500).solve_right(vector(QQ, [1]*500), extend=False) # <1s
902+
sage: matrix.identity(QQ, 500).hermite_form() # not tested (slow)
903+
sage: v = (matrix.identity(ZZ, 500)*2).solve_right(vector(ZZ, [2]*500), extend=False) # <1s
904+
sage: matrix.identity(ZZ, 500).hermite_form() # not tested (slow)
905+
sage: m = matrix.identity(ZZ, 250).stack(matrix.identity(ZZ, 250))*2
906+
sage: v = m.solve_right(vector(ZZ, [2]*500), extend=False) # <1s
907+
sage: m._solve_right_hermite_form(matrix(ZZ, [[2]]*500)) # not tested (slow)
881908
"""
882909
try:
883910
L = B.base_ring()
@@ -944,11 +971,22 @@ cdef class Matrix(Matrix1):
944971

945972
C = B.column() if b_is_vec else B
946973

947-
if not extend:
948-
try:
949-
X = self._solve_right_hermite_form(C)
950-
except NotImplementedError:
951-
X = self._solve_right_smith_form(C)
974+
if P not in _Fields and not extend:
975+
if self.rank() == self.ncols():
976+
# hermite_form is slow, avoid if possible
977+
if self.is_square():
978+
X = self._solve_right_nonsingular_square(C, check_rank=False)
979+
else:
980+
X = self._solve_right_general(C)
981+
try:
982+
X = X.change_ring(P)
983+
except TypeError:
984+
raise ValueError('matrix equation has no solutions')
985+
else:
986+
try:
987+
X = self._solve_right_hermite_form(C)
988+
except NotImplementedError:
989+
X = self._solve_right_smith_form(C)
952990
return X.column(0) if b_is_vec else X
953991

954992
if not self.is_square():
@@ -1199,7 +1237,7 @@ cdef class Matrix(Matrix1):
11991237
try:
12001238
X_[i] = v / d
12011239
except (ZeroDivisionError, TypeError) as e:
1202-
raise ValueError("matrix equation has no solution")
1240+
raise ValueError("matrix equation has no solutions")
12031241
# assert H*X_ == B
12041242

12051243
return U * X_

0 commit comments

Comments
 (0)