def __dimension_Sp6Z(wt): """ Return the dimensions of subspaces of Siegel modular forms on $Sp(4,Z)$. OUTPUT ("Total", "Miyawaki-Type-1", "Miyawaki-Type-2 (conjectured)", "Interesting") Remember, Miywaki type 2 is ONLY CONJECTURED!! """ if not is_even(wt): return (0, 0, 0, 0) R = PowerSeriesRing(IntegerRing(), default_prec=wt + 1, names=('x', )) (x, ) = R._first_ngens(1) R = PowerSeriesRing(IntegerRing(), default_prec=2 * wt - 1, names=('y', )) (y, ) = R._first_ngens(1) H_all = 1 / ( (1 - x**4) * (1 - x**12)**2 * (1 - x**14) * (1 - x**18) * (1 - x**20) * (1 - x**30)) * (1 + x**6 + x**10 + x**12 + 3 * x**16 + 2 * x**18 + 2 * x**20 + 5 * x**22 + 4 * x**24 + 5 * x**26 + 7 * x**28 + 6 * x**30 + 9 * x**32 + 10 * x**34 + 10 * x**36 + 12 * x**38 + 14 * x**40 + 15 * x**42 + 16 * x**44 + 18 * x**46 + 18 * x**48 + 19 * x**50 + 21 * x**52 + 19 * x**54 + 21 * x**56 + 21 * x**58 + 19 * x**60 + 21 * x**62 + 19 * x**64 + 18 * x**66 + 18 * x**68 + 16 * x**70 + 15 * x**72 + 14 * x**74 + 12 * x**76 + 10 * x**78 + 10 * x**80 + 9 * x**82 + 6 * x**84 + 7 * x**86 + 5 * x**88 + 4 * x**90 + 5 * x**92 + 2 * x**94 + 2 * x**96 + 3 * x**98 + x**102 + x**104 + x**108 + x**114) H_noncusp = 1 / (1 - x**4) / (1 - x**6) / (1 - x**10) / (1 - x**12) H_E = y**12 / (1 - y**4) / (1 - y**6) H_Miyawaki1 = H_E[wt] * H_E[2 * wt - 4] H_Miyawaki2 = H_E[wt - 2] * H_E[2 * wt - 2] a, b, c, d = H_all[wt], H_noncusp[wt], H_Miyawaki1, H_Miyawaki2 return (a, c, d, a - b - c - d)
def _is_even_symmetric_matrix_(self, A, R=None): """ Tests if a matrix is symmetric, defined over R, and has even diagonal in R. INPUT: A -- matrix R -- ring EXAMPLES:: sage: Q = QuadraticForm(ZZ, 2, [2,3,5]) sage: A = Q.matrix() sage: A [ 4 3] [ 3 10] sage: Q._is_even_symmetric_matrix_(A) True sage: A[0,0] = 1 sage: Q._is_even_symmetric_matrix_(A) False """ if not is_Matrix(A): raise TypeError("A is not a matrix.") ring_coerce_test = True if R == None: ## This allows us to omit the ring from the variables, and take it from the matrix R = A.base_ring() ring_coerce_test = False if not isinstance(R, Ring): raise TypeError("R is not a ring.") if not A.is_square(): return False ## Test that the matrix is symmetric n = A.nrows() for i in range(n): for j in range(i+1, n): if A[i,j] != A[j,i]: return False ## Test that all entries coerce to R if not ((A.base_ring() == R) or (ring_coerce_test == True)): try: for i in range(n): for j in range(i, n): x = R(A[i,j]) except Exception: return False ## Test that the diagonal is even (if 1/2 isn't in R) if not R(2).is_unit(): for i in range(n): if not is_even(R(A[i,i])): return False return True
def apply_simple_reflection_right(self, i): r""" Implements :meth:`CoxeterGroups.ElementMethods.apply_simple_reflection`. EXAMPLES:: sage: D5 = FiniteCoxeterGroups().example(5) sage: [i^2 for i in D5] # indirect doctest [(), (), (), (1, 2, 1, 2), (2, 1, 2, 1), (), (), (2, 1), (1, 2), ()] sage: [i^5 for i in D5] # indirect doctest [(), (1,), (2,), (), (), (1, 2, 1), (2, 1, 2), (), (), (1, 2, 1, 2, 1)] """ from copy import copy reduced_word = copy(self.value) n = self.parent().n if len(reduced_word) == n: if (i == 1 and is_odd(n)) or (i == 2 and is_even(n)): return self.parent()(reduced_word[:-1]) else: return self.parent()(reduced_word[1:]) elif (len(reduced_word) == n - 1 and (not self.has_descent(i))) and (reduced_word[0] == 2): return self.parent()((1, ) + reduced_word) else: if self.has_descent(i): return self.parent()(reduced_word[:-1]) else: return self.parent()(reduced_word + (i, ))
def _dimension_Sp4Z( wt_range): """ Return the dimensions of subspaces of Siegel modular forms on $Sp(4,Z)$. OUTPUT ("Total", "Eisenstein", "Klingen", "Maass", "Interesting") """ headers = ['Total', 'Eisenstein', 'Klingen', 'Maass', 'Interesting'] R = PowerSeriesRing( IntegerRing(), default_prec = wt_range[-1] + 1, names = ('x',)) (x,) = R._first_ngens(1) H_all = 1 / (1 - x ** 4) / (1 - x ** 6) / (1 - x ** 10) / (1 - x ** 12) H_Kl = x ** 12 / (1 - x ** 4) / (1 - x ** 6) H_MS = (x ** 10 + x ** 12) / (1 - x ** 4) / (1 - x ** 6) dct = dict( (k, { 'Total': H_all[k], 'Eisenstein': 1 if k >= 4 else 0, 'Klingen': H_Kl[k], 'Maass': H_MS[k], 'Interesting': H_all[k]-(1 if k >= 4 else 0)-H_Kl[k]-H_MS[k] } if is_even(k) else { 'Total': H_all[k-35], 'Eisenstein': 0, 'Klingen': 0, 'Maass': 0, 'Interesting': H_all[k-35] } ) for k in wt_range) return headers, dct
def __dimension_Sp6Z(wt): """ Return the dimensions of subspaces of Siegel modular forms on $Sp(6,Z)$. OUTPUT ("Total", "Miyawaki-Type-1", "Miyawaki-Type-2 (conjectured)", "Interesting") Remember, Miywaki type 2 is ONLY CONJECTURED!! """ if not is_even(wt): return (0, 0, 0, 0) R = PowerSeriesRing(IntegerRing(), default_prec=wt + 1, names=('x',)) (x,) = R._first_ngens(1) S = PowerSeriesRing(IntegerRing(), default_prec=max(2 * wt - 1,1), names=('y',)) (y,) = S._first_ngens(1) H_all = 1 / ((1 - x ** 4) * (1 - x ** 12) ** 2 * (1 - x ** 14) * (1 - x ** 18) * (1 - x ** 20) * (1 - x ** 30)) * ( 1 + x ** 6 + x ** 10 + x ** 12 + 3 * x ** 16 + 2 * x ** 18 + 2 * x ** 20 + 5 * x ** 22 + 4 * x ** 24 + 5 * x ** 26 + 7 * x ** 28 + 6 * x ** 30 + 9 * x ** 32 + 10 * x ** 34 + 10 * x ** 36 + 12 * x ** 38 + 14 * x ** 40 + 15 * x ** 42 + 16 * x ** 44 + 18 * x ** 46 + 18 * x ** 48 + 19 * x ** 50 + 21 * x ** 52 + 19 * x ** 54 + 21 * x ** 56 + 21 * x ** 58 + 19 * x ** 60 + 21 * x ** 62 + 19 * x ** 64 + 18 * x ** 66 + 18 * x ** 68 + 16 * x ** 70 + 15 * x ** 72 + 14 * x ** 74 + 12 * x ** 76 + 10 * x ** 78 + 10 * x ** 80 + 9 * x ** 82 + 6 * x ** 84 + 7 * x ** 86 + 5 * x ** 88 + 4 * x ** 90 + 5 * x ** 92 + 2 * x ** 94 + 2 * x ** 96 + 3 * x ** 98 + x ** 102 + x ** 104 + x ** 108 + x ** 114) H_noncusp = 1 / (1 - x ** 4) / (1 - x ** 6) / (1 - x ** 10) / (1 - x ** 12) H_E = y ** 12 / (1 - y ** 4) / (1 - y ** 6) H_Miyawaki1 = H_E[wt] * H_E[2 * wt - 4] H_Miyawaki2 = H_E[wt - 2] * H_E[2 * wt - 2] a, b, c, d = H_all[wt], H_noncusp[wt], H_Miyawaki1, H_Miyawaki2 return (a, c, d, a - b - c - d)
def _dimension_Sp4Z(wt_range): """ Return the dimensions of subspaces of Siegel modular forms on $Sp(4,Z)$. OUTPUT ("Total", "Eisenstein", "Klingen", "Maass", "Interesting") """ headers = ['Total', 'Eisenstein', 'Klingen', 'Maass', 'Interesting'] R = PowerSeriesRing(IntegerRing(), default_prec=wt_range[-1] + 1, names=('x', )) (x, ) = R._first_ngens(1) H_all = 1 / (1 - x**4) / (1 - x**6) / (1 - x**10) / (1 - x**12) H_Kl = x**12 / (1 - x**4) / (1 - x**6) H_MS = (x**10 + x**12) / (1 - x**4) / (1 - x**6) dct = dict( (k, { 'Total': H_all[k], 'Eisenstein': 1 if k >= 4 else 0, 'Klingen': H_Kl[k], 'Maass': H_MS[k], 'Interesting': H_all[k] - (1 if k >= 4 else 0) - H_Kl[k] - H_MS[k] } if is_even(k) else { 'Total': H_all[k - 35], 'Eisenstein': 0, 'Klingen': 0, 'Maass': 0, 'Interesting': H_all[k - 35] }) for k in wt_range) return headers, dct
def apply_simple_reflection_right(self, i): r""" Implements :meth:`CoxeterGroups.ElementMethods.apply_simple_reflection`. EXEMPLES:: sage: D5 = FiniteCoxeterGroups().example(5) sage: [i^2 for i in D5] [(), (), (1, 2, 1, 2), (), (2, 1), (), (), (2, 1, 2, 1), (), (1, 2)] sage: [i^5 for i in D5] [(), (1,), (), (1, 2, 1), (), (1, 2, 1, 2, 1), (2,), (), (2, 1, 2), ()] """ from copy import copy reduced_word = copy(self.value) n = self.parent().n if len(reduced_word) == n: if (i == 1 and is_odd(n)) or (i == 2 and is_even(n)): return self.parent()(reduced_word[:-1]) else: return self.parent()(reduced_word[1:]) elif (len(reduced_word) == n-1 and (not self.has_descent(i))) and (reduced_word[0] == 2): return self.parent()((1,)+reduced_word) else: if self.has_descent(i): return self.parent()(reduced_word[:-1]) else: return self.parent()(reduced_word+(i,))
def hadamard_matrix(n): """ Tries to construct a Hadamard matrix using a combination of Paley and Sylvester constructions. EXAMPLES:: sage: hadamard_matrix(12).det() 2985984 sage: 12^6 2985984 sage: hadamard_matrix(2) [ 1 1] [ 1 -1] sage: hadamard_matrix(8) [ 1 1 1 1 1 1 1 1] [ 1 -1 1 -1 1 -1 1 -1] [ 1 1 -1 -1 1 1 -1 -1] [ 1 -1 -1 1 1 -1 -1 1] [ 1 1 1 1 -1 -1 -1 -1] [ 1 -1 1 -1 -1 1 -1 1] [ 1 1 -1 -1 -1 -1 1 1] [ 1 -1 -1 1 -1 1 1 -1] sage: hadamard_matrix(8).det() == 8^4 True """ if not (n % 4 == 0) and (n != 2): raise ValueError("The Hadamard matrix of order %s does not exist" % n) if n == 2: return matrix([[1, 1], [1, -1]]) if is_even(n): N = Integer(n / 2) elif n == 1: return matrix([1]) if is_prime(N - 1) and (N - 1) % 4 == 1: return hadamard_matrix_paleyII(n) elif n == 4 or n % 8 == 0: had = hadamard_matrix(Integer(n / 2)) chad1 = matrix([list(r) + list(r) for r in had.rows()]) mhad = (-1) * had R = len(had.rows()) chad2 = matrix( [list(had.rows()[i]) + list(mhad.rows()[i]) for i in range(R)]) return chad1.stack(chad2) elif is_prime(N - 1) and (N - 1) % 4 == 3: return hadamard_matrix_paleyI(n) else: raise ValueError( "The Hadamard matrix of order %s is not yet implemented." % n)
def hadamard_matrix(n): """ Tries to construct a Hadamard matrix using a combination of Paley and Sylvester constructions. EXAMPLES:: sage: hadamard_matrix(12).det() 2985984 sage: 12^6 2985984 sage: hadamard_matrix(2) [ 1 1] [ 1 -1] sage: hadamard_matrix(8) [ 1 1 1 1 1 1 1 1] [ 1 -1 1 -1 1 -1 1 -1] [ 1 1 -1 -1 1 1 -1 -1] [ 1 -1 -1 1 1 -1 -1 1] [ 1 1 1 1 -1 -1 -1 -1] [ 1 -1 1 -1 -1 1 -1 1] [ 1 1 -1 -1 -1 -1 1 1] [ 1 -1 -1 1 -1 1 1 -1] sage: hadamard_matrix(8).det() == 8^4 True """ if not(n % 4 == 0) and (n != 2): raise ValueError("The Hadamard matrix of order %s does not exist" % n) if n == 2: return matrix([[1, 1], [1, -1]]) if is_even(n): N = Integer(n / 2) elif n == 1: return matrix([1]) if is_prime(N - 1) and (N - 1) % 4 == 1: return hadamard_matrix_paleyII(n) elif n == 4 or n % 8 == 0: had = hadamard_matrix(Integer(n / 2)) chad1 = matrix([list(r) + list(r) for r in had.rows()]) mhad = (-1) * had R = len(had.rows()) chad2 = matrix([list(had.rows()[i]) + list(mhad.rows()[i]) for i in range(R)]) return chad1.stack(chad2) elif is_prime(N - 1) and (N - 1) % 4 == 3: return hadamard_matrix_paleyI(n) else: raise ValueError("The Hadamard matrix of order %s is not yet implemented." % n)
def _dimension_Gamma0_4_psi_4(wt): """ Return the dimensions of subspaces of Siegel modular forms on $Gamma_0(4)$ with character $\psi_4$. OUTPUT ( "Total") REMARK The formula for odd weights is unknown or not obvious from the paper. """ R = PowerSeriesRing(IntegerRing(), default_prec=wt + 1, names=("x",)) (x,) = R._first_ngens(1) H_all_even = (x ** 12 + x ** 14) / (1 - x ** 2) ** 3 / (1 - x ** 6) if is_even(wt): return (H_all_even[wt],) else: raise NotImplementedError("Dimensions of $M_{k}(\Gamma_0(4), \psi_4)$ for odd $k$ not implemented")
def is_bent(self): r""" Return ``True`` if this S-Box is bent, i.e. its nonlinearity is equal to `2^{m-1} - 2^{m/2 - 1}` where `m` is the input size of the S-Box. EXAMPLES:: sage: from sage.crypto.sbox import SBox sage: R.<x> = GF(2**2, 'a')[] sage: base = R.base_ring() sage: a = base.gen() sage: G = a * x^2 + 1 sage: S = SBox([G(x * y**(14)) for x in sorted(base) for y in sorted(base)]) sage: S.is_bent() True sage: S.nonlinearity() 6 sage: S.linear_approximation_matrix() [ 8 -2 2 -2] [ 0 -2 2 -2] [ 0 -2 2 -2] [ 0 -2 2 -2] [ 0 -2 2 -2] [ 0 -2 -2 2] [ 0 2 2 2] [ 0 2 -2 -2] [ 0 -2 2 -2] [ 0 2 -2 -2] [ 0 -2 -2 2] [ 0 2 2 2] [ 0 -2 2 -2] [ 0 2 2 2] [ 0 2 -2 -2] [ 0 -2 -2 2] """ m = self.m n = self.n if not is_even(m) or n > m//2: return False return self.nonlinearity() == 2**(m-1) - 2**(m//2 - 1)
def _dimension_Gamma0_3_psi_3(wt): """ Return the dimensions of the space of Siegel modular forms on $Gamma_0(3)$ with character $\psi_3$. OUTPUT ( "Total") REMARK Not completely implemented """ R = PowerSeriesRing(IntegerRing(), default_prec=wt + 1, names=('x', )) (x, ) = R._first_ngens(1) B = 1 / (1 - x**1) / (1 - x**3) / (1 - x**4) / (1 - x**3) H_all_odd = B H_all_even = B * x**14 if is_even(wt): return (H_all_even[wt], ) else: return (H_all_odd[wt], )
def _dimension_Gamma0_3_psi_3(wt): """ Return the dimensions of the space of Siegel modular forms on $Gamma_0(3)$ with character $\psi_3$. OUTPUT ( "Total") REMARK Not completely implemented """ R = PowerSeriesRing(IntegerRing(), default_prec=wt + 1, names=("x",)) (x,) = R._first_ngens(1) B = 1 / (1 - x ** 1) / (1 - x ** 3) / (1 - x ** 4) / (1 - x ** 3) H_all_odd = B H_all_even = B * x ** 14 if is_even(wt): return (H_all_even[wt],) else: return (H_all_odd[wt],)
def _dimension_Gamma0_4_psi_4(wt): """ Return the dimensions of subspaces of Siegel modular forms on $Gamma_0(4)$ with character $\psi_4$. OUTPUT ( "Total") REMARK The formula for odd weights is unknown or not obvious from the paper. """ R = PowerSeriesRing(IntegerRing(), default_prec=wt + 1, names=('x', )) (x, ) = R._first_ngens(1) H_all_even = (x**12 + x**14) / (1 - x**2)**3 / (1 - x**6) if is_even(wt): return (H_all_even[wt], ) else: raise NotImplementedError( 'Dimensions of $M_{k}(\Gamma_0(4), \psi_4)$ for odd $k$ not implemented' )
def is_almost_bent(self): r""" Return ``True`` if this S-Box is an almost bent (AB) function. An `m \times m` S-Box `S`, for `m` odd, is called almost bent if its nonlinearity is equal to `2^{m-1} - 2^{(m-1)/2}`. EXAMPLES:: sage: S = mq.SBox([0,1,3,6,7,4,5,2]) sage: S.is_almost_bent() True """ if self.m != self.n: raise TypeError("almost bent function only exists for self.m == self.n") m = self.m if is_even(m): return False return self.nonlinearity() == 2**(m-1) - 2**((m-1)/2)
def is_almost_bent(self): r""" Return ``True`` if this S-Box is an almost bent (AB) function. An `m \times m` S-Box `S`, for `m` odd, is called almost bent if its nonlinearity is equal to `2^{m-1} - 2^{(m-1)/2}`. EXAMPLES:: sage: S = mq.SBox([0,1,3,6,7,4,5,2]) sage: S.is_almost_bent() True """ if self.m != self.n: raise TypeError("almost bent function only exists for self.m == self.n") m = self.m if is_even(m): return False return self.nonlinearity() == 2**(m-1) - 2**((m-1)//2)
def serre_cartan_mono_to_string(mono, latex=False, p=2): r""" String representation of element of the Serre-Cartan basis. This is used by the _repr_ and _latex_ methods. INPUT: - ``mono`` - tuple of positive integers (a,b,c,...) when `p=2`, or tuple (e0, n1, e1, n2, ...) when `p>2`, where each ei is 0 or 1, and each ni is positive - ``latex`` - boolean (optional, default False), if true, output LaTeX string - ``p`` - positive prime number (optional, default 2) OUTPUT: ``rep`` - string This returns a string like ``Sq^{a} Sq^{b} Sq^{c} ...`` when `p=2`, or a string like ``\beta^{e0} P^{n1} \beta^{e1} P^{n2} ...`` when `p` is odd. EXAMPLES:: sage: from sage.algebras.steenrod.steenrod_algebra_misc import serre_cartan_mono_to_string sage: serre_cartan_mono_to_string((1,2,3,4)) 'Sq^{1} Sq^{2} Sq^{3} Sq^{4}' sage: serre_cartan_mono_to_string((1,2,3,4),latex=True) '\\text{Sq}^{1} \\text{Sq}^{2} \\text{Sq}^{3} \\text{Sq}^{4}' sage: serre_cartan_mono_to_string((0,5,1,1,0), p=3) 'P^{5} beta P^{1}' sage: serre_cartan_mono_to_string((0,5,1,1,0), p=3, latex=True) '\\mathcal{P}^{5} \\beta \\mathcal{P}^{1}' The empty tuple represents the unit element 1:: sage: serre_cartan_mono_to_string(()) '1' sage: serre_cartan_mono_to_string((), p=7) '1' """ if latex: if p == 2: sq = "\\text{Sq}" P = "\\text{Sq}" else: P = "\\mathcal{P}" else: if p == 2: sq = "Sq" P = "Sq" else: P = "P" if len(mono) == 0 or mono == (0,): return "1" else: if p == 2: string = "" for n in mono: string = string + sq + "^{" + str(n) + "} " else: string = "" index = 0 for n in mono: from sage.misc.functional import is_even if is_even(index): if n == 1: if latex: string = string + "\\beta " else: string = string + "beta " else: string = string + P + "^{" + str(n) + "} " index += 1 return string.strip(" ")
def MatchingComplex(self, n): """ The matching complex of graphs on n vertices. Fix an integer `n>0` and consider a set `V` of `n` vertices. A 'partial matching' on `V` is a graph formed by edges so that each vertex is in at most one edge. If `G` is a partial matching, then so is any graph obtained by deleting edges from `G`. Thus the set of all partial matchings on `n` vertices, viewed as a set of subsets of the `n` choose 2 possible edges, is closed under taking subsets, and thus forms a simplicial complex called the 'matching complex'. This function produces that simplicial complex. INPUT: - ``n`` - positive integer. See Dumas et al. for information on computing its homology by computer, and see Wachs for an expository article about the theory. For example, the homology of these complexes seems to have only mod 3 torsion, and this has been proved for the bottom non-vanishing homology group for the matching complex `M_n`. EXAMPLES:: sage: M = simplicial_complexes.MatchingComplex(7) sage: H = M.homology() sage: H {0: 0, 1: C3, 2: Z^20} sage: H[2].ngens() 20 sage: simplicial_complexes.MatchingComplex(8).homology(2) # long time (a few seconds) Z^132 REFERENCES: - Dumas, Heckenbach, Saunders, Welker, "Computing simplicial homology based on efficient Smith normal form algorithms," in "Algebra, geometry, and software systems" (2003), 177-206. - Wachs, "Topology of Matching, Chessboard and General Bounded Degree Graph Complexes" (Algebra Universalis Special Issue in Memory of Gian-Carlo Rota, Algebra Universalis, 49 (2003) 345-385) """ G_vertices = Set(range(1, n + 1)) E_list = [] for w in G_vertices: for v in range(1, w): E_list.append((v, w)) facets = [] if is_even(n): half = int(n / 2) half_n_sets = list(G_vertices.subsets(size=half)) else: half = int((n - 1) / 2) half_n_sets = list(G_vertices.subsets(size=half)) for X in half_n_sets: Xcomp = G_vertices.difference(X) if is_even(n): if 1 in X: A = X B = Xcomp else: A = Xcomp B = X for M in matching(A, B): facet = [] for pair in M: facet.append(tuple(sorted(pair))) facets.append(facet) else: for w in Xcomp: if 1 in X or (w == 1 and 2 in X): A = X B = Xcomp.difference([w]) else: B = X A = Xcomp.difference([w]) for M in matching(A, B): facet = [] for pair in M: facet.append(tuple(sorted(pair))) facets.append(facet) return SimplicialComplex(E_list, facets)
def MatchingComplex(self, n): """ The matching complex of graphs on n vertices. Fix an integer `n>0` and consider a set `V` of `n` vertices. A 'partial matching' on `V` is a graph formed by edges so that each vertex is in at most one edge. If `G` is a partial matching, then so is any graph obtained by deleting edges from `G`. Thus the set of all partial matchings on `n` vertices, viewed as a set of subsets of the `n` choose 2 possible edges, is closed under taking subsets, and thus forms a simplicial complex called the 'matching complex'. This function produces that simplicial complex. INPUT: - ``n`` - positive integer. See Dumas et al. for information on computing its homology by computer, and see Wachs for an expository article about the theory. For example, the homology of these complexes seems to have only mod 3 torsion, and this has been proved for the bottom non-vanishing homology group for the matching complex `M_n`. EXAMPLES:: sage: M = simplicial_complexes.MatchingComplex(7) sage: H = M.homology() sage: H {0: 0, 1: C3, 2: Z^20} sage: H[2].ngens() 20 sage: simplicial_complexes.MatchingComplex(8).homology(2) # long time (a few seconds) Z^132 REFERENCES: - Dumas, Heckenbach, Saunders, Welker, "Computing simplicial homology based on efficient Smith normal form algorithms," in "Algebra, geometry, and software systems" (2003), 177-206. - Wachs, "Topology of Matching, Chessboard and General Bounded Degree Graph Complexes" (Algebra Universalis Special Issue in Memory of Gian-Carlo Rota, Algebra Universalis, 49 (2003) 345-385) """ G_vertices = Set(range(1,n+1)) E_list = [] for w in G_vertices: for v in range(1,w): E_list.append((v,w)) facets = [] if is_even(n): half = int(n/2) half_n_sets = list(G_vertices.subsets(size=half)) else: half = int((n-1)/2) half_n_sets = list(G_vertices.subsets(size=half)) for X in half_n_sets: Xcomp = G_vertices.difference(X) if is_even(n): if 1 in X: A = X B = Xcomp else: A = Xcomp B = X for M in matching(A, B): facet = [] for pair in M: facet.append(tuple(sorted(pair))) facets.append(facet) else: for w in Xcomp: if 1 in X or (w == 1 and 2 in X): A = X B = Xcomp.difference([w]) else: B = X A = Xcomp.difference([w]) for M in matching(A, B): facet = [] for pair in M: facet.append(tuple(sorted(pair))) facets.append(facet) return SimplicialComplex(E_list, facets)
def product_on_basis(self, w1, w2): r""" Return the product of two indices within the algebra. EXAMPLES:: sage: A.<x,y,z> = GradedCommutativeAlgebra(QQ, degrees=(4,8,2), max_degree=10) sage: z*x x*z sage: x^3 0 sage: 5*z + 4*z*x 5*z + 4*x*z :: sage: A.<x,y,z> = GradedCommutativeAlgebra(QQ, degrees=(1,2,3), max_degree=5) sage: 2*x*y 2*x*y sage: x^2 0 sage: x*z x*z sage: z*x -x*z sage: x*y*z 0 TESTS:: sage: A.<x,y,z> = GradedCommutativeAlgebra(QQ, degrees=(4,8,2), max_degree=10) sage: weighted_vectors = A._weighted_vectors sage: w1 = A._weighted_vectors([1,0,1]) sage: w2 = A._weighted_vectors([0,0,0]) sage: A.product_on_basis(w1, w2) x*z :: sage: A.<x,y,z> = GradedCommutativeAlgebra(QQ, degrees=(1,2,3), max_degree=5) sage: weighted_vectors = A._weighted_vectors sage: w1 = A._weighted_vectors([1,0,0]) sage: w2 = A._weighted_vectors([0,0,1]) sage: A.product_on_basis(w1, w2) x*z sage: A.product_on_basis(w2, w1) -x*z :: sage: A.<x,y,z> = GradedCommutativeAlgebra(QQ, degrees=(1,2,3), max_degree=10) sage: weighted_vectors = A._weighted_vectors sage: w1 = A._weighted_vectors([1,1,0]) sage: w2 = A._weighted_vectors([0,1,1]) sage: A.product_on_basis(w1, w2) x*y^2*z sage: A.product_on_basis(w2, w1) -x*y^2*z """ grading = self._weighted_vectors.grading deg_left = grading(w1) deg_right = grading(w2) deg_tot = deg_left + deg_right if deg_tot > self._max_deg: return self.zero() w_tot = self._weighted_vectors([sum(w) for w in zip(w1, w2)]) if not self._valid_index(w_tot): return self.zero() # determine sign n = self.__ngens c = 0 for p, i, d in zip(reversed(range(n)), reversed(w1), reversed(self._degrees)): if is_even(d) or i == 0: continue for q, j, b in zip(range(n), w2, self._degrees): if q == p: break if j == 0 or is_even(b): continue c += 1 return (-1)**c * self.monomial(w_tot)
def serre_cartan_mono_to_string(mono, latex=False, generic=False): r""" String representation of element of the Serre-Cartan basis. This is used by the _repr_ and _latex_ methods. INPUT: - ``mono`` - tuple of positive integers (a,b,c,...) when `generic=False`, or tuple (e0, n1, e1, n2, ...) when `generic=True`, where each ei is 0 or 1, and each ni is positive - ``latex`` - boolean (optional, default False), if true, output LaTeX string - ``generic`` - whether to format generically, or for the prime 2 (default) OUTPUT: ``rep`` - string This returns a string like ``Sq^{a} Sq^{b} Sq^{c} ...`` when `generic=False`, or a string like ``\beta^{e0} P^{n1} \beta^{e1} P^{n2} ...`` when `generic=True`. is odd. EXAMPLES:: sage: from sage.algebras.steenrod.steenrod_algebra_misc import serre_cartan_mono_to_string sage: serre_cartan_mono_to_string((1,2,3,4)) 'Sq^{1} Sq^{2} Sq^{3} Sq^{4}' sage: serre_cartan_mono_to_string((1,2,3,4),latex=True) '\\text{Sq}^{1} \\text{Sq}^{2} \\text{Sq}^{3} \\text{Sq}^{4}' sage: serre_cartan_mono_to_string((0,5,1,1,0), generic=True) 'P^{5} beta P^{1}' sage: serre_cartan_mono_to_string((0,5,1,1,0), generic=True, latex=True) '\\mathcal{P}^{5} \\beta \\mathcal{P}^{1}' The empty tuple represents the unit element 1:: sage: serre_cartan_mono_to_string(()) '1' sage: serre_cartan_mono_to_string((), generic=True) '1' """ if latex: if not generic: sq = "\\text{Sq}" P = "\\text{Sq}" else: P = "\\mathcal{P}" else: if not generic: sq = "Sq" P = "Sq" else: P = "P" if len(mono) == 0 or mono == (0, ): return "1" else: if not generic: string = "" for n in mono: string = string + sq + "^{" + str(n) + "} " else: string = "" index = 0 for n in mono: from sage.misc.functional import is_even if is_even(index): if n == 1: if latex: string = string + "\\beta " else: string = string + "beta " else: string = string + P + "^{" + str(n) + "} " index += 1 return string.strip(" ")