@@ -89,6 +89,7 @@ from sage.structure.element cimport have_same_parent
89
89
from sage.misc.verbose import verbose
90
90
from sage.categories.fields import Fields
91
91
from sage.categories.integral_domains import IntegralDomains
92
+ from sage.categories.principal_ideal_domains import PrincipalIdealDomains
92
93
from sage.rings.ring import is_Ring
93
94
from sage.rings.number_field.number_field_base import NumberField
94
95
from sage.rings.integer_ring import ZZ, is_IntegerRing
@@ -102,6 +103,8 @@ from . import berlekamp_massey
102
103
from sage.modules.free_module_element import is_FreeModuleElement
103
104
from sage.matrix.matrix_misc import permanental_minor_polynomial
104
105
106
+ from sage.misc.misc_c import prod
107
+
105
108
# used to deprecate only adjoint method
106
109
from sage.misc.superseded import deprecated_function_alias
107
110
@@ -15898,6 +15901,148 @@ cdef class Matrix(Matrix1):
15898
15901
else:
15899
15902
return dp
15900
15903
15904
+ def fitting_ideal(self, i):
15905
+ r"""
15906
+ Return the `i`-th Fitting ideal of the matrix. This is the ideal generated
15907
+ by the `n - i` minors, where `n` is the number of columns.
15908
+
15909
+ INPUT:
15910
+
15911
+ ``i`` -- an integer
15912
+
15913
+ OUTPUT:
15914
+
15915
+ An ideal on the base ring.
15916
+
15917
+ EXAMPLES::
15918
+
15919
+ sage: R.<x,y,z> = QQ[]
15920
+ sage: M = matrix(R, [[2*x-z, 0, y-z^2, 1], [0, z - y, z - x, 0],[z - y, x^2 - y, 0, 0]])
15921
+ sage: M
15922
+ [ 2*x - z 0 -z^2 + y 1]
15923
+ [ 0 -y + z -x + z 0]
15924
+ [ -y + z x^2 - y 0 0]
15925
+ sage: [R.ideal(M.minors(i)) == M.fitting_ideal(4-i) for i in range(5)]
15926
+ [True, True, True, True, True]
15927
+ sage: M.fitting_ideal(0)
15928
+ Ideal (0) of Multivariate Polynomial Ring in x, y, z over Rational Field
15929
+ sage: M.fitting_ideal(1)
15930
+ Ideal (2*x^4 - 3*x^3*z + x^2*z^2 + y^2*z^2 - 2*y*z^3 + z^4 - 2*x^2*y - y^3 + 3*x*y*z + 2*y^2*z - 2*y*z^2, -x^3 + x^2*z + x*y - y*z, y^2 - 2*y*z + z^2, x*y - x*z - y*z + z^2) of Multivariate Polynomial Ring in x, y, z over Rational Field
15931
+ sage: M.fitting_ideal(3)
15932
+ Ideal (2*x - z, -z^2 + y, 1, -y + z, -x + z, -y + z, x^2 - y) of Multivariate Polynomial Ring in x, y, z over Rational Field
15933
+ sage: M.fitting_ideal(4)
15934
+ Ideal (1) of Multivariate Polynomial Ring in x, y, z over Rational Field
15935
+
15936
+
15937
+ If the base ring is a field, the Fitting ideals are zero under the corank::
15938
+
15939
+ sage: M = matrix(QQ, [[2,1,3,5],[4,2,6,6],[0,3,2,0]])
15940
+ sage: M
15941
+ [2 1 3 5]
15942
+ [4 2 6 6]
15943
+ [0 3 2 0]
15944
+ sage: M.fitting_ideal(0)
15945
+ Principal ideal (0) of Rational Field
15946
+ sage: M.fitting_ideal(1)
15947
+ Principal ideal (1) of Rational Field
15948
+ sage: M.fitting_ideal(2)
15949
+ Principal ideal (1) of Rational Field
15950
+ sage: M.fitting_ideal(3)
15951
+ Principal ideal (1) of Rational Field
15952
+ sage: M.fitting_ideal(4)
15953
+ Principal ideal (1) of Rational Field
15954
+
15955
+
15956
+ In the case of principal ideal domains, it is given by the elementary
15957
+ divisors::
15958
+
15959
+ sage: M = matrix([[2,1,3,5],[4,2,6,6],[0,3,2,0]])
15960
+ sage: M
15961
+ [2 1 3 5]
15962
+ [4 2 6 6]
15963
+ [0 3 2 0]
15964
+ sage: M.fitting_ideal(0)
15965
+ Principal ideal (0) of Integer Ring
15966
+ sage: M.fitting_ideal(1)
15967
+ Principal ideal (4) of Integer Ring
15968
+ sage: M.fitting_ideal(2)
15969
+ Principal ideal (1) of Integer Ring
15970
+ sage: M.fitting_ideal(3)
15971
+ Principal ideal (1) of Integer Ring
15972
+ sage: M.fitting_ideal(4)
15973
+ Principal ideal (1) of Integer Ring
15974
+ sage: M.elementary_divisors()
15975
+ [1, 1, 4]
15976
+
15977
+ This is also true for univariate polynomials over a field::
15978
+
15979
+ sage: R.<x> = QQ[]
15980
+ sage: M = matrix(R,[[x^2-2*x+1, x-1,x^2-1],[0,x+1,1]])
15981
+ sage: M.fitting_ideal(0)
15982
+ Principal ideal (0) of Univariate Polynomial Ring in x over Rational Field
15983
+ sage: M.fitting_ideal(1)
15984
+ Principal ideal (x - 1) of Univariate Polynomial Ring in x over Rational Field
15985
+ sage: M.fitting_ideal(2)
15986
+ Principal ideal (1) of Univariate Polynomial Ring in x over Rational Field
15987
+ sage: M.smith_form()[0]
15988
+ [ 1 0 0]
15989
+ [ 0 x - 1 0]
15990
+
15991
+ """
15992
+ R = self.base_ring()
15993
+ if not R.is_exact():
15994
+ raise NotImplementedError("Fitting ideals over non-exact rings not implemented at present")
15995
+ n = self.ncols()
15996
+ rank_minors = n - i
15997
+ if rank_minors > self.nrows():
15998
+ return R.ideal([R.zero()])
15999
+ elif rank_minors <= 0:
16000
+ return R.ideal([R.one()])
16001
+ elif rank_minors == 1:
16002
+ return R.ideal(self.coefficients())
16003
+ if R in _Fields:
16004
+ if self.rank() >= rank_minors:
16005
+ return R.ideal([1])
16006
+ else:
16007
+ return R.ideal([0])
16008
+ try:
16009
+ elemdiv = self.elementary_divisors()
16010
+ if rank_minors > len(elemdiv):
16011
+ return R.ideal([0])
16012
+ return R.ideal(prod(elemdiv[:rank_minors]))
16013
+ except (TypeError, NotImplementedError, ArithmeticError):
16014
+ pass
16015
+ for (nr,r) in enumerate(self.rows()):
16016
+ nz = [e for e in enumerate(r) if e[1]]
16017
+ if len(nz) == 0:
16018
+ N = self.delete_rows([nr])
16019
+ return N.fitting_ideal(i)
16020
+ elif len(nz) == 1:
16021
+ N = self.delete_rows([nr])
16022
+ F1 = N.fitting_ideal(i)
16023
+ N = N.delete_columns([nz[0][0]])
16024
+ F2 = N.fitting_ideal(i)
16025
+ return F1 + nz[0][1]*F2
16026
+ for (nc,c) in enumerate(self.columns()):
16027
+ nz = [e for e in enumerate(c) if e[1]]
16028
+ if len(nz) == 0:
16029
+ N = self.delete_columns([nc])
16030
+ return N.fitting_ideal(i - 1)
16031
+ elif len(nz) == 1:
16032
+ N = self.delete_columns([nc])
16033
+ F1 = N.fitting_ideal(i-1)
16034
+ N = N.delete_rows([nz[0][0]])
16035
+ F2 = N.fitting_ideal(i)
16036
+ return F1 + nz[0][1]*F2
16037
+ if hasattr(self, '_fitting_ideal'):
16038
+ try:
16039
+ return self._fitting_ideal(i)
16040
+ except NotImplementedError:
16041
+ pass
16042
+ return R.ideal(self.minors(rank_minors))
16043
+
16044
+
16045
+
15901
16046
def _hermite_form_euclidean(self, transformation=False, normalization=None):
15902
16047
"""
15903
16048
Transform the matrix in place to hermite normal form and optionally
0 commit comments