Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
sagemath
GitHub Repository: sagemath/sagesmc
Path: blob/master/src/sage/matrix/matrix_misc.py
8815 views
1
"""
2
Miscellaneous matrix functions
3
4
"""
5
6
#*****************************************************************************
7
# Copyright (C) 2008 William Stein <[email protected]>
8
#
9
# Distributed under the terms of the GNU General Public License (GPL)
10
#
11
# This code is distributed in the hope that it will be useful,
12
# but WITHOUT ANY WARRANTY; without even the implied warranty of
13
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14
# General Public License for more details.
15
#
16
# The full text of the GPL is available at:
17
#
18
# http://www.gnu.org/licenses/
19
#*****************************************************************************
20
21
from sage.categories.fields import Fields
22
_Fields = Fields()
23
24
def row_iterator(A):
25
for i in xrange(A.nrows()):
26
yield A.row(i)
27
28
def weak_popov_form(M,ascend=True):
29
"""
30
This function computes a weak Popov form of a matrix over a rational
31
function field `k(x)`, for `k` a field.
32
33
INPUT:
34
35
- `M` - matrix
36
37
- `ascend` - if True, rows of output matrix `W` are sorted so
38
degree (= the maximum of the degrees of the elements in
39
the row) increases monotonically, and otherwise degrees decrease.
40
41
OUTPUT:
42
43
A 3-tuple `(W,N,d)` consisting of two matrices over `k(x)` and a list
44
of integers:
45
46
1. `W` - matrix giving a weak the Popov form of M
47
2. `N` - matrix representing row operations used to transform
48
`M` to `W`
49
3. `d` - degree of respective columns of W; the degree of a column is
50
the maximum of the degree of its elements
51
52
`N` is invertible over `k(x)`. These matrices satisfy the relation
53
`N*M = W`.
54
55
EXAMPLES:
56
57
The routine expects matrices over the rational function field, but
58
other examples below show how one can provide matrices over the ring
59
of polynomials (whose quotient field is the rational function field).
60
61
::
62
63
sage: R.<t> = GF(3)['t']
64
sage: K = FractionField(R)
65
sage: import sage.matrix.matrix_misc
66
sage: sage.matrix.matrix_misc.weak_popov_form(matrix([[(t-1)^2/t],[(t-1)]]))
67
(
68
[ 0] [ t 2*t + 1]
69
[(2*t + 1)/t], [ 1 2], [-Infinity, 0]
70
)
71
72
NOTES:
73
74
See docstring for weak_popov_form method of matrices for
75
more information.
76
"""
77
78
# determine whether M has polynomial or rational function coefficients
79
R0 = M.base_ring()
80
81
#Compute the base polynomial ring
82
if R0 in _Fields:
83
R = R0.base()
84
else:
85
R = R0
86
from sage.rings.polynomial.polynomial_ring import is_PolynomialRing
87
if not is_PolynomialRing(R):
88
raise TypeError("the coefficients of M must lie in a univariate polynomial ring")
89
90
t = R.gen()
91
92
# calculate least-common denominator of matrix entries and clear
93
# denominators. The result lies in R
94
from sage.rings.arith import lcm
95
from sage.matrix.constructor import matrix
96
from sage.misc.functional import numerator
97
if R0 in _Fields:
98
den = lcm([a.denominator() for a in M.list()])
99
num = matrix([(lambda x : map(numerator, x))(v) for v in map(list,(M*den).rows())])
100
else:
101
# No need to clear denominators
102
den = R.one_element()
103
num = M
104
105
r = [list(v) for v in num.rows()]
106
107
N = matrix(num.nrows(), num.nrows(), R(1)).rows()
108
109
from sage.rings.infinity import Infinity
110
if M.is_zero():
111
return (M, matrix(N), [-Infinity for i in range(num.nrows())])
112
113
rank = 0
114
num_zero = 0
115
while rank != len(r) - num_zero:
116
# construct matrix of leading coefficients
117
v = []
118
for w in map(list, r):
119
# calculate degree of row (= max of degree of entries)
120
d = max([e.numerator().degree() for e in w])
121
122
# extract leading coefficients from current row
123
x = []
124
for y in w:
125
if y.degree() >= d and d >= 0: x.append(y.coeffs()[d])
126
else: x.append(0)
127
v.append(x)
128
l = matrix(v)
129
130
# count number of zero rows in leading coefficient matrix
131
# because they do *not* contribute interesting relations
132
num_zero = 0
133
for v in l.rows():
134
is_zero = 1
135
for w in v:
136
if w != 0:
137
is_zero = 0
138
if is_zero == 1:
139
num_zero += 1
140
141
# find non-trivial relations among the columns of the
142
# leading coefficient matrix
143
kern = l.kernel().basis()
144
rank = num.nrows() - len(kern)
145
146
# do a row operation if there's a non-trivial relation
147
if not rank == len(r) - num_zero:
148
for rel in kern:
149
# find the row of num involved in the relation and of
150
# maximal degree
151
indices = []
152
degrees = []
153
for i in range(len(rel)):
154
if rel[i] != 0:
155
indices.append(i)
156
degrees.append(max([e.degree() for e in r[i]]))
157
158
# find maximum degree among rows involved in relation
159
max_deg = max(degrees)
160
161
# check if relation involves non-zero rows
162
if max_deg != -1:
163
i = degrees.index(max_deg)
164
rel /= rel[indices[i]]
165
166
for j in range(len(indices)):
167
if j != i:
168
# do row operation and record it
169
v = []
170
for k in range(len(r[indices[i]])):
171
v.append(r[indices[i]][k] + rel[indices[j]] * t**(max_deg-degrees[j]) * r[indices[j]][k])
172
r[indices[i]] = v
173
174
v = []
175
for k in range(len(N[indices[i]])):
176
v.append(N[indices[i]][k] + rel[indices[j]] * t**(max_deg-degrees[j]) * N[indices[j]][k])
177
N[indices[i]] = v
178
179
# remaining relations (if any) are no longer valid,
180
# so continue onto next step of algorithm
181
break
182
183
# sort the rows in order of degree
184
d = []
185
from sage.rings.all import infinity
186
for i in range(len(r)):
187
d.append(max([e.degree() for e in r[i]]))
188
if d[i] < 0:
189
d[i] = -infinity
190
else:
191
d[i] -= den.degree()
192
193
for i in range(len(r)):
194
for j in range(i+1,len(r)):
195
if (ascend and d[i] > d[j]) or (not ascend and d[i] < d[j]):
196
(r[i], r[j]) = (r[j], r[i])
197
(d[i], d[j]) = (d[j], d[i])
198
(N[i], N[j]) = (N[j], N[i])
199
200
# return reduced matrix and operations matrix
201
return (matrix(r)/den, matrix(N), d)
202
203