From f69efec4cf990b70763ed18a1cb712fff0a8522d Mon Sep 17 00:00:00 2001 From: Darij Grinberg <darijgrinberg@gmail.com> Date: Thu, 13 Mar 2025 22:04:10 -0400 Subject: [PATCH] define minpoly_lin for matrices over any field --- src/sage/matrix/matrix2.pyx | 55 +++++++++++++++++++++++++++++++++++++ 1 file changed, 55 insertions(+) diff --git a/src/sage/matrix/matrix2.pyx b/src/sage/matrix/matrix2.pyx index 852d749e1e6..e73587d4f75 100644 --- a/src/sage/matrix/matrix2.pyx +++ b/src/sage/matrix/matrix2.pyx @@ -3035,6 +3035,61 @@ cdef class Matrix(Matrix1): self.cache('minpoly', mp) return mp + def minpoly_lin(self, var='x', **kwds): + r""" + Return the minimal polynomial of ``self``. + + This uses a purely linear-algebraic algorithm (essentially + Gaussian elimination, applied to the powers of ``self``). + It is slow but it requires no factorization of polynomials. + + EXAMPLES:: + + sage: # needs sage.rings.finite_rings + sage: A = matrix(GF(9, 'c'), 4, [1,1,0,0, 0,1,0,0, 0,0,5,0, 0,0,0,5]) + sage: A.minpoly_lin() + x^3 + 2*x^2 + 2*x + 1 + sage: A.minpoly_lin()(A) == 0 + True + sage: CF = CyclotomicField() + sage: i = CF.gen(4) + sage: A = matrix(CF, 4, [1,1,0,0, 0,1,0,0, 0,0,1+i,0, 0,0,0,-i]) + sage: A.minpoly_lin() + x^4 - 3*x^3 + (4 - E(4))*x^2 + (-3 + 2*E(4))*x + 1 - E(4) + + The default variable name is `x`, but you can specify + another name:: + + sage: # needs sage.rings.finite_rings + sage: A.minpoly_lin('y') + y^4 - 3*y^3 + (4 - E(4))*y^2 + (-3 + 2*E(4))*y + 1 - E(4) + """ + f = self.fetch('minpoly') + if f is not None: + return f.change_variable_name(var) + + n = self.nrows() + F = self.base_ring() + from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing + P = PolynomialRing(F, "x") + x = P.gen() + from sage.modules.free_module_element import vector + from sage.matrix.constructor import matrix + + pow = self**0 + pows = [] + for k in range(n+1): + pows.append(vector(pow.list())) + pow *= self + Mpows = matrix(pows) + try: + cs = Mpows.solve_left(vector(pow.list())) + except ValueError: + continue + mp = x**(k+1) - P.sum(cs[i] * x**i for i in range(k+1)) + self.cache('minpoly', mp) + return mp + def _test_minpoly(self, **options): """ Check that :meth:`minpoly` works.