Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
sagemath
GitHub Repository: sagemath/sagelib
Path: blob/master/sage/modular/modsym/relation_matrix_pyx.pyx
4057 views
1
"""
2
Optimized Cython code for computing relation matrices in certain cases.
3
"""
4
5
#############################################################################
6
# Copyright (C) 2010 William Stein <[email protected]>
7
# Distributed under the terms of the GNU General Public License (GPL) v2+.
8
# The full text of the GPL is available at:
9
# http://www.gnu.org/licenses/
10
#############################################################################
11
12
import sage.misc.misc as misc
13
from sage.rings.rational cimport Rational
14
15
def sparse_2term_quotient_only_pm1(rels, n):
16
r"""
17
Performs Sparse Gauss elimination on a matrix all of whose columns
18
have at most 2 nonzero entries with relations all 1 or -1.
19
20
This algorithm is more subtle than just "identify symbols in pairs",
21
since complicated relations can cause generators to equal 0.
22
23
NOTE: Note the condition on the s,t coefficients in the relations
24
being 1 or -1 for this optimized function. There is a more
25
general function in relation_matrix.py, which is much, much
26
slower.
27
28
INPUT:
29
30
- ``rels`` - set of pairs ((i,s), (j,t)). The pair represents
31
the relation s*x_i + t*x_j = 0, where the i, j must be
32
Python int's, and the s,t must all be 1 or -1.
33
34
- ``n`` - int, the x_i are x_0, ..., x_n-1.
35
36
OUTPUT:
37
38
- ``mod`` - list such that mod[i] = (j,s), which means
39
that x_i is equivalent to s*x_j, where the x_j are a basis for
40
the quotient.
41
42
EXAMPLES::
43
44
sage: v = [((0,1), (1,-1)), ((1,1), (3,1)), ((2,1),(3,1)), ((4,1),(5,-1))]
45
sage: rels = set(v)
46
sage: n = 6
47
sage: from sage.modular.modsym.relation_matrix_pyx import sparse_2term_quotient_only_pm1
48
sage: sparse_2term_quotient_only_pm1(rels, n)
49
[(3, -1), (3, -1), (3, -1), (3, 1), (5, 1), (5, 1)]
50
"""
51
if not isinstance(rels, set):
52
raise TypeError, "rels must be a set"
53
54
n = int(n)
55
56
tm = misc.verbose("Starting optimized integer sparse 2-term quotient...")
57
58
cdef int c0, c1, i, die
59
free = range(n)
60
coef = [1]*n
61
related_to_me = [[] for i in range(n)]
62
63
for v0, v1 in rels:
64
c0 = coef[v0[0]] * v0[1]
65
c1 = coef[v1[0]] * v1[1]
66
67
# Mod out by the following relation:
68
#
69
# c0*free[v0[0]] + c1*free[v1[0]] = 0.
70
#
71
die = -1
72
if c0 == 0 and c1 == 0:
73
pass
74
elif c0 == 0 and c1 != 0: # free[v1[0]] --> 0
75
die = free[v1[0]]
76
elif c1 == 0 and c0 != 0:
77
die = free[v0[0]]
78
elif free[v0[0]] == free[v1[0]]:
79
if c0 + c1 != 0:
80
# all xi equal to free[v0[0]] must now equal to zero.
81
die = free[v0[0]]
82
else: # x1 = -c1/c0 * x2.
83
x = free[v0[0]]
84
free[x] = free[v1[0]]
85
if c0 != 1 and c0 != -1:
86
raise ValueError, "coefficients must all be -1 or 1."
87
coef[x] = -c1/c0
88
for i in related_to_me[x]:
89
free[i] = free[x]
90
coef[i] *= coef[x]
91
related_to_me[free[v1[0]]].append(i)
92
related_to_me[free[v1[0]]].append(x)
93
if die != -1:
94
for i in related_to_me[die]:
95
free[i] = 0
96
coef[i] = 0
97
free[die] = 0
98
coef[die] = 0
99
100
# Special casing the rationals leads to a huge speedup,
101
# actually. (All the code above is slower than just this line
102
# without this special case.)
103
mod = [(free[i], Rational(coef[i])) for i in range(len(free))]
104
105
misc.verbose("finished",tm)
106
return mod
107
108
109