Path: blob/master/src/sage/modular/modsym/relation_matrix.py
8820 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 search31from sage.rings.rational_field import is_RationalField323334import sage.misc.misc as misc3536import manin_symbols373839# S = [0,-1; 1,0]40# T = [0,-1; 1,-1],41# T^2 = [-1, 1, -1, 0]42# I = [-1,0; 0,1]434445######################################################################46# The following four functions are used to compute the quotient47# modulo the S, I, and T relations more efficiently that the generic48# code in the relation_matrix file:49# modS_relations -- compute the S relations.50# modI_quotient -- compute the I relations.51# T_relation_matrix -- matrix whose echelon form gives52# the quotient by 3-term T relations.53# gens_to_basis_matrix -- compute echelon form of 3-term54# relation matrix, and read off each55# generator in terms of basis.56# These four functions are orchestrated in the function57# compute_presentation58# which is defined below. See the comment at the beginning59# of that function for an overall description of the algorithm.60######################################################################61def modS_relations(syms):62"""63Compute quotient of Manin symbols by the S relations.6465Here S is the 2x2 matrix [0, -1; 1, 0].6667INPUT:686970- ``syms`` - manin_symbols.ManinSymbols717273OUTPUT:747576- ``rels`` - set of pairs of pairs (j, s), where if77mod[i] = (j,s), then x_i = s\*x_j (mod S relations)787980EXAMPLES::8182sage: from sage.modular.modsym.manin_symbols import ManinSymbolList_gamma083sage: from sage.modular.modsym.relation_matrix import modS_relations8485::8687sage: syms = ManinSymbolList_gamma0(2, 4); syms88Manin Symbol List of weight 4 for Gamma0(2)89sage: modS_relations(syms)90set([((3, -1), (4, 1)), ((5, -1), (5, 1)), ((1, 1), (6, 1)), ((0, 1), (7, 1)), ((3, 1), (4, -1)), ((2, 1), (8, 1))])9192::9394sage: syms = ManinSymbolList_gamma0(7, 2); syms95Manin Symbol List of weight 2 for Gamma0(7)96sage: modS_relations(syms)97set([((3, 1), (4, 1)), ((2, 1), (7, 1)), ((5, 1), (6, 1)), ((0, 1), (1, 1))])9899Next we do an example with Gamma1::100101sage: from sage.modular.modsym.manin_symbols import ManinSymbolList_gamma1102sage: syms = ManinSymbolList_gamma1(3,2); syms103Manin Symbol List of weight 2 for Gamma1(3)104sage: modS_relations(syms)105set([((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))])106"""107if not isinstance(syms, manin_symbols.ManinSymbolList):108raise TypeError, "syms must be a ManinSymbolList"109tm = misc.verbose()110# We will fill in this set with the relations x_i + s*x_j = 0,111# where the notation is as in _sparse_2term_quotient.112rels = set()113for i in xrange(len(syms)):114j, s = syms.apply_S(i)115assert j != -1116if i < j:117rels.add( ((i,1),(j,s)) )118else:119rels.add( ((j,s),(i,1)) )120misc.verbose("finished creating S relations",tm)121return rels122123def modI_relations(syms, sign):124"""125Compute quotient of Manin symbols by the I relations.126127INPUT:128129- ``syms`` - ManinSymbols130131- ``sign`` - int (either -1, 0, or 1)132133OUTPUT:134135- ``rels`` - set of pairs of pairs (j, s), where if136mod[i] = (j,s), then x_i = s\*x_j (mod S relations)137138EXAMPLE::139140sage: L = sage.modular.modsym.manin_symbols.ManinSymbolList_gamma1(4, 3)141sage: sage.modular.modsym.relation_matrix.modI_relations(L, 1)142set([((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))])143144.. warning::145146We quotient by the involution eta((u,v)) = (-u,v), which has147the opposite sign as the involution in Merel's Springer LNM1481585 paper! Thus our +1 eigenspace is his -1 eigenspace,149etc. We do this for consistency with MAGMA.150"""151tm = misc.verbose()152# We will fill in this set with the relations x_i - sign*s*x_j = 0,153# where the notation is as in _sparse_2term_quotient.154rels = set()155for i in xrange(len(syms)):156j, s = syms.apply_I(i)157assert j != -1158rels.add( ((i,1),(j,-sign*s)) )159misc.verbose("finished creating I relations",tm)160return rels161162def T_relation_matrix_wtk_g0(syms, mod, field, sparse):163r"""164Compute a matrix whose echelon form gives the quotient by 3-term T165relations. Despite the name, this is used for all modular symbols spaces166(including those with character and those for `\Gamma_1` and `\Gamma_H`167groups), not just `\Gamma_0`.168169INPUT:170171- ``syms`` - ManinSymbols172173- ``mod`` - list that gives quotient modulo some two-term relations, i.e.,174the S relations, and if sign is nonzero, the I relations.175176- ``field`` - base_ring177178- ``sparse`` - (True or False) whether to use sparse rather than dense179linear algebra180181OUTPUT: A sparse matrix whose rows correspond to the reduction of182the T relations modulo the S and I relations.183184EXAMPLE::185186sage: from sage.modular.modsym.relation_matrix import *187sage: L = sage.modular.modsym.manin_symbols.ManinSymbolList_gamma_h(GammaH(36, [17,19]), 2)188sage: modS = sparse_2term_quotient(modS_relations(L), 216, QQ)189sage: T_relation_matrix_wtk_g0(L, modS, QQ, False)19072 x 216 dense matrix over Rational Field191sage: T_relation_matrix_wtk_g0(L, modS, GF(17), True)19272 x 216 sparse matrix over Finite Field of size 17193"""194tm = misc.verbose()195row = 0196entries = {}197already_seen = set()198w = syms.weight()199for i in xrange(len(syms)):200if i in already_seen:201continue202iT_plus_iTT = syms.apply_T(i) + syms.apply_TT(i)203j0, s0 = mod[i]204v = {j0:s0}205for j, s in iT_plus_iTT:206if w==2: already_seen.add(j)207j0, s0 = mod[j]208s0 = s*s0209if v.has_key(j0):210v[j0] += s0211else:212v[j0] = s0213for j0 in v.keys():214entries[(row, j0)] = v[j0]215row += 1216217MAT = matrix_space.MatrixSpace(field, row,218len(syms), sparse=True)219R = MAT(entries)220if not sparse:221R = R.dense_matrix()222misc.verbose("finished (number of rows=%s)"%row, tm)223return R224225def gens_to_basis_matrix(syms, relation_matrix, mod, field, sparse):226"""227Compute echelon form of 3-term relation matrix, and read off each228generator in terms of basis.229230INPUT:231232- ``syms`` - a ManinSymbols object233234- ``relation_matrix`` - as output by235``__compute_T_relation_matrix(self, mod)``236237- ``mod`` - quotient of modular symbols modulo the2382-term S (and possibly I) relations239240- ``field`` - base field241242- ``sparse`` - (bool): whether or not matrix should be243sparse244245OUTPUT:246247- ``matrix`` - a matrix whose ith row expresses the248Manin symbol generators in terms of a basis of Manin symbols249(modulo the S, (possibly I,) and T rels) Note that the entries of250the matrix need not be integers.251252- ``list`` - integers i, such that the Manin symbols `x_i` are a basis.253254EXAMPLE::255256sage: from sage.modular.modsym.relation_matrix import *257sage: L = sage.modular.modsym.manin_symbols.ManinSymbolList_gamma1(4, 3)258sage: modS = sparse_2term_quotient(modS_relations(L), 24, GF(3))259sage: gens_to_basis_matrix(L, T_relation_matrix_wtk_g0(L, modS, GF(3), 24), modS, GF(3), True)260(24 x 2 sparse matrix over Finite Field of size 3, [13, 23])261"""262from sage.matrix.matrix import is_Matrix263if not is_Matrix(relation_matrix):264raise TypeError("relation_matrix must be a matrix")265if not isinstance(mod, list):266raise TypeError("mod must be a list")267268misc.verbose(str(relation_matrix.parent()))269270try:271h = relation_matrix.height()272except AttributeError:273h = 9999999274tm = misc.verbose("putting relation matrix in echelon form (height = %s)"%h)275if h < 10:276A = relation_matrix.echelon_form(algorithm='multimodular', height_guess=1)277else:278A = relation_matrix.echelon_form()279A.set_immutable()280tm = misc.verbose('finished echelon', tm)281282tm = misc.verbose("Now creating gens --> basis mapping")283284basis_set = set(A.nonpivots())285pivots = A.pivots()286287basis_mod2 = set([j for j,c in mod if c != 0])288289basis_set = basis_set.intersection(basis_mod2)290basis = list(basis_set)291basis.sort()292293ONE = field(1)294295misc.verbose("done doing setup",tm)296297298tm = misc.verbose("now forming quotient matrix")299M = matrix_space.MatrixSpace(field, len(syms), len(basis), sparse=sparse)300301B = M(0)302cols_index = dict([(basis[i], i) for i in range(len(basis))])303304for i in basis_mod2:305t, l = search(basis, i)306if t:307B[i,l] = ONE308else:309_, r = search(pivots, i) # so pivots[r] = i310# Set row i to -(row r of A), but where we only take311# the non-pivot columns of A:312B._set_row_to_negative_of_row_of_A_using_subset_of_columns(i, A, r, basis, cols_index)313314misc.verbose("done making quotient matrix",tm)315316# The following is very fast (over Q at least).317tm = misc.verbose('now filling in the rest of the matrix')318k = 0319for i in range(len(mod)):320j, s = mod[i]321if j != i and s != 0: # ignored in the above matrix322k += 1323B.set_row_to_multiple_of_row(i, j, s)324misc.verbose("set %s rows"%k)325tm = misc.verbose("time to fill in rest of matrix", tm)326327return B, basis328329def compute_presentation(syms, sign, field, sparse=None):330r"""331Compute the presentation for self, as a quotient of Manin symbols332modulo relations.333334INPUT:335336- ``syms`` - manin_symbols.ManinSymbols337338- ``sign`` - integer (-1, 0, 1)339340- ``field`` - a field341342343OUTPUT:344345- sparse matrix whose rows give each generator346in terms of a basis for the quotient347348- list of integers that give the basis for the349quotient350351- mod: list where mod[i]=(j,s) means that x_i352= s\*x_j modulo the 2-term S (and possibly I) relations.353354355ALGORITHM:356357#. Let `S = [0,-1; 1,0], T = [0,-1; 1,-1]`, and358`I = [-1,0; 0,1]`.359360#. Let `x_0,\ldots, x_{n-1}` by a list of all361non-equivalent Manin symbols.362363#. Form quotient by 2-term S and (possibly) I relations.364365#. Create a sparse matrix `A` with `m` columns,366whose rows encode the relations367368.. math::369370[x_i] + [x_i T] + [x_i T^2] = 0.371372373There are about n such rows. The number of nonzero entries per row374is at most 3\*(k-1). Note that we must include rows for *all* i,375since even if `[x_i] = [x_j]`, it need not be the case376that `[x_i T] = [x_j T]`, since `S` and377`T` do not commute. However, in many cases we have an a378priori formula for the dimension of the quotient by all these379relations, so we can omit many relations and just check that there380are enough at the end--if there aren't, we add in more.381382#. Compute the reduced row echelon form of `A` using sparse383Gaussian elimination.384385#. Use what we've done above to read off a sparse matrix R that386uniquely expresses each of the n Manin symbols in terms of a subset387of Manin symbols, modulo the relations. This subset of Manin388symbols is a basis for the quotient by the relations.389390391EXAMPLE::392393sage: L = sage.modular.modsym.manin_symbols.ManinSymbolList_gamma0(8,2)394sage: sage.modular.modsym.relation_matrix.compute_presentation(L, 1, GF(9,'a'), True)395(396[2 0 0]397[1 0 0]398[0 0 0]399[0 2 0]400[0 0 0]401[0 0 2]402[0 0 0]403[0 2 0]404[0 0 0]405[0 1 0]406[0 1 0]407[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)]408)409"""410if sparse is None:411if syms.weight() >= 6:412sparse = False413else:414sparse = True415R, mod = relation_matrix_wtk_g0(syms, sign, field, sparse)416B, basis = gens_to_basis_matrix(syms, R, mod, field, sparse)417return B, basis, mod418419def relation_matrix_wtk_g0(syms, sign, field, sparse):420r"""421Compute the matrix of relations. Despite the name, this is used for all422spaces (not just for Gamma0). For a description of the algorithm, see the423docstring for ``compute_presentation``.424425INPUT:426427- ``syms``: sage.modular.modsym.manin_symbols.ManinSymbolList object428429- ``sign``: integer (0, 1 or -1)430431- ``field``: the base field (non-field base rings not supported at present)432433- ``sparse``: (True or False) whether to use sparse arithmetic.434435Note that ManinSymbolList objects already have a specific weight, so there436is no need for an extra ``weight`` parameter.437438OUTPUT: a pair (R, mod) where439440- R is a matrix as output by ``T_relation_matrix_wtk_g0``441442- mod is a set of 2-term relations as output by ``sparse_2term_quotient``443444EXAMPLE::445446sage: L = sage.modular.modsym.manin_symbols.ManinSymbolList_gamma0(8,2)447sage: A = sage.modular.modsym.relation_matrix.relation_matrix_wtk_g0(L, 0, GF(2), True); A448(449[0 0 0 0 0 0 0 0 1 0 0 0]450[0 0 0 0 0 0 0 0 1 1 1 0]451[0 0 0 0 0 0 1 0 0 1 1 0]452[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)]453)454sage: A[0].is_sparse()455True456"""457rels = modS_relations(syms)458if sign != 0:459# Let rels = rels union I relations.460rels.update(modI_relations(syms,sign))461462if syms._apply_S_only_0pm1() and is_RationalField(field):463import relation_matrix_pyx464mod = relation_matrix_pyx.sparse_2term_quotient_only_pm1(rels, len(syms))465else:466mod = sparse_2term_quotient(rels, len(syms), field)467468R = T_relation_matrix_wtk_g0(syms, mod, field, sparse)469return R, mod470471def sparse_2term_quotient(rels, n, F):472r"""473Performs Sparse Gauss elimination on a matrix all of whose columns474have at most 2 nonzero entries. We use an obvious algorithm, which475runs fast enough. (Typically making the list of relations takes476more time than computing this quotient.) This algorithm is more477subtle than just "identify symbols in pairs", since complicated478relations can cause generators to surprisingly equal 0.479480INPUT:481482483- ``rels`` - set of pairs ((i,s), (j,t)). The pair484represents the relation s\*x_i + t\*x_j = 0, where the i, j must485be Python int's.486487- ``n`` - int, the x_i are x_0, ..., x_n-1.488489- ``F`` - base field490491492OUTPUT:493494495- ``mod`` - list such that mod[i] = (j,s), which means496that x_i is equivalent to s\*x_j, where the x_j are a basis for497the quotient.498499500EXAMPLE: We quotient out by the relations501502.. math::5035043*x0 - x1 = 0,\qquad x1 + x3 = 0,\qquad x2 + x3 = 0,\qquad x4 - x5 = 0505506507to get508509::510511sage: 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))]512sage: rels = set(v)513sage: n = 6514sage: from sage.modular.modsym.relation_matrix import sparse_2term_quotient515sage: sparse_2term_quotient(rels, n, QQ)516[(3, -1/3), (3, -1), (3, -1), (3, 1), (5, 1), (5, 1)]517"""518if not isinstance(rels, set):519raise TypeError, "rels must be a set"520n = int(n)521if not isinstance(F, rings.Ring):522raise TypeError, "F must be a ring."523524tm = misc.verbose("Starting sparse 2-term quotient...")525free = range(n)526ONE = F(1)527ZERO = F(0)528coef = [ONE for i in xrange(n)]529related_to_me = [[] for i in xrange(n)]530for v0, v1 in rels:531c0 = coef[v0[0]] * F(v0[1])532c1 = coef[v1[0]] * F(v1[1])533534# Mod out by the following relation:535#536# c0*free[v0[0]] + c1*free[v1[0]] = 0.537#538die = None539if c0 == ZERO and c1 == ZERO:540pass541elif c0 == ZERO and c1 != ZERO: # free[v1[0]] --> 0542die = free[v1[0]]543elif c1 == ZERO and c0 != ZERO:544die = free[v0[0]]545elif free[v0[0]] == free[v1[0]]:546if c0 + c1 != 0:547# all xi equal to free[v0[0]] must now equal to zero.548die = free[v0[0]]549else: # x1 = -c1/c0 * x2.550x = free[v0[0]]551free[x] = free[v1[0]]552coef[x] = -c1/c0553for i in related_to_me[x]:554free[i] = free[x]555coef[i] *= coef[x]556related_to_me[free[v1[0]]].append(i)557related_to_me[free[v1[0]]].append(x)558if die is not None:559for i in related_to_me[die]:560free[i] = 0561coef[i] = ZERO562free[die] = 0563coef[die] = ZERO564565mod = [(free[i], coef[i]) for i in xrange(len(free))]566misc.verbose("finished",tm)567return mod568569570571#############################################################572## The following two sparse_relation_matrix are not573## used by any modular symbols code. They're here for574## historical reasons, and can probably be safely deleted.575#############################################################576577## def sparse_relation_matrix_wt2_g0n(list, field, sign=0):578## r"""579## Create the sparse relation matrix over $\Q$ for Manin symbols of580## weight 2 on $\Gamma_0(N)$, with given sign.581582## INPUT:583## list -- sage.modular.modsym.p1list.List584## OUTPUT:585## A -- a sparse matrix that gives the 2-term and 3-term586## relations between Manin symbols.587588## MORE DETAILS:589## \begin{enumerate}590## \item Create an empty sparse matrix.591592## \item Let $S = [0,-1; 1,0]$, $T = [0,-1; 1,-1]$, $I = [-1,0; 0,1]$.593594## \item Enter the T relations:595## $$596## x + x T = 0.597## $$598## Remove x and x*T from reps to consider.599600## \item If sign $\neq 0$, enter the I relations:601## $$602## x - sign\cdot x\cdot I = 0.603## $$604605## \item Enter the S relations in the matrix:606## $$607## x + x S + x S^2 = 0608## $$609## by putting 1s at cols corresponding to $x$, $x S$, and $x S^2$.610## Remove $x$, $x S$, and $x S^2$ from list of reps to consider.611## \end{enumerate}612## """613## ZERO = field(0)614## ONE = field(1)615## TWO = field(2)616617## # This will be a dict of the entries of the sparse matrix, where618## # the notation is entries[(i,j)]=x.619## entries = {}620621## # The current row622## row = 0623624## ## The S relations625## already_seen= set([])626## for i in range(len(list)):627## if i in already_seen:628## continue629## u,v = list[i]630## j = list.index(v,-u)631## already_seen.add(j)632## if i != j:633## entries[(row,i)] = ONE634## entries[(row,j)] = ONE635## else:636## entries[(row,i)] = TWO637## row += 1638## number_of_S_relations = row639## misc.verbose("There were %s S relations"%(number_of_S_relations))640641## ## The eta relations:642## ## eta((u,v)) = -(-u,v)643## if sign != 0:644## SIGN = field(sign)645## already_seen= set([])646## for i in range(len(list)):647## if i in already_seen:648## continue649## u, v = list[i]650## j = list.index(-u,v)651## already_seen.add(j)652## if i != j:653## entries[(row,i)] = ONE654## entries[(row,j)] = SIGN*ONE655## else:656## entries[(row,i)] = ONE + SIGN657## row += 1658## number_of_I_relations = row - number_of_S_relations659## misc.verbose("There were %s I relations"%(number_of_I_relations))660661## ## The three-term T relations662## already_seen = set([])663## for i in range(len(list)):664## if i in already_seen:665## continue666## u,v = list[i]667## j1 = list.index(v,-u-v)668## already_seen.add(j1)669## j2 = list.index(-u-v,u)670## already_seen.add(j2)671## v = {i:ZERO, j1:ZERO, j2:ZERO}672## v[i] = ONE673## v[j1] += ONE674## v[j2] += ONE675## for x in v.keys():676## entries[(row,x)] = v[x]677## row += 1678679## number_of_T_relations = row - number_of_I_relations - number_of_S_relations680## misc.verbose("There were %s T relations"%(number_of_T_relations))681682## M = matrix_space.MatrixSpace(RationalField(), row,683## len(list), sparse=True)684## if not sparse:685## M = M.dense_matrix()686687## return M(entries)688689## def sparse_relation_matrix_wtk_g0n(M, field, sign=0):690## r"""691## Create the sparse relation matrix over $\Q$ for Manin symbols of692## given weight on $\Gamma_0(N)$, with given sign.693694## INPUT:695## M -- manin_symbols.ManinSymbolList696## field -- base field697## weight -- the weight, an integer > 2698## sign -- element of [-1,0,1]699700## OUTPUT:701## A -- a SparseMatrix that gives the 2-term and 3-term relations702## between Manin symbols.703704## MORE DETAILS:705## \begin{enumerate}706## \item Create an empty sparse matrix.707708## \item Let $S = [0,-1; 1,0]$, $T = [0,-1; 1,-1]$, $I = [-1,0; 0,1]$.709710## \item Enter the $T$ relations:711## $$ x + x*T = 0 $$712## Remove $x$ and $x T$ from reps to consider.713714## \item If sign $\neq 0$, enter the I relations:715## $$716## x + sign x I = 0.717## $$718719## \item Enter the $S$ relations in the matrix:720## $$721## x + x S + x S^2 = 0722## $$723## by putting 1's at cols corresponding to $x$, $x S$, and $x S^2$.724## Remove x from list of reps to consider.725## \end{enumerate}726## """727## weight = M.weight()728## if not (isinstance(weight, int) and weight > 2):729## raise TypeError, "weight must be an int > 2"730731## ZERO = field(0)732## ONE = field(1)733## TWO = field(2)734735## # This will be a dict of the entries of the sparse matrix, where736## # the notation is entries[(i,j)]=x.737## entries = {}738739## # The current row740## row = 0741742## # The list of Manin symbol triples (i,u,v)743## n = len(M)744745## ## The S relations746## already_seen= set([])747## for i in xrange(n):748## if i in already_seen:749## continue750## j, s = M.apply_S(i)751## already_seen.add(j)752## if i != j:753## entries[(row,i)] = ONE754## entries[(row,j)] = field(s)755## else:756## entries[(row,i)] = ONE+field(s)757## row += 1758## number_of_S_relations = row759## misc.verbose("There were %s S relations"%(number_of_S_relations))760## cnt = row761## ## The I relations762## if sign != 0:763## SIGN = field(sign)764## already_seen= set([])765## for i in xrange(n):766## if i in already_seen:767## continue768## j, s = M.apply_I(i)769## already_seen.add(j)770## if i != j:771## entries[(row,i)] = ONE772## entries[(row,j)] = -SIGN*field(s)773## else:774## entries[(row,i)] = ONE-SIGN*field(s)775## row += 1776## number_of_I_relations = row - number_of_S_relations777## misc.verbose("There were %s I relations"%(number_of_I_relations))778## cnt = row779780## ## The T relations781## already_seen = set([])782## for i in xrange(n):783## if i in already_seen:784## continue785## iT_plus_iTT = M.apply_T(i) + M.apply_TT(i)786## v = {i:ONE}787## for j, s in iT_plus_iTT:788## if v.has_key(j):789## v[j] += field(s)790## else:791## v[j] = field(s)792## for j in v.keys():793## entries[(row, j)] = v[j]794## row += 1795796797798