Path: blob/master/sage/modular/modsym/relation_matrix_pyx.pyx
4057 views
"""1Optimized Cython code for computing relation matrices in certain cases.2"""34#############################################################################5# Copyright (C) 2010 William Stein <[email protected]>6# Distributed under the terms of the GNU General Public License (GPL) v2+.7# The full text of the GPL is available at:8# http://www.gnu.org/licenses/9#############################################################################1011import sage.misc.misc as misc12from sage.rings.rational cimport Rational1314def sparse_2term_quotient_only_pm1(rels, n):15r"""16Performs Sparse Gauss elimination on a matrix all of whose columns17have at most 2 nonzero entries with relations all 1 or -1.1819This algorithm is more subtle than just "identify symbols in pairs",20since complicated relations can cause generators to equal 0.2122NOTE: Note the condition on the s,t coefficients in the relations23being 1 or -1 for this optimized function. There is a more24general function in relation_matrix.py, which is much, much25slower.2627INPUT:2829- ``rels`` - set of pairs ((i,s), (j,t)). The pair represents30the relation s*x_i + t*x_j = 0, where the i, j must be31Python int's, and the s,t must all be 1 or -1.3233- ``n`` - int, the x_i are x_0, ..., x_n-1.3435OUTPUT:3637- ``mod`` - list such that mod[i] = (j,s), which means38that x_i is equivalent to s*x_j, where the x_j are a basis for39the quotient.4041EXAMPLES::4243sage: v = [((0,1), (1,-1)), ((1,1), (3,1)), ((2,1),(3,1)), ((4,1),(5,-1))]44sage: rels = set(v)45sage: n = 646sage: from sage.modular.modsym.relation_matrix_pyx import sparse_2term_quotient_only_pm147sage: sparse_2term_quotient_only_pm1(rels, n)48[(3, -1), (3, -1), (3, -1), (3, 1), (5, 1), (5, 1)]49"""50if not isinstance(rels, set):51raise TypeError, "rels must be a set"5253n = int(n)5455tm = misc.verbose("Starting optimized integer sparse 2-term quotient...")5657cdef int c0, c1, i, die58free = range(n)59coef = [1]*n60related_to_me = [[] for i in range(n)]6162for v0, v1 in rels:63c0 = coef[v0[0]] * v0[1]64c1 = coef[v1[0]] * v1[1]6566# Mod out by the following relation:67#68# c0*free[v0[0]] + c1*free[v1[0]] = 0.69#70die = -171if c0 == 0 and c1 == 0:72pass73elif c0 == 0 and c1 != 0: # free[v1[0]] --> 074die = free[v1[0]]75elif c1 == 0 and c0 != 0:76die = free[v0[0]]77elif free[v0[0]] == free[v1[0]]:78if c0 + c1 != 0:79# all xi equal to free[v0[0]] must now equal to zero.80die = free[v0[0]]81else: # x1 = -c1/c0 * x2.82x = free[v0[0]]83free[x] = free[v1[0]]84if c0 != 1 and c0 != -1:85raise ValueError, "coefficients must all be -1 or 1."86coef[x] = -c1/c087for i in related_to_me[x]:88free[i] = free[x]89coef[i] *= coef[x]90related_to_me[free[v1[0]]].append(i)91related_to_me[free[v1[0]]].append(x)92if die != -1:93for i in related_to_me[die]:94free[i] = 095coef[i] = 096free[die] = 097coef[die] = 09899# Special casing the rationals leads to a huge speedup,100# actually. (All the code above is slower than just this line101# without this special case.)102mod = [(free[i], Rational(coef[i])) for i in range(len(free))]103104misc.verbose("finished",tm)105return mod106107108109