Path: blob/master/sage/modular/modsym/relation_matrix.py
4045 views
"""1Relation matrices for ambient modular symbols spaces23This file contains functions that are used by the various ambient modular4symbols classes to compute presentations of spaces in terms of generators and5relations, using the standard methods based on Manin symbols.6"""78#*****************************************************************************9# Sage: System for Algebra and Geometry Experimentation10#11# Copyright (C) 2005 William Stein <[email protected]>12#13# Distributed under the terms of the GNU General Public License (GPL)14#15# This code is distributed in the hope that it will be useful,16# but WITHOUT ANY WARRANTY; without even the implied warranty of17# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU18# General Public License for more details.19#20# The full text of the GPL is available at:21#22# http://www.gnu.org/licenses/23#*****************************************************************************2425SPARSE=True2627import sage.matrix.matrix_space as matrix_space28import sage.matrix.all29import sage.rings.all as rings30from sage.misc.search import search313233import sage.misc.misc as misc3435import manin_symbols363738# S = [0,-1; 1,0]39# T = [0,-1; 1,-1],40# T^2 = [-1, 1, -1, 0]41# I = [-1,0; 0,1]424344######################################################################45# The following four functions are used to compute the quotient46# modulo the S, I, and T relations more efficiently that the generic47# code in the relation_matrix file:48# modS_relations -- compute the S relations.49# modI_quotient -- compute the I relations.50# T_relation_matrix -- matrix whose echelon form gives51# the quotient by 3-term T relations.52# gens_to_basis_matrix -- compute echelon form of 3-term53# relation matrix, and read off each54# generator in terms of basis.55# These four functions are orchestrated in the function56# compute_presentation57# which is defined below. See the comment at the beginning58# of that function for an overall description of the algorithm.59######################################################################60def modS_relations(syms):61"""62Compute quotient of Manin symbols by the S relations.6364Here S is the 2x2 matrix [0, -1; 1, 0].6566INPUT:676869- ``syms`` - manin_symbols.ManinSymbols707172OUTPUT:737475- ``rels`` - set of pairs of pairs (j, s), where if76mod[i] = (j,s), then x_i = s\*x_j (mod S relations)777879EXAMPLES::8081sage: from sage.modular.modsym.manin_symbols import ManinSymbolList_gamma082sage: from sage.modular.modsym.relation_matrix import modS_relations8384::8586sage: syms = ManinSymbolList_gamma0(2, 4); syms87Manin Symbol List of weight 4 for Gamma0(2)88sage: modS_relations(syms)89set([((3, -1), (4, 1)), ((5, -1), (5, 1)), ((1, 1), (6, 1)), ((0, 1), (7, 1)), ((3, 1), (4, -1)), ((2, 1), (8, 1))])9091::9293sage: syms = ManinSymbolList_gamma0(7, 2); syms94Manin Symbol List of weight 2 for Gamma0(7)95sage: modS_relations(syms)96set([((3, 1), (4, 1)), ((2, 1), (7, 1)), ((5, 1), (6, 1)), ((0, 1), (1, 1))])9798Next we do an example with Gamma1::99100sage: from sage.modular.modsym.manin_symbols import ManinSymbolList_gamma1101sage: syms = ManinSymbolList_gamma1(3,2); syms102Manin Symbol List of weight 2 for Gamma1(3)103sage: modS_relations(syms)104set([((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))])105"""106if not isinstance(syms, manin_symbols.ManinSymbolList):107raise TypeError, "syms must be a ManinSymbolList"108tm = misc.verbose()109# We will fill in this set with the relations x_i + s*x_j = 0,110# where the notation is as in _sparse_2term_quotient.111rels = set()112for i in xrange(len(syms)):113j, s = syms.apply_S(i)114assert j != -1115if i < j:116rels.add( ((i,1),(j,s)) )117else:118rels.add( ((j,s),(i,1)) )119misc.verbose("finished creating S relations",tm)120return rels121122def modI_relations(syms, sign):123"""124Compute quotient of Manin symbols by the I relations.125126INPUT:127128- ``syms`` - ManinSymbols129130- ``sign`` - int (either -1, 0, or 1)131132OUTPUT:133134- ``rels`` - set of pairs of pairs (j, s), where if135mod[i] = (j,s), then x_i = s\*x_j (mod S relations)136137EXAMPLE::138139sage: L = sage.modular.modsym.manin_symbols.ManinSymbolList_gamma1(4, 3)140sage: sage.modular.modsym.relation_matrix.modI_relations(L, 1)141set([((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))])142143.. warning::144145We quotient by the involution eta((u,v)) = (-u,v), which has146the opposite sign as the involution in Merel's Springer LNM1471585 paper! Thus our +1 eigenspace is his -1 eigenspace,148etc. We do this for consistency with MAGMA.149"""150tm = misc.verbose()151# We will fill in this set with the relations x_i - sign*s*x_j = 0,152# where the notation is as in _sparse_2term_quotient.153rels = set()154for i in xrange(len(syms)):155j, s = syms.apply_I(i)156assert j != -1157rels.add( ((i,1),(j,-sign*s)) )158misc.verbose("finished creating I relations",tm)159return rels160161def T_relation_matrix_wtk_g0(syms, mod, field, sparse):162r"""163Compute a matrix whose echelon form gives the quotient by 3-term T164relations. Despite the name, this is used for all modular symbols spaces165(including those with character and those for `\Gamma_1` and `\Gamma_H`166groups), not just `\Gamma_0`.167168INPUT:169170- ``syms`` - ManinSymbols171172- ``mod`` - list that gives quotient modulo some two-term relations, i.e.,173the S relations, and if sign is nonzero, the I relations.174175- ``field`` - base_ring176177- ``sparse`` - (True or False) whether to use sparse rather than dense178linear algebra179180OUTPUT: A sparse matrix whose rows correspond to the reduction of181the T relations modulo the S and I relations.182183EXAMPLE::184185sage: from sage.modular.modsym.relation_matrix import *186sage: L = sage.modular.modsym.manin_symbols.ManinSymbolList_gamma_h(GammaH(36, [17,19]), 2)187sage: modS = sparse_2term_quotient(modS_relations(L), 216, QQ)188sage: T_relation_matrix_wtk_g0(L, modS, QQ, False)18972 x 216 dense matrix over Rational Field190sage: T_relation_matrix_wtk_g0(L, modS, GF(17), True)19172 x 216 sparse matrix over Finite Field of size 17192"""193tm = misc.verbose()194row = 0195entries = {}196already_seen = set()197w = syms.weight()198for i in xrange(len(syms)):199if i in already_seen:200continue201iT_plus_iTT = syms.apply_T(i) + syms.apply_TT(i)202j0, s0 = mod[i]203v = {j0:s0}204for j, s in iT_plus_iTT:205if w==2: already_seen.add(j)206j0, s0 = mod[j]207s0 = s*s0208if v.has_key(j0):209v[j0] += s0210else:211v[j0] = s0212for j0 in v.keys():213entries[(row, j0)] = v[j0]214row += 1215216MAT = matrix_space.MatrixSpace(field, row,217len(syms), sparse=True)218R = MAT(entries)219if not sparse:220R = R.dense_matrix()221misc.verbose("finished (number of rows=%s)"%row, tm)222return R223224def gens_to_basis_matrix(syms, relation_matrix, mod, field, sparse):225"""226Compute echelon form of 3-term relation matrix, and read off each227generator in terms of basis.228229INPUT:230231- ``syms`` - a ManinSymbols object232233- ``relation_matrix`` - as output by234``__compute_T_relation_matrix(self, mod)``235236- ``mod`` - quotient of modular symbols modulo the2372-term S (and possibly I) relations238239- ``field`` - base field240241- ``sparse`` - (bool): whether or not matrix should be242sparse243244OUTPUT:245246- ``matrix`` - a matrix whose ith row expresses the247Manin symbol generators in terms of a basis of Manin symbols248(modulo the S, (possibly I,) and T rels) Note that the entries of249the matrix need not be integers.250251- ``list`` - integers i, such that the Manin symbols `x_i` are a basis.252253EXAMPLE::254255sage: from sage.modular.modsym.relation_matrix import *256sage: L = sage.modular.modsym.manin_symbols.ManinSymbolList_gamma1(4, 3)257sage: modS = sparse_2term_quotient(modS_relations(L), 24, GF(3))258sage: gens_to_basis_matrix(L, T_relation_matrix_wtk_g0(L, modS, GF(3), 24), modS, GF(3), True)259(24 x 2 sparse matrix over Finite Field of size 3, [13, 23])260"""261if not sage.matrix.all.is_Matrix(relation_matrix):262raise TypeError, "relation_matrix must be a matrix"263if not isinstance(mod, list):264raise TypeError, "mod must be a list"265266misc.verbose(str(relation_matrix.parent()))267268try:269h = relation_matrix.height()270except AttributeError:271h = 9999999272tm = misc.verbose("putting relation matrix in echelon form (height = %s)"%h)273if h < 10:274A = relation_matrix.echelon_form(algorithm='multimodular', height_guess=1)275else:276A = relation_matrix.echelon_form()277A.set_immutable()278tm = misc.verbose('finished echelon', tm)279280tm = misc.verbose("Now creating gens --> basis mapping")281282basis_set = set(A.nonpivots())283pivots = A.pivots()284285basis_mod2 = set([j for j,c in mod if c != 0])286287basis_set = basis_set.intersection(basis_mod2)288basis = list(basis_set)289basis.sort()290291ONE = field(1)292293misc.verbose("done doing setup",tm)294295296tm = misc.verbose("now forming quotient matrix")297M = matrix_space.MatrixSpace(field, len(syms), len(basis), sparse=sparse)298299B = M(0)300cols_index = dict([(basis[i], i) for i in range(len(basis))])301302for i in basis_mod2:303t, l = search(basis, i)304if t:305B[i,l] = ONE306else:307_, r = search(pivots, i) # so pivots[r] = i308# Set row i to -(row r of A), but where we only take309# the non-pivot columns of A:310B._set_row_to_negative_of_row_of_A_using_subset_of_columns(i, A, r, basis, cols_index)311312misc.verbose("done making quotient matrix",tm)313314# The following is very fast (over Q at least).315tm = misc.verbose('now filling in the rest of the matrix')316k = 0317for i in range(len(mod)):318j, s = mod[i]319if j != i and s != 0: # ignored in the above matrix320k += 1321B.set_row_to_multiple_of_row(i, j, s)322misc.verbose("set %s rows"%k)323tm = misc.verbose("time to fill in rest of matrix", tm)324325return B, basis326327def compute_presentation(syms, sign, field, sparse=None):328r"""329Compute the presentation for self, as a quotient of Manin symbols330modulo relations.331332INPUT:333334- ``syms`` - manin_symbols.ManinSymbols335336- ``sign`` - integer (-1, 0, 1)337338- ``field`` - a field339340341OUTPUT:342343- sparse matrix whose rows give each generator344in terms of a basis for the quotient345346- list of integers that give the basis for the347quotient348349- mod: list where mod[i]=(j,s) means that x_i350= s\*x_j modulo the 2-term S (and possibly I) relations.351352353ALGORITHM:354355#. Let `S = [0,-1; 1,0], T = [0,-1; 1,-1]`, and356`I = [-1,0; 0,1]`.357358#. Let `x_0,\ldots, x_{n-1}` by a list of all359non-equivalent Manin symbols.360361#. Form quotient by 2-term S and (possibly) I relations.362363#. Create a sparse matrix `A` with `m` columns,364whose rows encode the relations365366.. math::367368[x_i] + [x_i T] + [x_i T^2] = 0.369370371There are about n such rows. The number of nonzero entries per row372is at most 3\*(k-1). Note that we must include rows for *all* i,373since even if `[x_i] = [x_j]`, it need not be the case374that `[x_i T] = [x_j T]`, since `S` and375`T` do not commute. However, in many cases we have an a376priori formula for the dimension of the quotient by all these377relations, so we can omit many relations and just check that there378are enough at the end--if there aren't, we add in more.379380#. Compute the reduced row echelon form of `A` using sparse381Gaussian elimination.382383#. Use what we've done above to read off a sparse matrix R that384uniquely expresses each of the n Manin symbols in terms of a subset385of Manin symbols, modulo the relations. This subset of Manin386symbols is a basis for the quotient by the relations.387388389EXAMPLE::390391sage: L = sage.modular.modsym.manin_symbols.ManinSymbolList_gamma0(8,2)392sage: sage.modular.modsym.relation_matrix.compute_presentation(L, 1, GF(9,'a'), True)393(394[2 0 0]395[1 0 0]396[0 0 0]397[0 2 0]398[0 0 0]399[0 0 2]400[0 0 0]401[0 2 0]402[0 0 0]403[0 1 0]404[0 1 0]405[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)]406)407"""408if sparse is None:409if syms.weight() >= 6:410sparse = False411else:412sparse = True413R, mod = relation_matrix_wtk_g0(syms, sign, field, sparse)414B, basis = gens_to_basis_matrix(syms, R, mod, field, sparse)415return B, basis, mod416417def relation_matrix_wtk_g0(syms, sign, field, sparse):418r"""419Compute the matrix of relations. Despite the name, this is used for all420spaces (not just for Gamma0). For a description of the algorithm, see the421docstring for ``compute_presentation``.422423INPUT:424425- ``syms``: sage.modular.modsym.manin_symbols.ManinSymbolList object426427- ``sign``: integer (0, 1 or -1)428429- ``field``: the base field (non-field base rings not supported at present)430431- ``sparse``: (True or False) whether to use sparse arithmetic.432433Note that ManinSymbolList objects already have a specific weight, so there434is no need for an extra ``weight`` parameter.435436OUTPUT: a pair (R, mod) where437438- R is a matrix as output by ``T_relation_matrix_wtk_g0``439440- mod is a set of 2-term relations as output by ``sparse_2term_quotient``441442EXAMPLE::443444sage: L = sage.modular.modsym.manin_symbols.ManinSymbolList_gamma0(8,2)445sage: A = sage.modular.modsym.relation_matrix.relation_matrix_wtk_g0(L, 0, GF(2), True); A446(447[0 0 0 0 0 0 0 0 1 0 0 0]448[0 0 0 0 0 0 0 0 1 1 1 0]449[0 0 0 0 0 0 1 0 0 1 1 0]450[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)]451)452sage: A[0].is_sparse()453True454"""455rels = modS_relations(syms)456if sign != 0:457# Let rels = rels union I relations.458rels.update(modI_relations(syms,sign))459460if syms._apply_S_only_0pm1() and rings.is_RationalField(field):461import relation_matrix_pyx462mod = relation_matrix_pyx.sparse_2term_quotient_only_pm1(rels, len(syms))463else:464mod = sparse_2term_quotient(rels, len(syms), field)465466R = T_relation_matrix_wtk_g0(syms, mod, field, sparse)467return R, mod468469def sparse_2term_quotient(rels, n, F):470r"""471Performs Sparse Gauss elimination on a matrix all of whose columns472have at most 2 nonzero entries. We use an obvious algorithm, which473runs fast enough. (Typically making the list of relations takes474more time than computing this quotient.) This algorithm is more475subtle than just "identify symbols in pairs", since complicated476relations can cause generators to surprisingly equal 0.477478INPUT:479480481- ``rels`` - set of pairs ((i,s), (j,t)). The pair482represents the relation s\*x_i + t\*x_j = 0, where the i, j must483be Python int's.484485- ``n`` - int, the x_i are x_0, ..., x_n-1.486487- ``F`` - base field488489490OUTPUT:491492493- ``mod`` - list such that mod[i] = (j,s), which means494that x_i is equivalent to s\*x_j, where the x_j are a basis for495the quotient.496497498EXAMPLE: We quotient out by the relations499500.. math::5015023*x0 - x1 = 0,\qquad x1 + x3 = 0,\qquad x2 + x3 = 0,\qquad x4 - x5 = 0503504505to get506507::508509sage: 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))]510sage: rels = set(v)511sage: n = 6512sage: from sage.modular.modsym.relation_matrix import sparse_2term_quotient513sage: sparse_2term_quotient(rels, n, QQ)514[(3, -1/3), (3, -1), (3, -1), (3, 1), (5, 1), (5, 1)]515"""516if not isinstance(rels, set):517raise TypeError, "rels must be a set"518n = int(n)519if not isinstance(F, rings.Ring):520raise TypeError, "F must be a ring."521522tm = misc.verbose("Starting sparse 2-term quotient...")523free = range(n)524ONE = F(1)525ZERO = F(0)526coef = [ONE for i in xrange(n)]527related_to_me = [[] for i in xrange(n)]528for v0, v1 in rels:529c0 = coef[v0[0]] * F(v0[1])530c1 = coef[v1[0]] * F(v1[1])531532# Mod out by the following relation:533#534# c0*free[v0[0]] + c1*free[v1[0]] = 0.535#536die = None537if c0 == ZERO and c1 == ZERO:538pass539elif c0 == ZERO and c1 != ZERO: # free[v1[0]] --> 0540die = free[v1[0]]541elif c1 == ZERO and c0 != ZERO:542die = free[v0[0]]543elif free[v0[0]] == free[v1[0]]:544if c0 + c1 != 0:545# all xi equal to free[v0[0]] must now equal to zero.546die = free[v0[0]]547else: # x1 = -c1/c0 * x2.548x = free[v0[0]]549free[x] = free[v1[0]]550coef[x] = -c1/c0551for i in related_to_me[x]:552free[i] = free[x]553coef[i] *= coef[x]554related_to_me[free[v1[0]]].append(i)555related_to_me[free[v1[0]]].append(x)556if die is not None:557for i in related_to_me[die]:558free[i] = 0559coef[i] = ZERO560free[die] = 0561coef[die] = ZERO562563mod = [(free[i], coef[i]) for i in xrange(len(free))]564misc.verbose("finished",tm)565return mod566567568569#############################################################570## The following two sparse_relation_matrix are not571## used by any modular symbols code. They're here for572## historical reasons, and can probably be safely deleted.573#############################################################574575## def sparse_relation_matrix_wt2_g0n(list, field, sign=0):576## r"""577## Create the sparse relation matrix over $\Q$ for Manin symbols of578## weight 2 on $\Gamma_0(N)$, with given sign.579580## INPUT:581## list -- sage.modular.modsym.p1list.List582## OUTPUT:583## A -- a sparse matrix that gives the 2-term and 3-term584## relations between Manin symbols.585586## MORE DETAILS:587## \begin{enumerate}588## \item Create an empty sparse matrix.589590## \item Let $S = [0,-1; 1,0]$, $T = [0,-1; 1,-1]$, $I = [-1,0; 0,1]$.591592## \item Enter the T relations:593## $$594## x + x T = 0.595## $$596## Remove x and x*T from reps to consider.597598## \item If sign $\neq 0$, enter the I relations:599## $$600## x - sign\cdot x\cdot I = 0.601## $$602603## \item Enter the S relations in the matrix:604## $$605## x + x S + x S^2 = 0606## $$607## by putting 1s at cols corresponding to $x$, $x S$, and $x S^2$.608## Remove $x$, $x S$, and $x S^2$ from list of reps to consider.609## \end{enumerate}610## """611## ZERO = field(0)612## ONE = field(1)613## TWO = field(2)614615## # This will be a dict of the entries of the sparse matrix, where616## # the notation is entries[(i,j)]=x.617## entries = {}618619## # The current row620## row = 0621622## ## The S relations623## already_seen= set([])624## for i in range(len(list)):625## if i in already_seen:626## continue627## u,v = list[i]628## j = list.index(v,-u)629## already_seen.add(j)630## if i != j:631## entries[(row,i)] = ONE632## entries[(row,j)] = ONE633## else:634## entries[(row,i)] = TWO635## row += 1636## number_of_S_relations = row637## misc.verbose("There were %s S relations"%(number_of_S_relations))638639## ## The eta relations:640## ## eta((u,v)) = -(-u,v)641## if sign != 0:642## SIGN = field(sign)643## already_seen= set([])644## for i in range(len(list)):645## if i in already_seen:646## continue647## u, v = list[i]648## j = list.index(-u,v)649## already_seen.add(j)650## if i != j:651## entries[(row,i)] = ONE652## entries[(row,j)] = SIGN*ONE653## else:654## entries[(row,i)] = ONE + SIGN655## row += 1656## number_of_I_relations = row - number_of_S_relations657## misc.verbose("There were %s I relations"%(number_of_I_relations))658659## ## The three-term T relations660## already_seen = set([])661## for i in range(len(list)):662## if i in already_seen:663## continue664## u,v = list[i]665## j1 = list.index(v,-u-v)666## already_seen.add(j1)667## j2 = list.index(-u-v,u)668## already_seen.add(j2)669## v = {i:ZERO, j1:ZERO, j2:ZERO}670## v[i] = ONE671## v[j1] += ONE672## v[j2] += ONE673## for x in v.keys():674## entries[(row,x)] = v[x]675## row += 1676677## number_of_T_relations = row - number_of_I_relations - number_of_S_relations678## misc.verbose("There were %s T relations"%(number_of_T_relations))679680## M = matrix_space.MatrixSpace(RationalField(), row,681## len(list), sparse=True)682## if not sparse:683## M = M.dense_matrix()684685## return M(entries)686687## def sparse_relation_matrix_wtk_g0n(M, field, sign=0):688## r"""689## Create the sparse relation matrix over $\Q$ for Manin symbols of690## given weight on $\Gamma_0(N)$, with given sign.691692## INPUT:693## M -- manin_symbols.ManinSymbolList694## field -- base field695## weight -- the weight, an integer > 2696## sign -- element of [-1,0,1]697698## OUTPUT:699## A -- a SparseMatrix that gives the 2-term and 3-term relations700## between Manin symbols.701702## MORE DETAILS:703## \begin{enumerate}704## \item Create an empty sparse matrix.705706## \item Let $S = [0,-1; 1,0]$, $T = [0,-1; 1,-1]$, $I = [-1,0; 0,1]$.707708## \item Enter the $T$ relations:709## $$ x + x*T = 0 $$710## Remove $x$ and $x T$ from reps to consider.711712## \item If sign $\neq 0$, enter the I relations:713## $$714## x + sign x I = 0.715## $$716717## \item Enter the $S$ relations in the matrix:718## $$719## x + x S + x S^2 = 0720## $$721## by putting 1's at cols corresponding to $x$, $x S$, and $x S^2$.722## Remove x from list of reps to consider.723## \end{enumerate}724## """725## weight = M.weight()726## if not (isinstance(weight, int) and weight > 2):727## raise TypeError, "weight must be an int > 2"728729## ZERO = field(0)730## ONE = field(1)731## TWO = field(2)732733## # This will be a dict of the entries of the sparse matrix, where734## # the notation is entries[(i,j)]=x.735## entries = {}736737## # The current row738## row = 0739740## # The list of Manin symbol triples (i,u,v)741## n = len(M)742743## ## The S relations744## already_seen= set([])745## for i in xrange(n):746## if i in already_seen:747## continue748## j, s = M.apply_S(i)749## already_seen.add(j)750## if i != j:751## entries[(row,i)] = ONE752## entries[(row,j)] = field(s)753## else:754## entries[(row,i)] = ONE+field(s)755## row += 1756## number_of_S_relations = row757## misc.verbose("There were %s S relations"%(number_of_S_relations))758## cnt = row759## ## The I relations760## if sign != 0:761## SIGN = field(sign)762## already_seen= set([])763## for i in xrange(n):764## if i in already_seen:765## continue766## j, s = M.apply_I(i)767## already_seen.add(j)768## if i != j:769## entries[(row,i)] = ONE770## entries[(row,j)] = -SIGN*field(s)771## else:772## entries[(row,i)] = ONE-SIGN*field(s)773## row += 1774## number_of_I_relations = row - number_of_S_relations775## misc.verbose("There were %s I relations"%(number_of_I_relations))776## cnt = row777778## ## The T relations779## already_seen = set([])780## for i in xrange(n):781## if i in already_seen:782## continue783## iT_plus_iTT = M.apply_T(i) + M.apply_TT(i)784## v = {i:ONE}785## for j, s in iT_plus_iTT:786## if v.has_key(j):787## v[j] += field(s)788## else:789## v[j] = field(s)790## for j in v.keys():791## entries[(row, j)] = v[j]792## row += 1793794795796