\(J\)-ideals of matrices#
Let \(B\) be an \(n\times n\)-matrix over a principal ideal domain \(D\).
For an ideal \(J\), the \(J\)-ideal of \(B\) is defined to be \(N_J(B) = \{ f\in D[X] \mid f(B) \in M_n(J) \}\).
For a prime element \(p\) of \(D\) and \(t\ge 0\), a \((p^t)\)-minimal polynomial of \(B\) is a monic polynomial \(f\in N_{(p^t)}(B)\) of minimal degree.
This module computes these minimal polynomials.
Let \(p\) be a prime element of \(D\). Then there is a finite set \(\mathcal{S}_p\) of positive integers and monic polynomials \(\nu_{ps}\) for \(s\in\mathcal{S}_p\) such that for \(t\ge 1\),
holds where \(b(t) = \min\{r\in \mathcal{S}_p \mid r \ge s\}\). The degree of \(\nu_{ps}\) is strictly increasing in \(s\in \mathcal{S}_p\) and \(\nu_{ps}\) is a \((p^s)\)-minimal polynomial. If \(t\le \max\mathcal{S}_p\), then the summand \(\mu_BD[X]\) can be omitted.
All computations are done by the class
ComputeMinimalPolynomials
where various intermediate results
are cached. It provides the following methods:
p_minimal_polynomials()
computes \(\mathcal{S}_p\) and the monic polynomials \(\nu_{ps}\).null_ideal()
determines \(N_{(p^t)}(B)\).prime_candidates()
determines all primes \(p\) where \(\mathcal{S}_p\) might be non-empty.integer_valued_polynomials_generators()
determines the generators of the ring \(\{f \in K[X] \mid f(B) \in M_n(D)\}\) of integer valued polynomials on \(B\).
EXAMPLES:
sage: from sage.matrix.compute_J_ideal import ComputeMinimalPolynomials
sage: B = matrix(ZZ, [[1, 0, 1], [1, -2, -1], [10, 0, 0]])
sage: C = ComputeMinimalPolynomials(B)
sage: C.prime_candidates()
[2, 3, 5]
sage: for t in range(4):
....: print(C.null_ideal(2^t))
Principal ideal (1) of
Univariate Polynomial Ring in x over Integer Ring
Ideal (2, x^2 + x) of
Univariate Polynomial Ring in x over Integer Ring
Ideal (4, x^2 + 3*x + 2) of
Univariate Polynomial Ring in x over Integer Ring
Ideal (8, x^3 + x^2 - 12*x - 20, 2*x^2 + 6*x + 4) of
Univariate Polynomial Ring in x over Integer Ring
sage: C.p_minimal_polynomials(2)
{2: x^2 + 3*x + 2}
sage: C.integer_valued_polynomials_generators()
(x^3 + x^2 - 12*x - 20, [1, 1/4*x^2 + 3/4*x + 1/2])
The last output means that
Todo
Test code over PIDs other than ZZ.
This requires implementation of
frobenius()
over more general domains than ZZ.
Additionally, lifting()
requires modification or a bug
needs fixing, see
AskSage Question 35555.
REFERENCES:
AUTHORS:
Clemens Heuberger (2016)
Roswitha Rissner (2016)
ACKNOWLEDGEMENT:
Clemens Heuberger is supported by the Austrian Science Fund (FWF): P 24644-N26.
Roswitha Rissner is supported by the Austrian Science Fund (FWF): P 27816-N26.
Classes and Methods#
- class sage.matrix.compute_J_ideal.ComputeMinimalPolynomials(B)#
Bases:
SageObject
Create an object for computing \((p^t)\)-minimal polynomials and \(J\)-ideals.
For an ideal \(J\) and a square matrix \(B\) over a principal ideal domain \(D\), the \(J\)-ideal of \(B\) is defined to be \(N_J(B) = \{ f\in D[X] \mid f(B) \in M_n(J) \}\).
For a prime element \(p\) of \(D\) and \(t\ge 0\), a \((p^t)\)-minimal polynomial of \(B\) is a monic polynomial \(f\in N_{(p^t)}(B)\) of minimal degree.
The characteristic polynomial of \(B\) is denoted by \(\chi_B\); \(n\) is the size of \(B\).
INPUT:
B
– a square matrix over a principal ideal domain \(D\)
OUTPUT:
An object which allows to call
p_minimal_polynomials()
,null_ideal()
andinteger_valued_polynomials_generators()
.EXAMPLES:
sage: from sage.matrix.compute_J_ideal import ComputeMinimalPolynomials sage: B = matrix(ZZ, [[1, 0, 1], [1, -2, -1], [10, 0, 0]]) sage: C = ComputeMinimalPolynomials(B) sage: C.prime_candidates() [2, 3, 5] sage: for t in range(4): ....: print(C.null_ideal(2^t)) Principal ideal (1) of Univariate Polynomial Ring in x over Integer Ring Ideal (2, x^2 + x) of Univariate Polynomial Ring in x over Integer Ring Ideal (4, x^2 + 3*x + 2) of Univariate Polynomial Ring in x over Integer Ring Ideal (8, x^3 + x^2 - 12*x - 20, 2*x^2 + 6*x + 4) of Univariate Polynomial Ring in x over Integer Ring sage: C.p_minimal_polynomials(2) {2: x^2 + 3*x + 2} sage: C.integer_valued_polynomials_generators() (x^3 + x^2 - 12*x - 20, [1, 1/4*x^2 + 3/4*x + 1/2])
- current_nu(p, t, pt_generators, prev_nu)#
Compute \((p^t)\)-minimal polynomial of \(B\).
INPUT:
p
– a prime element of \(D\)t
– a positive integerpt_generators
– a list \((g_1, \ldots, g_s)\) of polynomials in \(D[X]\) such that \(N_{(p^t)}(B) = (g_1, \ldots, g_s) + pN_{(p^{t-1})}(B)\)prev_nu
– a \((p^{t-1})\)-minimal polynomial of \(B\)
OUTPUT:
A \((p^t)\)-minimal polynomial of \(B\).
EXAMPLES:
sage: from sage.matrix.compute_J_ideal import ComputeMinimalPolynomials sage: B = matrix(ZZ, [[1, 0, 1], [1, -2, -1], [10, 0, 0]]) sage: C = ComputeMinimalPolynomials(B) sage: x = polygen(ZZ, 'x') sage: nu_1 = x^2 + x sage: generators_4 = [2*x^2 + 2*x, x^2 + 3*x + 2] sage: C.current_nu(2, 2, generators_4, nu_1) x^2 + 3*x + 2
ALGORITHM:
[HR2016], Algorithm 4.
- find_monic_replacements(p, t, pt_generators, prev_nu)#
Replace possibly non-monic generators of \(N_{(p^t)}(B)\) by monic generators.
INPUT:
p
– a prime element of \(D\)t
– a non-negative integerpt_generators
– a list \((g_1, \ldots, g_s)\) of polynomials in \(D[X]\) such that \(N_{(p^t)}(B) = (g_1, \ldots, g_s) + pN_{(p^{t-1})}(B)\)prev_nu
– a \((p^{t-1})\)-minimal polynomial of \(B\)
OUTPUT:
A list \((h_1, \ldots, h_r)\) of monic polynomials such that \(N_{(p^t)}(B) = (h_1, \ldots, h_r) + pN_{(p^{t-1})}(B)\).
EXAMPLES:
sage: from sage.matrix.compute_J_ideal import ComputeMinimalPolynomials sage: B = matrix(ZZ, [[1, 0, 1], [1, -2, -1], [10, 0, 0]]) sage: C = ComputeMinimalPolynomials(B) sage: x = polygen(ZZ, 'x') sage: nu_1 = x^2 + x sage: generators_4 = [2*x^2 + 2*x, x^2 + 3*x + 2] sage: C.find_monic_replacements(2, 2, generators_4, nu_1) [x^2 + 3*x + 2]
ALGORITHM:
[HR2016], Algorithms 2 and 3.
- integer_valued_polynomials_generators()#
Determine the generators of the ring of integer valued polynomials on \(B\).
OUTPUT:
A pair
(mu_B, P)
whereP
is a list of polynomials in \(K[X]\) such that\[\{f \in K[X] \mid f(B) \in M_n(D)\} = \mu_B K[X] + \sum_{g\in P} g D[X]\]where \(K\) denotes the fraction field of \(D\).
EXAMPLES:
sage: from sage.matrix.compute_J_ideal import ComputeMinimalPolynomials sage: B = matrix(ZZ, [[1, 0, 1], [1, -2, -1], [10, 0, 0]]) sage: C = ComputeMinimalPolynomials(B) sage: C.integer_valued_polynomials_generators() (x^3 + x^2 - 12*x - 20, [1, 1/4*x^2 + 3/4*x + 1/2])
- mccoy_column(p, t, nu)#
Compute matrix for McCoy’s criterion.
INPUT:
p
– a prime element in \(D\)t
– a positive integernu
– a \((p^t)\)-minimal polynomial of \(B\)
OUTPUT:
An \((n^2 + 1) \times 1\) matrix \(g\) with first entry
nu
such that \(\begin{pmatrix}b& -\chi_B I\end{pmatrix}g \equiv 0\pmod{p^t}\) where \(b\) consists of the entries of \(\operatorname{adj}(X-B)\).EXAMPLES:
sage: from sage.matrix.compute_J_ideal import ComputeMinimalPolynomials sage: B = matrix(ZZ, [[1, 0, 1], [1, -2, -1], [10, 0, 0]]) sage: C = ComputeMinimalPolynomials(B) sage: x = polygen(ZZ, 'x') sage: nu_4 = x^2 + 3*x + 2 sage: g = C.mccoy_column(2, 2, nu_4) sage: b = matrix(9, 1, (x-B).adjugate().list()) sage: M = matrix.block([[b , -B.charpoly(x)*matrix.identity(9)]]) sage: (M*g % 4).is_zero() True
ALGORITHM:
[HR2016], Algorithm 5.
- null_ideal(b=0)#
Return the \((b)\)-ideal \(N_{(b)}(B)=\{f\in D[X] \mid f(B)\in M_n(bD)\}\).
INPUT:
b
– an element of \(D\) (default: 0)
OUTPUT:
An ideal in \(D[X]\).
EXAMPLES:
sage: from sage.matrix.compute_J_ideal import ComputeMinimalPolynomials sage: B = matrix(ZZ, [[1, 0, 1], [1, -2, -1], [10, 0, 0]]) sage: C = ComputeMinimalPolynomials(B) sage: C.null_ideal() Principal ideal (x^3 + x^2 - 12*x - 20) of Univariate Polynomial Ring in x over Integer Ring sage: C.null_ideal(2) Ideal (2, x^2 + x) of Univariate Polynomial Ring in x over Integer Ring sage: C.null_ideal(4) Ideal (4, x^2 + 3*x + 2) of Univariate Polynomial Ring in x over Integer Ring sage: C.null_ideal(8) Ideal (8, x^3 + x^2 - 12*x - 20, 2*x^2 + 6*x + 4) of Univariate Polynomial Ring in x over Integer Ring sage: C.null_ideal(3) Ideal (3, x^3 + x^2 - 12*x - 20) of Univariate Polynomial Ring in x over Integer Ring sage: C.null_ideal(6) Ideal (6, 2*x^3 + 2*x^2 - 24*x - 40, 3*x^2 + 3*x) of Univariate Polynomial Ring in x over Integer Ring
- p_minimal_polynomials(p, s_max=None)#
Compute \((p^s)\)-minimal polynomials \(\nu_s\) of \(B\).
Compute a finite subset \(\mathcal{S}\) of the positive integers and \((p^s)\)-minimal polynomials \(\nu_s\) for \(s \in \mathcal{S}\).
For \(0 < t \le \max \mathcal{S}\), a \((p^t)\)-minimal polynomial is given by \(\nu_s\) where \(s = \min\{ r \in \mathcal{S} \mid r\ge t \}\). For \(t > \max \mathcal{S}\), the minimal polynomial of \(B\) is also a \((p^t)\)-minimal polynomial.
INPUT:
p
– a prime in \(D\)s_max
– a positive integer (default:None
); if set, only \((p^s)\)-minimal polynomials fors <= s_max
are computed (see below for details)
OUTPUT:
A dictionary. Keys are the finite set \(\mathcal{S}\), the values are the associated \((p^s)\)-minimal polynomials \(\nu_s\), \(s \in \mathcal{S}\).
Setting
s_max
only affects the output ifs_max
is at most \(\max\mathcal{S}\) where \(\mathcal{S}\) denotes the full set. In that case, only those \(\nu_s\) withs <= s_max
are returned wheres_max
is always included even if it is not included in the full set \(\mathcal{S}\).EXAMPLES:
sage: from sage.matrix.compute_J_ideal import ComputeMinimalPolynomials sage: B = matrix(ZZ, [[1, 0, 1], [1, -2, -1], [10, 0, 0]]) sage: C = ComputeMinimalPolynomials(B) sage: C.p_minimal_polynomials(2) {2: x^2 + 3*x + 2} sage: set_verbose(1) sage: C = ComputeMinimalPolynomials(B) sage: C.p_minimal_polynomials(2) verbose 1 (...: compute_J_ideal.py, p_minimal_polynomials) ------------------------------------------ verbose 1 (...: compute_J_ideal.py, p_minimal_polynomials) p = 2, t = 1: verbose 1 (...: compute_J_ideal.py, p_minimal_polynomials) Result of lifting: verbose 1 (...: compute_J_ideal.py, p_minimal_polynomials) F = verbose 1 (...: compute_J_ideal.py, p_minimal_polynomials) [x^2 + x] [ x] [ 0] [ 1] [ 1] [ x + 1] [ 1] [ 0] [ 0] [ x + 1] verbose 1 (...: compute_J_ideal.py, current_nu) ------------------------------------------ verbose 1 (...: compute_J_ideal.py, current_nu) (x^2 + x) verbose 1 (...: compute_J_ideal.py, current_nu) Generators with (p^t)-generating property: verbose 1 (...: compute_J_ideal.py, current_nu) [x^2 + x] verbose 1 (...: compute_J_ideal.py, p_minimal_polynomials) nu = x^2 + x verbose 1 (...: compute_J_ideal.py, p_minimal_polynomials) corresponding columns for G verbose 1 (...: compute_J_ideal.py, p_minimal_polynomials) [x^2 + x] [ x + 2] [ 0] [ 1] [ 1] [ x - 1] [ -1] [ 10] [ 0] [ x + 1] verbose 1 (...: compute_J_ideal.py, p_minimal_polynomials) ------------------------------------------ verbose 1 (...: compute_J_ideal.py, p_minimal_polynomials) p = 2, t = 2: verbose 1 (...: compute_J_ideal.py, p_minimal_polynomials) Result of lifting: verbose 1 (...: compute_J_ideal.py, p_minimal_polynomials) F = verbose 1 (...: compute_J_ideal.py, p_minimal_polynomials) [ 2*x^2 + 2*x x^2 + 3*x + 2] [ 2*x x + 4] [ 0 0] [ 2 1] [ 2 1] [ 2*x + 2 x + 1] [ 2 -1] [ 0 10] [ 0 0] [ 2*x + 2 x + 3] verbose 1 (...: compute_J_ideal.py, current_nu) ------------------------------------------ verbose 1 (...: compute_J_ideal.py, current_nu) (2*x^2 + 2*x, x^2 + 3*x + 2) verbose 1 (...: compute_J_ideal.py, current_nu) Generators with (p^t)-generating property: verbose 1 (...: compute_J_ideal.py, current_nu) [x^2 + 3*x + 2] verbose 1 (...: compute_J_ideal.py, p_minimal_polynomials) nu = x^2 + 3*x + 2 verbose 1 (...: compute_J_ideal.py, p_minimal_polynomials) corresponding columns for G verbose 1 (...: compute_J_ideal.py, p_minimal_polynomials) [x^2 + 3*x + 2] [ x + 4] [ 0] [ 1] [ 1] [ x + 1] [ -1] [ 10] [ 0] [ x + 3] verbose 1 (...: compute_J_ideal.py, p_minimal_polynomials) ------------------------------------------ verbose 1 (...: compute_J_ideal.py, p_minimal_polynomials) p = 2, t = 3: verbose 1 (...: compute_J_ideal.py, p_minimal_polynomials) Result of lifting: verbose 1 (...: compute_J_ideal.py, p_minimal_polynomials) F = verbose 1 (...: compute_J_ideal.py, p_minimal_polynomials) [x^3 + 7*x^2 + 6*x x^3 + 3*x^2 + 2*x] [ x^2 + 8*x x^2 + 4*x] [ 0 0] [ x x + 4] [ x + 4 x] [ x^2 + 5*x + 4 x^2 + x] [ -x + 4 -x] [ 10*x 10*x] [ 0 0] [ x^2 + 7*x x^2 + 3*x + 4] verbose 1 (...: compute_J_ideal.py, current_nu) ------------------------------------------ verbose 1 (...: compute_J_ideal.py, current_nu) (x^3 + 7*x^2 + 6*x, x^3 + 3*x^2 + 2*x) verbose 1 (...: compute_J_ideal.py, current_nu) Generators with (p^t)-generating property: verbose 1 (...: compute_J_ideal.py, current_nu) ... verbose 1 (...: compute_J_ideal.py, current_nu) [x^3 + 3*x^2 + 2*x] verbose 1 (...: compute_J_ideal.py, p_minimal_polynomials) nu = x^3 + 3*x^2 + 2*x {2: x^2 + 3*x + 2} sage: set_verbose(0) sage: C.p_minimal_polynomials(2, s_max=1) {1: x^2 + x} sage: C.p_minimal_polynomials(2, s_max=2) {2: x^2 + 3*x + 2} sage: C.p_minimal_polynomials(2, s_max=3) {2: x^2 + 3*x + 2}
ALGORITHM:
[HR2016], Algorithm 5.
- prime_candidates()#
Determine those primes \(p\) where \(\mu_B\) might not be a \((p)\)-minimal polynomial.
OUTPUT:
A list of primes.
EXAMPLES:
sage: from sage.matrix.compute_J_ideal import ComputeMinimalPolynomials sage: B = matrix(ZZ, [[1, 0, 1], [1, -2, -1], [10, 0, 0]]) sage: C = ComputeMinimalPolynomials(B) sage: C.prime_candidates() [2, 3, 5] sage: C.p_minimal_polynomials(2) {2: x^2 + 3*x + 2} sage: C.p_minimal_polynomials(3) {} sage: C.p_minimal_polynomials(5) {}
This means that \(3\) and \(5\) were candidates, but actually, \(\mu_B\) turns out to be a \((3)\)-minimal polynomial and a \((5)\)-minimal polynomial.
- sage.matrix.compute_J_ideal.lifting(p, t, A, G)#
Compute generators of \(\{f \in D[X]^d \mid Af \equiv 0 \pmod{p^{t}}\}\) given generators of \(\{f\in D[X]^d \mid Af \equiv 0\pmod{p^{t-1}}\}\).
INPUT:
p
– a prime element of some principal ideal domain \(D\)t
– a non-negative integerA
– a \(c\times d\) matrix over \(D[X]\)G
– a matrix over \(D[X]\). The columns of \(\begin{pmatrix}p^{t-1}I& G\end{pmatrix}\) are generators of \(\{ f\in D[X]^d \mid Af \equiv 0\pmod{p^{t-1}}\}\); can be set toNone
ift
is zero
OUTPUT:
A matrix \(F\) over \(D[X]\) such that the columns of \(\begin{pmatrix}p^tI&F&pG\end{pmatrix}\) are generators of \(\{ f\in D[X]^d \mid Af \equiv 0\pmod{p^t}\}\).
EXAMPLES:
sage: from sage.matrix.compute_J_ideal import lifting sage: X = polygen(ZZ, 'X') sage: A = matrix([[1, X], [2*X, X^2]]) sage: G0 = lifting(5, 0, A, None) sage: G1 = lifting(5, 1, A, G0); G1 [] sage: (A*G1 % 5).is_zero() True sage: A = matrix([[1, X, X^2], [2*X, X^2, 3*X^3]]) sage: G0 = lifting(5, 0, A, None) sage: G1 = lifting(5, 1, A, G0); G1 [3*X^2] [ X] [ 1] sage: (A*G1 % 5).is_zero() True sage: G2 = lifting(5, 2, A, G1); G2 [15*X^2 23*X^2] [ 5*X X] [ 5 1] sage: (A*G2 % 25).is_zero() True sage: lifting(5, 10, A, G1) Traceback (most recent call last): ... ValueError: A*G not zero mod 5^9
ALGORITHM:
[HR2016], Algorithm 1.
- sage.matrix.compute_J_ideal.p_part(f, p)#
Compute the \(p\)-part of a polynomial.
INPUT:
f
– a polynomial over \(D\)p
– a prime in \(D\)
OUTPUT:
A polynomial \(g\) such that \(\deg g \le \deg f\) and all non-zero coefficients of \(f - p g\) are not divisible by \(p\).
EXAMPLES:
sage: from sage.matrix.compute_J_ideal import p_part sage: X = polygen(ZZ, 'X') sage: f = X^3 + 5*X + 25 sage: g = p_part(f, 5); g X + 5 sage: f - 5*g X^3