Skip to content

Commit

Permalink
Trac #7989: Minpoly doesn't work for all matrices
Browse files Browse the repository at this point in the history
Right now, not all matrices can compute minpolys.  This patch exposes
these matrices.

URL: https://trac.sagemath.org/7989
Reported by: jason
Ticket author(s): Jason Grout, Frédéric Chapoton
Reviewer(s): Travis Scrimshaw
  • Loading branch information
Release Manager committed May 24, 2022
2 parents 7c5c452 + 329d472 commit 517265e
Show file tree
Hide file tree
Showing 4 changed files with 45 additions and 8 deletions.
34 changes: 28 additions & 6 deletions src/sage/matrix/matrix2.pyx
Expand Up @@ -2794,20 +2794,28 @@ cdef class Matrix(Matrix1):

sage: factor(A.minpoly('y'))
(y + 1) * (y + 2)^2

"""
f = self.fetch('minpoly')
if not f is None:
return f.change_variable_name(var)
f = self.charpoly(var=var, **kwds)
if f.is_squarefree(): # is_squarefree for polys much faster than factor.
# Then f must be the minpoly
self.cache('minpoly', f)
return f
try:
no_sq = f.is_squarefree()
# is_squarefree for polys much faster than factor.
except (TypeError, NotImplementedError):
pass
else:
if no_sq:
# Then f must be the minpoly
self.cache('minpoly', f)
return f

# Now we have to work harder. We find the power of each
# irreducible factor that divides the minpoly.
mp = f.radical()
try:
mp = f.radical()
except (TypeError, NotImplementedError):
raise NotImplementedError("minimal polynomial not implemented")
for h, e in f.factor():
if e > 1:
# Find the power of B so that the dimension
Expand All @@ -2825,6 +2833,20 @@ cdef class Matrix(Matrix1):
self.cache('minpoly', mp)
return mp

def _test_minpoly(self, **options):
"""
Check that :meth:`minpoly` works.

EXAMPLES::

sage: a = matrix([[1,2],[3,4]])
sage: a._test_minpoly()
"""
if self.nrows() == self.ncols() and self.base_ring().is_exact():
tester = self._tester(**options)
# At least check that the minimal polynomial kills the matrix
tester.assertTrue(self.minpoly().subs(x=self).is_zero())

def charpoly(self, var = 'x', algorithm = None):
r"""
Returns the characteristic polynomial of self, as a polynomial over
Expand Down
2 changes: 1 addition & 1 deletion src/sage/matrix/matrix_dense.pyx
Expand Up @@ -5,7 +5,7 @@ TESTS::
sage: R.<a,b> = QQ[]
sage: m = matrix(R,2,[0,a,b,b^2])
sage: TestSuite(m).run()
sage: TestSuite(m).run(skip="_test_minpoly")
"""

cimport sage.matrix.matrix as matrix
Expand Down
15 changes: 15 additions & 0 deletions src/sage/matrix/matrix_gap.pyx
Expand Up @@ -416,6 +416,21 @@ cdef class Matrix_gap(Matrix_dense):
"""
return int(self._libgap.RankMat())

def minpoly(self, var='x', **kwds):
"""
Compute the minimal polynomial.
EXAMPLES::
sage: M = MatrixSpace(ZZ, 2, implementation='gap')
sage: M([0, 1, -1, -1]).minpoly()
x^2 + x + 1
"""
po = self._libgap.MinimalPolynomial().sage()
return po.change_variable_name(var)

minimal_polynomial = minpoly

def elementary_divisors(self):
"""
Return the list of elementary divisors of this matrix.
Expand Down
2 changes: 1 addition & 1 deletion src/sage/matrix/matrix_generic_dense.pyx
Expand Up @@ -28,7 +28,7 @@ cdef class Matrix_generic_dense(matrix_dense.Matrix_dense):
sage: A = random_matrix(Integers(25)['x'], 2)
sage: type(A)
<class 'sage.matrix.matrix_generic_dense.Matrix_generic_dense'>
sage: TestSuite(A).run()
sage: TestSuite(A).run(skip='_test_minpoly')
Test comparisons::
Expand Down

0 comments on commit 517265e

Please sign in to comment.