Skip to content

Commit

Permalink
sagemathgh-37826: FreeModuleAutomorphism: Add more invariants
Browse files Browse the repository at this point in the history
    
<!-- ^ Please provide a concise and informative title. -->
<!-- ^ Don't put issue numbers in the title, do this in the PR
description below. -->
<!-- ^ For example, instead of "Fixes sagemath#12345" use "Introduce new method
to calculate 1 + 2". -->
<!-- v Describe your changes below in detail. -->
<!-- v Why is this change required? What problem does it solve? -->
<!-- v If this PR resolves an open issue, please link to it here. For
example, "Fixes sagemath#12345". -->

We add more methods that complement the existing methods `det` and
`trace`, by delegating to the existing methods of Sage matrices.

This is parallel to what is done for ModulesWithBasis in:
- sagemath#37731

### 📝 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,
-->
<!-- - sagemath#12345: short description why this is a dependency -->
<!-- - sagemath#34567: ... -->
    
URL: sagemath#37826
Reported by: Matthias Köppe
Reviewer(s): Eric Gourgoulhon, Matthias Köppe, Travis Scrimshaw
  • Loading branch information
Release Manager committed Apr 28, 2024
2 parents 5add431 + 7cfc187 commit f12c4e3
Showing 1 changed file with 106 additions and 12 deletions.
118 changes: 106 additions & 12 deletions src/sage/tensor/modules/free_module_automorphism.py
Expand Up @@ -32,6 +32,7 @@
# https://www.gnu.org/licenses/
# *****************************************************************************

from sage.misc.lazy_attribute import lazy_attribute
from sage.structure.element import MultiplicativeGroupElement
from sage.tensor.modules.free_module_tensor import FreeModuleTensor

Expand Down Expand Up @@ -1054,6 +1055,55 @@ def matrix(self, basis1=None, basis2=None):
raise NotImplementedError("basis1 != basis2 not implemented yet")
return self._matrices[(basis1, basis2)]

def _some_matrix(self):
r"""
Return the matrix of ``self`` w.r.t. some basis.
EXAMPLES::
sage: M = FiniteRankFreeModule(QQ, 2, name='M')
sage: e = M.basis('e')
sage: a = M.automorphism([[1,1],[0,2]], name='a')
sage: a._some_matrix()
[1 1]
[0 2]
"""
self.matrix() # forces the update of the matrix in the module's default
# basis, to make sure that the dictionary self._matrices
# is not empty
return next(iter(self._matrices.values()))

@lazy_attribute
def characteristic_polynomial(self):
r"""
Return the characteristic polynomial of ``self``.
:meth:`characteristic_polynomial` and :meth:`charpoly` are the same method.
INPUT:
- ``var`` -- string (default: ``'x'``); a variable name
EXAMPLES::
sage: M = FiniteRankFreeModule(QQ, 2, name='M')
sage: e = M.basis('e')
sage: a = M.automorphism([[1,1],[0,2]], name='a')
sage: a.matrix(e)
[1 1]
[0 2]
sage: a.characteristic_polynomial()
x^2 - 3*x + 2
sage: a.charpoly()
x^2 - 3*x + 2
sage: a.charpoly('T')
T^2 - 3*T + 2
"""
return self._some_matrix().characteristic_polynomial

charpoly = characteristic_polynomial

@lazy_attribute
def det(self):
r"""
Return the determinant of ``self``.
Expand Down Expand Up @@ -1084,13 +1134,62 @@ def det(self):
1
"""
self.matrix() # forces the update of the matrix in the module's default
# basis, to make sure that the dictionary self._matrices
# is not empty
return next(iter(self._matrices.values())).det() # pick a random value in the
# dictionary self._matrices
# and compute the determinant
return self._some_matrix().det

determinant = det

@lazy_attribute
def fcp(self):
r"""
Return the factorization of the characteristic polynomial of ``self``.
INPUT:
- ``var`` -- string (default: ``'x'``); a variable name
EXAMPLES::
sage: M = FiniteRankFreeModule(QQ, 2, name='M')
sage: e = M.basis('e')
sage: a = M.automorphism([[1,1],[0,2]], name='a')
sage: a.matrix(e)
[1 1]
[0 2]
sage: a.fcp() # needs sage.libs.pari
(x - 2) * (x - 1)
sage: a.fcp('T') # needs sage.libs.pari
(T - 2) * (T - 1)
"""
return self._some_matrix().fcp

@lazy_attribute
def minimal_polynomial(self):
r"""
Return the minimal polynomial of ``self``.
:meth:`minimal_polynomial` and :meth:`minpoly` are the same method.
INPUT:
- ``var`` -- string (default: ``'x'``); a variable name
EXAMPLES::
sage: M = FiniteRankFreeModule(GF(7), 3, name='M')
sage: e = M.basis('e')
sage: a = M.automorphism([[0,1,2], [-1,0,3], [2,4,1]], name='a')
sage: a.minpoly() # needs sage.libs.pari
x^3 + 6*x^2 + 6*x + 1
sage: a.minimal_polynomial() # needs sage.libs.pari
x^3 + 6*x^2 + 6*x + 1
sage: a.minimal_polynomial('T') # needs sage.libs.pari
T^3 + 6*T^2 + 6*T + 1
"""
return self._some_matrix().minimal_polynomial

minpoly = minimal_polynomial

@lazy_attribute
def trace(self):
r"""
Return the trace of ``self``.
Expand All @@ -1117,9 +1216,4 @@ def trace(self):
2
"""
self.matrix() # forces the update of the matrix in the module's default
# basis, to make sure that the dictionary self._matrices
# is not empty
return next(iter(self._matrices.values())).trace() # pick a random value in the
# dictionary self._matrices
# and compute the trace
return self._some_matrix().trace

0 comments on commit f12c4e3

Please sign in to comment.