Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
sagemath
GitHub Repository: sagemath/sagesmc
Path: blob/master/src/sage/modular/modsym/relation_matrix.py
8820 views
1
"""
2
Relation matrices for ambient modular symbols spaces
3
4
This file contains functions that are used by the various ambient modular
5
symbols classes to compute presentations of spaces in terms of generators and
6
relations, using the standard methods based on Manin symbols.
7
"""
8
9
#*****************************************************************************
10
# Sage: System for Algebra and Geometry Experimentation
11
#
12
# Copyright (C) 2005 William Stein <[email protected]>
13
#
14
# Distributed under the terms of the GNU General Public License (GPL)
15
#
16
# This code is distributed in the hope that it will be useful,
17
# but WITHOUT ANY WARRANTY; without even the implied warranty of
18
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19
# General Public License for more details.
20
#
21
# The full text of the GPL is available at:
22
#
23
# http://www.gnu.org/licenses/
24
#*****************************************************************************
25
26
SPARSE=True
27
28
import sage.matrix.matrix_space as matrix_space
29
import sage.matrix.all
30
import sage.rings.all as rings
31
from sage.misc.search import search
32
from sage.rings.rational_field import is_RationalField
33
34
35
import sage.misc.misc as misc
36
37
import manin_symbols
38
39
40
# S = [0,-1; 1,0]
41
# T = [0,-1; 1,-1],
42
# T^2 = [-1, 1, -1, 0]
43
# I = [-1,0; 0,1]
44
45
46
######################################################################
47
# The following four functions are used to compute the quotient
48
# modulo the S, I, and T relations more efficiently that the generic
49
# code in the relation_matrix file:
50
# modS_relations -- compute the S relations.
51
# modI_quotient -- compute the I relations.
52
# T_relation_matrix -- matrix whose echelon form gives
53
# the quotient by 3-term T relations.
54
# gens_to_basis_matrix -- compute echelon form of 3-term
55
# relation matrix, and read off each
56
# generator in terms of basis.
57
# These four functions are orchestrated in the function
58
# compute_presentation
59
# which is defined below. See the comment at the beginning
60
# of that function for an overall description of the algorithm.
61
######################################################################
62
def modS_relations(syms):
63
"""
64
Compute quotient of Manin symbols by the S relations.
65
66
Here S is the 2x2 matrix [0, -1; 1, 0].
67
68
INPUT:
69
70
71
- ``syms`` - manin_symbols.ManinSymbols
72
73
74
OUTPUT:
75
76
77
- ``rels`` - set of pairs of pairs (j, s), where if
78
mod[i] = (j,s), then x_i = s\*x_j (mod S relations)
79
80
81
EXAMPLES::
82
83
sage: from sage.modular.modsym.manin_symbols import ManinSymbolList_gamma0
84
sage: from sage.modular.modsym.relation_matrix import modS_relations
85
86
::
87
88
sage: syms = ManinSymbolList_gamma0(2, 4); syms
89
Manin Symbol List of weight 4 for Gamma0(2)
90
sage: modS_relations(syms)
91
set([((3, -1), (4, 1)), ((5, -1), (5, 1)), ((1, 1), (6, 1)), ((0, 1), (7, 1)), ((3, 1), (4, -1)), ((2, 1), (8, 1))])
92
93
::
94
95
sage: syms = ManinSymbolList_gamma0(7, 2); syms
96
Manin Symbol List of weight 2 for Gamma0(7)
97
sage: modS_relations(syms)
98
set([((3, 1), (4, 1)), ((2, 1), (7, 1)), ((5, 1), (6, 1)), ((0, 1), (1, 1))])
99
100
Next we do an example with Gamma1::
101
102
sage: from sage.modular.modsym.manin_symbols import ManinSymbolList_gamma1
103
sage: syms = ManinSymbolList_gamma1(3,2); syms
104
Manin Symbol List of weight 2 for Gamma1(3)
105
sage: modS_relations(syms)
106
set([((3, 1), (6, 1)), ((0, 1), (5, 1)), ((0, 1), (2, 1)), ((3, 1), (4, 1)), ((6, 1), (7, 1)), ((1, 1), (2, 1)), ((1, 1), (5, 1)), ((4, 1), (7, 1))])
107
"""
108
if not isinstance(syms, manin_symbols.ManinSymbolList):
109
raise TypeError, "syms must be a ManinSymbolList"
110
tm = misc.verbose()
111
# We will fill in this set with the relations x_i + s*x_j = 0,
112
# where the notation is as in _sparse_2term_quotient.
113
rels = set()
114
for i in xrange(len(syms)):
115
j, s = syms.apply_S(i)
116
assert j != -1
117
if i < j:
118
rels.add( ((i,1),(j,s)) )
119
else:
120
rels.add( ((j,s),(i,1)) )
121
misc.verbose("finished creating S relations",tm)
122
return rels
123
124
def modI_relations(syms, sign):
125
"""
126
Compute quotient of Manin symbols by the I relations.
127
128
INPUT:
129
130
- ``syms`` - ManinSymbols
131
132
- ``sign`` - int (either -1, 0, or 1)
133
134
OUTPUT:
135
136
- ``rels`` - set of pairs of pairs (j, s), where if
137
mod[i] = (j,s), then x_i = s\*x_j (mod S relations)
138
139
EXAMPLE::
140
141
sage: L = sage.modular.modsym.manin_symbols.ManinSymbolList_gamma1(4, 3)
142
sage: sage.modular.modsym.relation_matrix.modI_relations(L, 1)
143
set([((14, 1), (20, 1)), ((0, 1), (0, -1)), ((7, 1), (7, -1)), ((9, 1), (3, -1)), ((3, 1), (9, -1)), ((16, 1), (22, 1)), ((10, 1), (4, -1)), ((1, 1), (1, -1)), ((19, 1), (19, 1)), ((8, 1), (2, -1)), ((12, 1), (12, 1)), ((20, 1), (14, 1)), ((21, 1), (15, 1)), ((5, 1), (11, -1)), ((15, 1), (21, 1)), ((22, 1), (16, 1)), ((6, 1), (6, -1)), ((2, 1), (8, -1)), ((17, 1), (23, 1)), ((4, 1), (10, -1)), ((18, 1), (18, 1)), ((11, 1), (5, -1)), ((23, 1), (17, 1)), ((13, 1), (13, 1))])
144
145
.. warning::
146
147
We quotient by the involution eta((u,v)) = (-u,v), which has
148
the opposite sign as the involution in Merel's Springer LNM
149
1585 paper! Thus our +1 eigenspace is his -1 eigenspace,
150
etc. We do this for consistency with MAGMA.
151
"""
152
tm = misc.verbose()
153
# We will fill in this set with the relations x_i - sign*s*x_j = 0,
154
# where the notation is as in _sparse_2term_quotient.
155
rels = set()
156
for i in xrange(len(syms)):
157
j, s = syms.apply_I(i)
158
assert j != -1
159
rels.add( ((i,1),(j,-sign*s)) )
160
misc.verbose("finished creating I relations",tm)
161
return rels
162
163
def T_relation_matrix_wtk_g0(syms, mod, field, sparse):
164
r"""
165
Compute a matrix whose echelon form gives the quotient by 3-term T
166
relations. Despite the name, this is used for all modular symbols spaces
167
(including those with character and those for `\Gamma_1` and `\Gamma_H`
168
groups), not just `\Gamma_0`.
169
170
INPUT:
171
172
- ``syms`` - ManinSymbols
173
174
- ``mod`` - list that gives quotient modulo some two-term relations, i.e.,
175
the S relations, and if sign is nonzero, the I relations.
176
177
- ``field`` - base_ring
178
179
- ``sparse`` - (True or False) whether to use sparse rather than dense
180
linear algebra
181
182
OUTPUT: A sparse matrix whose rows correspond to the reduction of
183
the T relations modulo the S and I relations.
184
185
EXAMPLE::
186
187
sage: from sage.modular.modsym.relation_matrix import *
188
sage: L = sage.modular.modsym.manin_symbols.ManinSymbolList_gamma_h(GammaH(36, [17,19]), 2)
189
sage: modS = sparse_2term_quotient(modS_relations(L), 216, QQ)
190
sage: T_relation_matrix_wtk_g0(L, modS, QQ, False)
191
72 x 216 dense matrix over Rational Field
192
sage: T_relation_matrix_wtk_g0(L, modS, GF(17), True)
193
72 x 216 sparse matrix over Finite Field of size 17
194
"""
195
tm = misc.verbose()
196
row = 0
197
entries = {}
198
already_seen = set()
199
w = syms.weight()
200
for i in xrange(len(syms)):
201
if i in already_seen:
202
continue
203
iT_plus_iTT = syms.apply_T(i) + syms.apply_TT(i)
204
j0, s0 = mod[i]
205
v = {j0:s0}
206
for j, s in iT_plus_iTT:
207
if w==2: already_seen.add(j)
208
j0, s0 = mod[j]
209
s0 = s*s0
210
if v.has_key(j0):
211
v[j0] += s0
212
else:
213
v[j0] = s0
214
for j0 in v.keys():
215
entries[(row, j0)] = v[j0]
216
row += 1
217
218
MAT = matrix_space.MatrixSpace(field, row,
219
len(syms), sparse=True)
220
R = MAT(entries)
221
if not sparse:
222
R = R.dense_matrix()
223
misc.verbose("finished (number of rows=%s)"%row, tm)
224
return R
225
226
def gens_to_basis_matrix(syms, relation_matrix, mod, field, sparse):
227
"""
228
Compute echelon form of 3-term relation matrix, and read off each
229
generator in terms of basis.
230
231
INPUT:
232
233
- ``syms`` - a ManinSymbols object
234
235
- ``relation_matrix`` - as output by
236
``__compute_T_relation_matrix(self, mod)``
237
238
- ``mod`` - quotient of modular symbols modulo the
239
2-term S (and possibly I) relations
240
241
- ``field`` - base field
242
243
- ``sparse`` - (bool): whether or not matrix should be
244
sparse
245
246
OUTPUT:
247
248
- ``matrix`` - a matrix whose ith row expresses the
249
Manin symbol generators in terms of a basis of Manin symbols
250
(modulo the S, (possibly I,) and T rels) Note that the entries of
251
the matrix need not be integers.
252
253
- ``list`` - integers i, such that the Manin symbols `x_i` are a basis.
254
255
EXAMPLE::
256
257
sage: from sage.modular.modsym.relation_matrix import *
258
sage: L = sage.modular.modsym.manin_symbols.ManinSymbolList_gamma1(4, 3)
259
sage: modS = sparse_2term_quotient(modS_relations(L), 24, GF(3))
260
sage: gens_to_basis_matrix(L, T_relation_matrix_wtk_g0(L, modS, GF(3), 24), modS, GF(3), True)
261
(24 x 2 sparse matrix over Finite Field of size 3, [13, 23])
262
"""
263
from sage.matrix.matrix import is_Matrix
264
if not is_Matrix(relation_matrix):
265
raise TypeError("relation_matrix must be a matrix")
266
if not isinstance(mod, list):
267
raise TypeError("mod must be a list")
268
269
misc.verbose(str(relation_matrix.parent()))
270
271
try:
272
h = relation_matrix.height()
273
except AttributeError:
274
h = 9999999
275
tm = misc.verbose("putting relation matrix in echelon form (height = %s)"%h)
276
if h < 10:
277
A = relation_matrix.echelon_form(algorithm='multimodular', height_guess=1)
278
else:
279
A = relation_matrix.echelon_form()
280
A.set_immutable()
281
tm = misc.verbose('finished echelon', tm)
282
283
tm = misc.verbose("Now creating gens --> basis mapping")
284
285
basis_set = set(A.nonpivots())
286
pivots = A.pivots()
287
288
basis_mod2 = set([j for j,c in mod if c != 0])
289
290
basis_set = basis_set.intersection(basis_mod2)
291
basis = list(basis_set)
292
basis.sort()
293
294
ONE = field(1)
295
296
misc.verbose("done doing setup",tm)
297
298
299
tm = misc.verbose("now forming quotient matrix")
300
M = matrix_space.MatrixSpace(field, len(syms), len(basis), sparse=sparse)
301
302
B = M(0)
303
cols_index = dict([(basis[i], i) for i in range(len(basis))])
304
305
for i in basis_mod2:
306
t, l = search(basis, i)
307
if t:
308
B[i,l] = ONE
309
else:
310
_, r = search(pivots, i) # so pivots[r] = i
311
# Set row i to -(row r of A), but where we only take
312
# the non-pivot columns of A:
313
B._set_row_to_negative_of_row_of_A_using_subset_of_columns(i, A, r, basis, cols_index)
314
315
misc.verbose("done making quotient matrix",tm)
316
317
# The following is very fast (over Q at least).
318
tm = misc.verbose('now filling in the rest of the matrix')
319
k = 0
320
for i in range(len(mod)):
321
j, s = mod[i]
322
if j != i and s != 0: # ignored in the above matrix
323
k += 1
324
B.set_row_to_multiple_of_row(i, j, s)
325
misc.verbose("set %s rows"%k)
326
tm = misc.verbose("time to fill in rest of matrix", tm)
327
328
return B, basis
329
330
def compute_presentation(syms, sign, field, sparse=None):
331
r"""
332
Compute the presentation for self, as a quotient of Manin symbols
333
modulo relations.
334
335
INPUT:
336
337
- ``syms`` - manin_symbols.ManinSymbols
338
339
- ``sign`` - integer (-1, 0, 1)
340
341
- ``field`` - a field
342
343
344
OUTPUT:
345
346
- sparse matrix whose rows give each generator
347
in terms of a basis for the quotient
348
349
- list of integers that give the basis for the
350
quotient
351
352
- mod: list where mod[i]=(j,s) means that x_i
353
= s\*x_j modulo the 2-term S (and possibly I) relations.
354
355
356
ALGORITHM:
357
358
#. Let `S = [0,-1; 1,0], T = [0,-1; 1,-1]`, and
359
`I = [-1,0; 0,1]`.
360
361
#. Let `x_0,\ldots, x_{n-1}` by a list of all
362
non-equivalent Manin symbols.
363
364
#. Form quotient by 2-term S and (possibly) I relations.
365
366
#. Create a sparse matrix `A` with `m` columns,
367
whose rows encode the relations
368
369
.. math::
370
371
[x_i] + [x_i T] + [x_i T^2] = 0.
372
373
374
There are about n such rows. The number of nonzero entries per row
375
is at most 3\*(k-1). Note that we must include rows for *all* i,
376
since even if `[x_i] = [x_j]`, it need not be the case
377
that `[x_i T] = [x_j T]`, since `S` and
378
`T` do not commute. However, in many cases we have an a
379
priori formula for the dimension of the quotient by all these
380
relations, so we can omit many relations and just check that there
381
are enough at the end--if there aren't, we add in more.
382
383
#. Compute the reduced row echelon form of `A` using sparse
384
Gaussian elimination.
385
386
#. Use what we've done above to read off a sparse matrix R that
387
uniquely expresses each of the n Manin symbols in terms of a subset
388
of Manin symbols, modulo the relations. This subset of Manin
389
symbols is a basis for the quotient by the relations.
390
391
392
EXAMPLE::
393
394
sage: L = sage.modular.modsym.manin_symbols.ManinSymbolList_gamma0(8,2)
395
sage: sage.modular.modsym.relation_matrix.compute_presentation(L, 1, GF(9,'a'), True)
396
(
397
[2 0 0]
398
[1 0 0]
399
[0 0 0]
400
[0 2 0]
401
[0 0 0]
402
[0 0 2]
403
[0 0 0]
404
[0 2 0]
405
[0 0 0]
406
[0 1 0]
407
[0 1 0]
408
[0 0 1], [1, 9, 11], [(1, 2), (1, 1), (0, 0), (9, 2), (0, 0), (11, 2), (0, 0), (9, 2), (0, 0), (9, 1), (9, 1), (11, 1)]
409
)
410
"""
411
if sparse is None:
412
if syms.weight() >= 6:
413
sparse = False
414
else:
415
sparse = True
416
R, mod = relation_matrix_wtk_g0(syms, sign, field, sparse)
417
B, basis = gens_to_basis_matrix(syms, R, mod, field, sparse)
418
return B, basis, mod
419
420
def relation_matrix_wtk_g0(syms, sign, field, sparse):
421
r"""
422
Compute the matrix of relations. Despite the name, this is used for all
423
spaces (not just for Gamma0). For a description of the algorithm, see the
424
docstring for ``compute_presentation``.
425
426
INPUT:
427
428
- ``syms``: sage.modular.modsym.manin_symbols.ManinSymbolList object
429
430
- ``sign``: integer (0, 1 or -1)
431
432
- ``field``: the base field (non-field base rings not supported at present)
433
434
- ``sparse``: (True or False) whether to use sparse arithmetic.
435
436
Note that ManinSymbolList objects already have a specific weight, so there
437
is no need for an extra ``weight`` parameter.
438
439
OUTPUT: a pair (R, mod) where
440
441
- R is a matrix as output by ``T_relation_matrix_wtk_g0``
442
443
- mod is a set of 2-term relations as output by ``sparse_2term_quotient``
444
445
EXAMPLE::
446
447
sage: L = sage.modular.modsym.manin_symbols.ManinSymbolList_gamma0(8,2)
448
sage: A = sage.modular.modsym.relation_matrix.relation_matrix_wtk_g0(L, 0, GF(2), True); A
449
(
450
[0 0 0 0 0 0 0 0 1 0 0 0]
451
[0 0 0 0 0 0 0 0 1 1 1 0]
452
[0 0 0 0 0 0 1 0 0 1 1 0]
453
[0 0 0 0 0 0 1 0 0 0 0 0], [(1, 1), (1, 1), (8, 1), (10, 1), (6, 1), (11, 1), (6, 1), (9, 1), (8, 1), (9, 1), (10, 1), (11, 1)]
454
)
455
sage: A[0].is_sparse()
456
True
457
"""
458
rels = modS_relations(syms)
459
if sign != 0:
460
# Let rels = rels union I relations.
461
rels.update(modI_relations(syms,sign))
462
463
if syms._apply_S_only_0pm1() and is_RationalField(field):
464
import relation_matrix_pyx
465
mod = relation_matrix_pyx.sparse_2term_quotient_only_pm1(rels, len(syms))
466
else:
467
mod = sparse_2term_quotient(rels, len(syms), field)
468
469
R = T_relation_matrix_wtk_g0(syms, mod, field, sparse)
470
return R, mod
471
472
def sparse_2term_quotient(rels, n, F):
473
r"""
474
Performs Sparse Gauss elimination on a matrix all of whose columns
475
have at most 2 nonzero entries. We use an obvious algorithm, which
476
runs fast enough. (Typically making the list of relations takes
477
more time than computing this quotient.) This algorithm is more
478
subtle than just "identify symbols in pairs", since complicated
479
relations can cause generators to surprisingly equal 0.
480
481
INPUT:
482
483
484
- ``rels`` - set of pairs ((i,s), (j,t)). The pair
485
represents the relation s\*x_i + t\*x_j = 0, where the i, j must
486
be Python int's.
487
488
- ``n`` - int, the x_i are x_0, ..., x_n-1.
489
490
- ``F`` - base field
491
492
493
OUTPUT:
494
495
496
- ``mod`` - list such that mod[i] = (j,s), which means
497
that x_i is equivalent to s\*x_j, where the x_j are a basis for
498
the quotient.
499
500
501
EXAMPLE: We quotient out by the relations
502
503
.. math::
504
505
3*x0 - x1 = 0,\qquad x1 + x3 = 0,\qquad x2 + x3 = 0,\qquad x4 - x5 = 0
506
507
508
to get
509
510
::
511
512
sage: v = [((int(0),3), (int(1),-1)), ((int(1),1), (int(3),1)), ((int(2),1),(int(3),1)), ((int(4),1),(int(5),-1))]
513
sage: rels = set(v)
514
sage: n = 6
515
sage: from sage.modular.modsym.relation_matrix import sparse_2term_quotient
516
sage: sparse_2term_quotient(rels, n, QQ)
517
[(3, -1/3), (3, -1), (3, -1), (3, 1), (5, 1), (5, 1)]
518
"""
519
if not isinstance(rels, set):
520
raise TypeError, "rels must be a set"
521
n = int(n)
522
if not isinstance(F, rings.Ring):
523
raise TypeError, "F must be a ring."
524
525
tm = misc.verbose("Starting sparse 2-term quotient...")
526
free = range(n)
527
ONE = F(1)
528
ZERO = F(0)
529
coef = [ONE for i in xrange(n)]
530
related_to_me = [[] for i in xrange(n)]
531
for v0, v1 in rels:
532
c0 = coef[v0[0]] * F(v0[1])
533
c1 = coef[v1[0]] * F(v1[1])
534
535
# Mod out by the following relation:
536
#
537
# c0*free[v0[0]] + c1*free[v1[0]] = 0.
538
#
539
die = None
540
if c0 == ZERO and c1 == ZERO:
541
pass
542
elif c0 == ZERO and c1 != ZERO: # free[v1[0]] --> 0
543
die = free[v1[0]]
544
elif c1 == ZERO and c0 != ZERO:
545
die = free[v0[0]]
546
elif free[v0[0]] == free[v1[0]]:
547
if c0 + c1 != 0:
548
# all xi equal to free[v0[0]] must now equal to zero.
549
die = free[v0[0]]
550
else: # x1 = -c1/c0 * x2.
551
x = free[v0[0]]
552
free[x] = free[v1[0]]
553
coef[x] = -c1/c0
554
for i in related_to_me[x]:
555
free[i] = free[x]
556
coef[i] *= coef[x]
557
related_to_me[free[v1[0]]].append(i)
558
related_to_me[free[v1[0]]].append(x)
559
if die is not None:
560
for i in related_to_me[die]:
561
free[i] = 0
562
coef[i] = ZERO
563
free[die] = 0
564
coef[die] = ZERO
565
566
mod = [(free[i], coef[i]) for i in xrange(len(free))]
567
misc.verbose("finished",tm)
568
return mod
569
570
571
572
#############################################################
573
## The following two sparse_relation_matrix are not
574
## used by any modular symbols code. They're here for
575
## historical reasons, and can probably be safely deleted.
576
#############################################################
577
578
## def sparse_relation_matrix_wt2_g0n(list, field, sign=0):
579
## r"""
580
## Create the sparse relation matrix over $\Q$ for Manin symbols of
581
## weight 2 on $\Gamma_0(N)$, with given sign.
582
583
## INPUT:
584
## list -- sage.modular.modsym.p1list.List
585
## OUTPUT:
586
## A -- a sparse matrix that gives the 2-term and 3-term
587
## relations between Manin symbols.
588
589
## MORE DETAILS:
590
## \begin{enumerate}
591
## \item Create an empty sparse matrix.
592
593
## \item Let $S = [0,-1; 1,0]$, $T = [0,-1; 1,-1]$, $I = [-1,0; 0,1]$.
594
595
## \item Enter the T relations:
596
## $$
597
## x + x T = 0.
598
## $$
599
## Remove x and x*T from reps to consider.
600
601
## \item If sign $\neq 0$, enter the I relations:
602
## $$
603
## x - sign\cdot x\cdot I = 0.
604
## $$
605
606
## \item Enter the S relations in the matrix:
607
## $$
608
## x + x S + x S^2 = 0
609
## $$
610
## by putting 1s at cols corresponding to $x$, $x S$, and $x S^2$.
611
## Remove $x$, $x S$, and $x S^2$ from list of reps to consider.
612
## \end{enumerate}
613
## """
614
## ZERO = field(0)
615
## ONE = field(1)
616
## TWO = field(2)
617
618
## # This will be a dict of the entries of the sparse matrix, where
619
## # the notation is entries[(i,j)]=x.
620
## entries = {}
621
622
## # The current row
623
## row = 0
624
625
## ## The S relations
626
## already_seen= set([])
627
## for i in range(len(list)):
628
## if i in already_seen:
629
## continue
630
## u,v = list[i]
631
## j = list.index(v,-u)
632
## already_seen.add(j)
633
## if i != j:
634
## entries[(row,i)] = ONE
635
## entries[(row,j)] = ONE
636
## else:
637
## entries[(row,i)] = TWO
638
## row += 1
639
## number_of_S_relations = row
640
## misc.verbose("There were %s S relations"%(number_of_S_relations))
641
642
## ## The eta relations:
643
## ## eta((u,v)) = -(-u,v)
644
## if sign != 0:
645
## SIGN = field(sign)
646
## already_seen= set([])
647
## for i in range(len(list)):
648
## if i in already_seen:
649
## continue
650
## u, v = list[i]
651
## j = list.index(-u,v)
652
## already_seen.add(j)
653
## if i != j:
654
## entries[(row,i)] = ONE
655
## entries[(row,j)] = SIGN*ONE
656
## else:
657
## entries[(row,i)] = ONE + SIGN
658
## row += 1
659
## number_of_I_relations = row - number_of_S_relations
660
## misc.verbose("There were %s I relations"%(number_of_I_relations))
661
662
## ## The three-term T relations
663
## already_seen = set([])
664
## for i in range(len(list)):
665
## if i in already_seen:
666
## continue
667
## u,v = list[i]
668
## j1 = list.index(v,-u-v)
669
## already_seen.add(j1)
670
## j2 = list.index(-u-v,u)
671
## already_seen.add(j2)
672
## v = {i:ZERO, j1:ZERO, j2:ZERO}
673
## v[i] = ONE
674
## v[j1] += ONE
675
## v[j2] += ONE
676
## for x in v.keys():
677
## entries[(row,x)] = v[x]
678
## row += 1
679
680
## number_of_T_relations = row - number_of_I_relations - number_of_S_relations
681
## misc.verbose("There were %s T relations"%(number_of_T_relations))
682
683
## M = matrix_space.MatrixSpace(RationalField(), row,
684
## len(list), sparse=True)
685
## if not sparse:
686
## M = M.dense_matrix()
687
688
## return M(entries)
689
690
## def sparse_relation_matrix_wtk_g0n(M, field, sign=0):
691
## r"""
692
## Create the sparse relation matrix over $\Q$ for Manin symbols of
693
## given weight on $\Gamma_0(N)$, with given sign.
694
695
## INPUT:
696
## M -- manin_symbols.ManinSymbolList
697
## field -- base field
698
## weight -- the weight, an integer > 2
699
## sign -- element of [-1,0,1]
700
701
## OUTPUT:
702
## A -- a SparseMatrix that gives the 2-term and 3-term relations
703
## between Manin symbols.
704
705
## MORE DETAILS:
706
## \begin{enumerate}
707
## \item Create an empty sparse matrix.
708
709
## \item Let $S = [0,-1; 1,0]$, $T = [0,-1; 1,-1]$, $I = [-1,0; 0,1]$.
710
711
## \item Enter the $T$ relations:
712
## $$ x + x*T = 0 $$
713
## Remove $x$ and $x T$ from reps to consider.
714
715
## \item If sign $\neq 0$, enter the I relations:
716
## $$
717
## x + sign x I = 0.
718
## $$
719
720
## \item Enter the $S$ relations in the matrix:
721
## $$
722
## x + x S + x S^2 = 0
723
## $$
724
## by putting 1's at cols corresponding to $x$, $x S$, and $x S^2$.
725
## Remove x from list of reps to consider.
726
## \end{enumerate}
727
## """
728
## weight = M.weight()
729
## if not (isinstance(weight, int) and weight > 2):
730
## raise TypeError, "weight must be an int > 2"
731
732
## ZERO = field(0)
733
## ONE = field(1)
734
## TWO = field(2)
735
736
## # This will be a dict of the entries of the sparse matrix, where
737
## # the notation is entries[(i,j)]=x.
738
## entries = {}
739
740
## # The current row
741
## row = 0
742
743
## # The list of Manin symbol triples (i,u,v)
744
## n = len(M)
745
746
## ## The S relations
747
## already_seen= set([])
748
## for i in xrange(n):
749
## if i in already_seen:
750
## continue
751
## j, s = M.apply_S(i)
752
## already_seen.add(j)
753
## if i != j:
754
## entries[(row,i)] = ONE
755
## entries[(row,j)] = field(s)
756
## else:
757
## entries[(row,i)] = ONE+field(s)
758
## row += 1
759
## number_of_S_relations = row
760
## misc.verbose("There were %s S relations"%(number_of_S_relations))
761
## cnt = row
762
## ## The I relations
763
## if sign != 0:
764
## SIGN = field(sign)
765
## already_seen= set([])
766
## for i in xrange(n):
767
## if i in already_seen:
768
## continue
769
## j, s = M.apply_I(i)
770
## already_seen.add(j)
771
## if i != j:
772
## entries[(row,i)] = ONE
773
## entries[(row,j)] = -SIGN*field(s)
774
## else:
775
## entries[(row,i)] = ONE-SIGN*field(s)
776
## row += 1
777
## number_of_I_relations = row - number_of_S_relations
778
## misc.verbose("There were %s I relations"%(number_of_I_relations))
779
## cnt = row
780
781
## ## The T relations
782
## already_seen = set([])
783
## for i in xrange(n):
784
## if i in already_seen:
785
## continue
786
## iT_plus_iTT = M.apply_T(i) + M.apply_TT(i)
787
## v = {i:ONE}
788
## for j, s in iT_plus_iTT:
789
## if v.has_key(j):
790
## v[j] += field(s)
791
## else:
792
## v[j] = field(s)
793
## for j in v.keys():
794
## entries[(row, j)] = v[j]
795
## row += 1
796
797
798