def __classcall_private__(cls, R, names, index_set=None): """ Normalize input to ensure a unique representation. """ names, index_set = standardize_names_index_set(names, index_set) return super(NotAFreeLieAlgebra, cls).__classcall__(cls, R, names, index_set)
def __init__(self, R, ngens=1, weights=None, parity=None, names=None, index_set=None): """ Initialize self. EXAMPLES:: sage: V = lie_conformal_algebras.Abelian(QQ) sage: TestSuite(V).run() """ if (names is None) and (index_set is None): names = 'a' self._latex_names = tuple(r'a_{%d}' % i for i in range(ngens)) names, index_set = standardize_names_index_set(names=names, index_set=index_set, ngens=ngens) abeliandict = {} GradedLieConformalAlgebra.__init__(self, R, abeliandict, names=names, index_set=index_set, weights=weights, parity=parity)
def __classcall_private__(cls, R, classification, s_coeff, names, index_set=None, category=None, **kwds): r""" Normalize input to ensure a unique representation. """ names, index_set = standardize_names_index_set(names, index_set) s_coeff = LieAlgebraWithStructureCoefficients._standardize_s_coeff( s_coeff, index_set) cat = LieAlgebras(R).FiniteDimensional().WithBasis().Nilpotent() category = cat.or_subcategory(category) return super(ClassifiedNilpotentLieAlgebra, cls).__classcall__(cls, R, classification, s_coeff, names, index_set, category=category, **kwds)
def __classcall_private__(cls, R, s_coeff, names=None, index_set=None, category=None, **kwds): """ Normalize input to ensure a unique representation. EXAMPLES: If the variable order is specified, the order of structural coefficients does not matter:: sage: from sage.algebras.lie_algebras.nilpotent_lie_algebra import NilpotentLieAlgebra_dense sage: L1.<x,y,z> = NilpotentLieAlgebra_dense(QQ, {('x','y'): {'z': 1}}) sage: L2.<x,y,z> = NilpotentLieAlgebra_dense(QQ, {('y','x'): {'z': -1}}) sage: L1 is L2 True If the variables are implicitly defined by the structural coefficients, the ordering may be different and the Lie algebras will be considered different:: sage: from sage.algebras.lie_algebras.nilpotent_lie_algebra import NilpotentLieAlgebra_dense sage: L1 = NilpotentLieAlgebra_dense(QQ, {('x','y'): {'z': 1}}) sage: L2 = NilpotentLieAlgebra_dense(QQ, {('y','x'): {'z': -1}}) sage: L1 Nilpotent Lie algebra on 3 generators (x, y, z) over Rational Field sage: L2 Nilpotent Lie algebra on 3 generators (y, x, z) over Rational Field sage: L1 is L2 False Constructed using two different methods from :class:`LieAlgebra` yields the same Lie algebra:: sage: sc = {('X','Y'): {'Z': 1}} sage: C = LieAlgebras(QQ).Nilpotent().FiniteDimensional().WithBasis() sage: L1.<X,Y,Z> = LieAlgebra(QQ, sc, category=C) sage: L2 = LieAlgebra(QQ, sc, nilpotent=True, names=['X','Y','Z']) sage: L1 is L2 True """ if not names: # extract names from structural coefficients names = [] for (X, Y), d in s_coeff.items(): if X not in names: names.append(X) if Y not in names: names.append(Y) for k in d: if k not in names: names.append(k) from sage.structure.indexed_generators import standardize_names_index_set names, index_set = standardize_names_index_set(names, index_set) s_coeff = LieAlgebraWithStructureCoefficients._standardize_s_coeff( s_coeff, index_set) cat = LieAlgebras(R).FiniteDimensional().WithBasis().Nilpotent() category = cat.or_subcategory(category) return super(NilpotentLieAlgebra_dense, cls).__classcall__( cls, R, s_coeff, names, index_set, category=category, **kwds)
def __init__(self, R, ngens=None, gram_matrix=None, names=None, index_set=None): """ Initialize self. TESTS:: sage: V = lie_conformal_algebras.FreeFermions(QQ) sage: TestSuite(V).run() """ from sage.matrix.matrix_space import MatrixSpace from sage.matrix.special import identity_matrix if (gram_matrix is not None): if ngens is None: ngens = gram_matrix.dimensions()[0] try: assert (gram_matrix in MatrixSpace(R,ngens,ngens)) except AssertionError: raise ValueError("The gram_matrix should be a symmetric " + "{0} x {0} matrix, got {1}".format(ngens,gram_matrix)) if not gram_matrix.is_symmetric(): raise ValueError("The gram_matrix should be a symmetric " + "{0} x {0} matrix, got {1}".format(ngens,gram_matrix)) else: if ngens is None: ngens = 1; gram_matrix = identity_matrix(R,ngens,ngens) latex_names=None if (names is None) and (index_set is None): if ngens==1: names = 'psi' else: names = 'psi_' latex_names = tuple(r"\psi_{%d}" % i \ for i in range (ngens)) + ('K',) from sage.structure.indexed_generators import \ standardize_names_index_set names,index_set = standardize_names_index_set(names=names, index_set=index_set, ngens=ngens) fermiondict = { (i,j): {0: {('K',0): gram_matrix[index_set.rank(i), index_set.rank(j)]}} for i in index_set for j in index_set} from sage.rings.rational_field import QQ weights = (QQ(1/2),)*ngens parity = (1,)*ngens GradedLieConformalAlgebra.__init__(self,R,fermiondict,names=names, latex_names=latex_names, index_set=index_set,weights=weights, parity=parity, central_elements=('K',)) self._gram_matrix = gram_matrix
def __classcall_private__(cls, R, names=None, index_set=None): """ Normalize input to ensure a unique representation. EXAMPLES:: sage: from sage.algebras.lie_algebras.free_lie_algebra import FreeLieAlgebra sage: L1 = FreeLieAlgebra(QQ, ['x', 'y', 'z']) sage: L2.<x,y,z> = LieAlgebra(QQ) sage: L1 is L2 True """ names, index_set = standardize_names_index_set(names, index_set) return super(FreeLieAlgebra, cls).__classcall__(cls, R, names, index_set)
def __classcall_private__(cls, R, s_coeff, names=None, index_set=None, **kwds): """ Normalize input to ensure a unique representation. EXAMPLES:: sage: L1 = LieAlgebra(QQ, 'x,y', {('x','y'): {'x':1}}) sage: L2 = LieAlgebra(QQ, 'x,y', {('y','x'): {'x':-1}}) sage: L1 is L2 True Check that we convert names to the indexing set:: sage: L = LieAlgebra(QQ, 'x,y,z', {('x','y'): {'z':1}, ('y','z'): {'x':1}, ('z','x'): {'y':1}}, index_set=list(range(3))) sage: (x,y,z) = L.gens() sage: L[x,y] L[2] """ names, index_set = standardize_names_index_set(names, index_set) # Make sure the structure coefficients are given by the index set if names is not None and names != tuple(index_set): d = {x: index_set[i] for i, x in enumerate(names)} get_pairs = lambda X: X.items() if isinstance(X, dict) else X try: s_coeff = {(d[k[0]], d[k[1]]): [(d[x], y) for x, y in get_pairs(s_coeff[k])] for k in s_coeff} except KeyError: # At this point we assume they are given by the index set pass s_coeff = LieAlgebraWithStructureCoefficients._standardize_s_coeff( s_coeff, index_set) if s_coeff.cardinality() == 0: from sage.algebras.lie_algebras.abelian import AbelianLieAlgebra return AbelianLieAlgebra(R, names, index_set, **kwds) if (names is None and len(index_set) <= 1) or len(names) <= 1: from sage.algebras.lie_algebras.abelian import AbelianLieAlgebra return AbelianLieAlgebra(R, names, index_set, **kwds) return super(LieAlgebraWithStructureCoefficients, cls).__classcall__(cls, R, s_coeff, names, index_set, **kwds)
def __classcall_private__(cls, R, names=None, index_set=None): """ Normalize input to ensure a unique representation. EXAMPLES:: sage: from sage.algebras.lie_algebras.free_lie_algebra import FreeLieAlgebra sage: L1 = FreeLieAlgebra(QQ, ['x', 'y', 'z']) sage: L2.<x,y,z> = LieAlgebra(QQ) sage: L1 is L2 True """ names, index_set = standardize_names_index_set(names, index_set) return super(FreeLieAlgebra, cls).__classcall__(cls, R, names, index_set)
def __init__(self, R, ngens=2, names=None, index_set=None): """ Initialize self. TESTS:: sage: V = lie_conformal_algebras.BosonicGhosts(QQ) sage: TestSuite(V).run() """ try: assert (ngens > 0 and ngens % 2 == 0) except AssertionError: raise ValueError("ngens should be an even positive integer, " + "got {}".format(ngens)) latex_names = None if (names is None) and (index_set is None): from sage.misc.defaults import variable_names as varnames from sage.misc.defaults import latex_variable_names as laxnames names = varnames(ngens / 2, 'b') + varnames(ngens / 2, 'c') latex_names = tuple(laxnames(ngens/2,'b') +\ laxnames(ngens/2,'c')) + ('K',) from sage.structure.indexed_generators import \ standardize_names_index_set names, index_set = standardize_names_index_set(names=names, index_set=index_set, ngens=ngens) from sage.matrix.special import identity_matrix A = identity_matrix(R, ngens / 2) from sage.matrix.special import block_matrix gram_matrix = block_matrix([[R.zero(), A], [A, R.zero()]]) ghostsdict = {(i, j): { 0: { ('K', 0): gram_matrix[index_set.rank(i), index_set.rank(j)] } } for i in index_set for j in index_set} weights = (1, ) * (ngens // 2) + (0, ) * (ngens // 2) parity = (1, ) * ngens super(FermionicGhostsLieConformalAlgebra, self).__init__(R, ghostsdict, names=names, latex_names=latex_names, index_set=index_set, weights=weights, parity=parity, central_elements=('K', ))
def __classcall_private__(cls, R, names=None, index_set=None, category=None, **kwds): """ Normalize input to ensure a unique representation. TESTS:: sage: L1 = LieAlgebra(QQ, 'x,y', {}) sage: L2.<x, y> = LieAlgebra(QQ, abelian=True) sage: L1 is L2 True """ names, index_set = standardize_names_index_set(names, index_set) if index_set.cardinality() == infinity: return InfiniteDimensionalAbelianLieAlgebra(R, index_set, **kwds) return super(AbelianLieAlgebra, cls).__classcall__(cls, R, names, index_set, category=category, **kwds)
def __init__(self, R, ngens=None, gram_matrix=None, names=None, index_set=None): """ Initialize self. TESTS:: sage: V = lie_conformal_algebras.FreeBosons(QQ) sage: TestSuite(V).run() """ from sage.matrix.matrix_space import MatrixSpace if (gram_matrix is not None): if ngens is None: ngens = gram_matrix.dimensions()[0] try: assert (gram_matrix in MatrixSpace(R,ngens,ngens)) except AssertionError: raise ValueError("the gram_matrix should be a symmetric " + "{0} x {0} matrix, got {1}".format(ngens,gram_matrix)) if not gram_matrix.is_symmetric(): raise ValueError("the gram_matrix should be a symmetric " + "{0} x {0} matrix, got {1}".format(ngens,gram_matrix)) else: if ngens is None: ngens = 1; gram_matrix = identity_matrix(R,ngens,ngens) latex_names = None if (names is None) and (index_set is None): names = 'alpha' latex_names = tuple(r'\alpha_{%d}' % i \ for i in range (ngens)) + ('K',) names,index_set = standardize_names_index_set(names=names, index_set=index_set, ngens=ngens) bosondict = { (i,j): {1: {('K',0): gram_matrix[index_set.rank(i), index_set.rank(j)]}} for i in index_set for j in index_set} GradedLieConformalAlgebra.__init__(self,R,bosondict,names=names, latex_names=latex_names, index_set=index_set, central_elements=('K',)) self._gram_matrix = gram_matrix
def __classcall_private__(cls, R, s_coeff, names=None, index_set=None, **kwds): """ Normalize input to ensure a unique representation. EXAMPLES:: sage: L1 = LieAlgebra(QQ, 'x,y', {('x','y'): {'x':1}}) sage: L2 = LieAlgebra(QQ, 'x,y', {('y','x'): {'x':-1}}) sage: L1 is L2 True Check that we convert names to the indexing set:: sage: L = LieAlgebra(QQ, 'x,y,z', {('x','y'): {'z':1}, ('y','z'): {'x':1}, ('z','x'): {'y':1}}, index_set=list(range(3))) sage: (x,y,z) = L.gens() sage: L[x,y] L[2] """ names, index_set = standardize_names_index_set(names, index_set) # Make sure the structure coefficients are given by the index set if names is not None and names != tuple(index_set): d = {x: index_set[i] for i,x in enumerate(names)} get_pairs = lambda X: X.items() if isinstance(X, dict) else X try: s_coeff = {(d[k[0]], d[k[1]]): [(d[x], y) for x,y in get_pairs(s_coeff[k])] for k in s_coeff} except KeyError: # At this point we assume they are given by the index set pass s_coeff = LieAlgebraWithStructureCoefficients._standardize_s_coeff(s_coeff, index_set) if s_coeff.cardinality() == 0: from sage.algebras.lie_algebras.abelian import AbelianLieAlgebra return AbelianLieAlgebra(R, names, index_set, **kwds) if (names is None and len(index_set) <= 1) or len(names) <= 1: from sage.algebras.lie_algebras.abelian import AbelianLieAlgebra return AbelianLieAlgebra(R, names, index_set, **kwds) return super(LieAlgebraWithStructureCoefficients, cls).__classcall__( cls, R, s_coeff, names, index_set, **kwds)
def __classcall_private__(cls, A, gens=None, names=None, index_set=None, free_lie_algebra=False): """ Normalize input to ensure a unique representation. TESTS:: sage: G = SymmetricGroup(3) sage: S = GroupAlgebra(G, QQ) sage: L1 = LieAlgebra(associative=tuple(S.gens()), names=['x','y']) sage: L2 = LieAlgebra(associative=[ S(G((1,2,3))), S(G((1,2))) ], names='x,y') sage: L1 is L2 True sage: F.<x,y,z> = FreeAlgebra(QQ) sage: L1 = LieAlgebra(associative=F.algebra_generators(), names='x,y,z') sage: L2.<x,y,z> = LieAlgebra(associative=F.gens()) sage: L1 is L2 True """ # If A is not a ring, then we treat it as a set of generators if isinstance(A, Parent) and A.category().is_subcategory(Rings()): if gens is None and index_set is None: # Use the indexing set of the basis try: index_set = A.basis().keys() except (AttributeError, NotImplementedError): pass else: gens = A A = None if index_set is None: # See if we can get an index set from the generators try: index_set = gens.keys() except (AttributeError, ValueError): pass ngens = None if isinstance(gens, AbstractFamily): if index_set is None and names is None: index_set = gens.keys() if gens.cardinality() < float('inf'): # TODO: This makes the generators of a finitely generated # Lie algebra into an ordered list for uniqueness and then # reconstructs the family. Instead create a key for the # cache this way and then pass the family. try: gens = tuple([gens[i] for i in index_set]) except KeyError: gens = tuple(gens) ngens = len(gens) elif isinstance(gens, dict): if index_set is None and names is None: index_set = gens.keys() gens = gens.values() ngens = len(gens) elif gens is not None: # Assume it is list-like gens = tuple(gens) ngens = len(gens) if index_set is None and names is None: index_set = list(range(ngens)) if ngens is not None: if A is None: A = gens[0].parent() # Make sure all the generators have the same parent of A gens = tuple([A(g) for g in gens]) names, index_set = standardize_names_index_set(names, index_set, ngens) if isinstance(A, MatrixSpace): if gens is not None: for g in gens: g.set_immutable() return MatrixLieAlgebraFromAssociative(A, gens, names=names, index_set=index_set) return super(LieAlgebraFromAssociative, cls).__classcall__(cls, A, gens, names=names, index_set=index_set)
def __init__(self, R, ngens=None, gram_matrix=None, names=None, index_set=None): """ Initialize self. TESTS:: sage: V = lie_conformal_algebras.Weyl(QQ) sage: TestSuite(V).run() """ from sage.matrix.matrix_space import MatrixSpace if ngens: try: from sage.rings.integer_ring import ZZ assert ngens in ZZ and ngens % 2 == 0 except AssertionError: raise ValueError("ngens needs to be an even positive " + "Integer, got {}".format(ngens)) if (gram_matrix is not None): if ngens is None: ngens = gram_matrix.dimensions()[0] try: assert (gram_matrix in MatrixSpace(R, ngens, ngens)) except AssertionError: raise ValueError( "The gram_matrix should be a skew-symmetric " + "{0} x {0} matrix, got {1}".format(ngens, gram_matrix)) if (not gram_matrix.is_skew_symmetric()) or \ (gram_matrix.is_singular()): raise ValueError("The gram_matrix should be a non degenerate " + "skew-symmetric {0} x {0} matrix, got {1}"\ .format(ngens,gram_matrix)) elif (gram_matrix is None): if ngens is None: ngens = 2 A = identity_matrix(R, ngens // 2) from sage.matrix.special import block_matrix gram_matrix = block_matrix([[R.zero(), A], [-A, R.zero()]]) latex_names = None if (names is None) and (index_set is None): names = 'alpha' latex_names = tuple(r'\alpha_{%d}' % i \ for i in range (ngens)) + ('K',) names, index_set = standardize_names_index_set(names=names, index_set=index_set, ngens=ngens) weyldict = {(i, j): { 0: { ('K', 0): gram_matrix[index_set.rank(i), index_set.rank(j)] } } for i in index_set for j in index_set} super(WeylLieConformalAlgebra, self).__init__(R, weyldict, names=names, latex_names=latex_names, index_set=index_set, central_elements=('K', )) self._gram_matrix = gram_matrix
def __classcall_private__(cls, R, s_coeff, names=None, index_set=None, category=None, **kwds): """ Normalize input to ensure a unique representation. EXAMPLES: If the variable order is specified, the order of structural coefficients does not matter:: sage: from sage.algebras.lie_algebras.nilpotent_lie_algebra import NilpotentLieAlgebra_dense sage: L1.<x,y,z> = NilpotentLieAlgebra_dense(QQ, {('x','y'): {'z': 1}}) sage: L2.<x,y,z> = NilpotentLieAlgebra_dense(QQ, {('y','x'): {'z': -1}}) sage: L1 is L2 True If the variables are implicitly defined by the structural coefficients, the ordering may be different and the Lie algebras will be considered different:: sage: from sage.algebras.lie_algebras.nilpotent_lie_algebra import NilpotentLieAlgebra_dense sage: L1 = NilpotentLieAlgebra_dense(QQ, {('x','y'): {'z': 1}}) sage: L2 = NilpotentLieAlgebra_dense(QQ, {('y','x'): {'z': -1}}) sage: L1 Nilpotent Lie algebra on 3 generators (x, y, z) over Rational Field sage: L2 Nilpotent Lie algebra on 3 generators (y, x, z) over Rational Field sage: L1 is L2 False Constructed using two different methods from :class:`LieAlgebra` yields the same Lie algebra:: sage: sc = {('X','Y'): {'Z': 1}} sage: C = LieAlgebras(QQ).Nilpotent().FiniteDimensional().WithBasis() sage: L1.<X,Y,Z> = LieAlgebra(QQ, sc, category=C) sage: L2 = LieAlgebra(QQ, sc, nilpotent=True, names=['X','Y','Z']) sage: L1 is L2 True """ if not names: # extract names from structural coefficients names = [] for (X, Y), d in s_coeff.items(): if X not in names: names.append(X) if Y not in names: names.append(Y) for k in d: if k not in names: names.append(k) from sage.structure.indexed_generators import standardize_names_index_set names, index_set = standardize_names_index_set(names, index_set) s_coeff = LieAlgebraWithStructureCoefficients._standardize_s_coeff( s_coeff, index_set) cat = LieAlgebras(R).FiniteDimensional().WithBasis().Nilpotent() category = cat.or_subcategory(category) return super(NilpotentLieAlgebra_dense, cls).__classcall__(cls, R, s_coeff, names, index_set, category=category, **kwds)
def __init__(self, R, r, s, names, naming, category, **kwds): r""" Initialize ``self`` EXAMPLES:: sage: L = LieAlgebra(ZZ, 2, step=2) sage: TestSuite(L).run() sage: L = LieAlgebra(QQ, 4, step=3) sage: TestSuite(L).run() # long time """ if r not in ZZ or r <= 0: raise ValueError("number of generators %s is not " "a positive integer" % r) if s not in ZZ or s <= 0: raise ValueError("step %s is not a positive integer" % s) # extract an index set from the Lyndon words of the corresponding # free Lie algebra, and store the corresponding elements in a dict from sage.algebras.lie_algebras.lie_algebra import LieAlgebra free_gen_names = ['F%d' % k for k in range(r)] free_gen_names_inv = { val: i + 1 for i, val in enumerate(free_gen_names) } L = LieAlgebra(R, free_gen_names).Lyndon() basis_by_deg = {d: [] for d in range(1, s + 1)} for d in range(1, s + 1): for X in L.graded_basis(d): # convert brackets of form [X_1, [X_1, X_2]] to words (1,1,2) w = tuple(free_gen_names_inv[s] for s in X.leading_support().to_word()) basis_by_deg[d].append((w, X)) index_set = [ind for d in basis_by_deg for ind, val in basis_by_deg[d]] if len(names) == 1 and len(index_set) > 1: if not naming: if r >= 10: naming = 'linear' else: naming = 'index' if naming == 'linear': names = [ '%s_%d' % (names[0], k + 1) for k in range(len(index_set)) ] elif naming == 'index': if r >= 10: raise ValueError("'index' naming scheme not supported for " "10 or more generators") names = [ '%s_%s' % (names[0], "".join(str(s) for s in ind)) for ind in index_set ] else: raise ValueError("unknown naming scheme %s" % naming) # extract structural coefficients from the free Lie algebra s_coeff = {} for dx in range(1, s + 1): # Brackets are only computed when deg(X) + deg(Y) <= s # We also require deg(Y) >= deg(X) by the ordering for dy in range(dx, s + 1 - dx): if dx == dy: for i, val in enumerate(basis_by_deg[dx]): X_ind, X = val for Y_ind, Y in basis_by_deg[dy][i + 1:]: Z = L[X, Y] if not Z.is_zero(): s_coeff[(X_ind, Y_ind)] = { W_ind: Z[W.leading_support()] for W_ind, W in basis_by_deg[dx + dy] } else: for X_ind, X in basis_by_deg[dx]: for Y_ind, Y in basis_by_deg[dy]: Z = L[X, Y] if not Z.is_zero(): s_coeff[(X_ind, Y_ind)] = { W_ind: Z[W.leading_support()] for W_ind, W in basis_by_deg[dx + dy] } names, index_set = standardize_names_index_set(names, index_set) s_coeff = LieAlgebraWithStructureCoefficients._standardize_s_coeff( s_coeff, index_set) NilpotentLieAlgebra_dense.__init__(self, R, s_coeff, names, index_set, s, category=category, **kwds)
def __init__(self, R, r, s, names, naming, category, **kwds): r""" Initialize ``self`` EXAMPLES:: sage: L = LieAlgebra(ZZ, 2, step=2) sage: TestSuite(L).run() sage: L = LieAlgebra(QQ, 4, step=3) sage: TestSuite(L).run() # long time """ if r not in ZZ or r <= 0: raise ValueError("number of generators %s is not " "a positive integer" % r) if s not in ZZ or s <= 0: raise ValueError("step %s is not a positive integer" % s) # extract an index set from the Lyndon words of the corresponding # free Lie algebra, and store the corresponding elements in a dict from sage.algebras.lie_algebras.lie_algebra import LieAlgebra free_gen_names = ['F%d' % k for k in range(r)] free_gen_names_inv = {val: i + 1 for i, val in enumerate(free_gen_names)} L = LieAlgebra(R, free_gen_names).Lyndon() basis_by_deg = {d: [] for d in range(1, s + 1)} for d in range(1, s + 1): for X in L.graded_basis(d): # convert brackets of form [X_1, [X_1, X_2]] to words (1,1,2) w = tuple(free_gen_names_inv[s] for s in X.leading_support().to_word()) basis_by_deg[d].append((w, X)) index_set = [ind for d in basis_by_deg for ind, val in basis_by_deg[d]] if len(names) == 1 and len(index_set) > 1: if not naming: if r >= 10: naming = 'linear' else: naming = 'index' if naming == 'linear': names = ['%s_%d' % (names[0], k + 1) for k in range(len(index_set))] elif naming == 'index': if r >= 10: raise ValueError("'index' naming scheme not supported for " "10 or more generators") names = ['%s_%s' % (names[0], "".join(str(s) for s in w)) for w in index_set] else: raise ValueError("unknown naming scheme %s" % naming) # extract structural coefficients from the free Lie algebra s_coeff = {} for dx in range(1, s + 1): # Brackets are only computed when deg(X) + deg(Y) <= s # We also require deg(Y) >= deg(X) by the ordering for dy in range(dx, s + 1 - dx): if dx == dy: for i, val in enumerate(basis_by_deg[dx]): X_ind, X = val for Y_ind, Y in basis_by_deg[dy][i + 1:]: Z = L[X, Y] if not Z.is_zero(): s_coeff[(X_ind, Y_ind)] = {W_ind: Z[W.leading_support()] for W_ind, W in basis_by_deg[dx + dy]} else: for X_ind, X in basis_by_deg[dx]: for Y_ind, Y in basis_by_deg[dy]: Z = L[X, Y] if not Z.is_zero(): s_coeff[(X_ind, Y_ind)] = {W_ind: Z[W.leading_support()] for W_ind, W in basis_by_deg[dx + dy]} names, index_set = standardize_names_index_set(names, index_set) s_coeff = LieAlgebraWithStructureCoefficients._standardize_s_coeff( s_coeff, index_set) NilpotentLieAlgebra_dense.__init__(self, R, s_coeff, names, index_set, s, category=category, **kwds)
def __classcall_private__(cls, I, ambient=None, names=None, index_set=None, category=None): r""" Normalize input to ensure a unique representation. EXAMPLES: Specifying the ambient Lie algebra is not necessary:: sage: from sage.algebras.lie_algebras.quotient import LieQuotient_finite_dimensional_with_basis sage: L.<X,Y> = LieAlgebra(QQ, {('X','Y'): {'X': 1}}) sage: Q1 = LieQuotient_finite_dimensional_with_basis(X, ambient=L) sage: Q2 = LieQuotient_finite_dimensional_with_basis(X) sage: Q1 is Q2 True Variable names are extracted from the ambient Lie algebra by default:: sage: Q3 = L.quotient(X, names=['Y']) sage: Q1 is Q3 True """ if not isinstance(I, LieSubalgebra_finite_dimensional_with_basis): # assume I is an element or list of elements of some lie algebra if ambient is None: if not isinstance(I, (list, tuple)): ambient = I.parent() else: ambient = I[0].parent() I = ambient.ideal(I) if ambient is None: ambient = I.ambient() if not ambient.base_ring().is_field(): raise NotImplementedError("quotients over non-fields " "not implemented") # extract an index set from a complementary basis to the ideal I_supp = [X.leading_support() for X in I.leading_monomials()] inv = ambient.basis().inverse_family() sorted_indices = [inv[X] for X in ambient.basis()] index_set = [i for i in sorted_indices if i not in I_supp] if names is None: amb_names = dict(zip(sorted_indices, ambient.variable_names())) names = [amb_names[i] for i in index_set] elif isinstance(names, str): if len(index_set) == 1: names = [names] else: names = [ '%s_%d' % (names, k + 1) for k in range(len(index_set)) ] names, index_set = standardize_names_index_set(names, index_set) cat = LieAlgebras(ambient.base_ring()).FiniteDimensional().WithBasis() if ambient in LieAlgebras(ambient.base_ring()).Nilpotent(): cat = cat.Nilpotent() category = cat.Subquotients().or_subcategory(category) sup = super(LieQuotient_finite_dimensional_with_basis, cls) return sup.__classcall__(cls, I, ambient, names, index_set, category=category)
def __classcall_private__(cls, A, gens=None, names=None, index_set=None, free_lie_algebra=False): """ Normalize input to ensure a unique representation. TESTS:: sage: G = SymmetricGroup(3) sage: S = GroupAlgebra(G, QQ) sage: L1 = LieAlgebra(associative=tuple(S.gens()), names=['x','y']) sage: L2 = LieAlgebra(associative=[ S(G((1,2,3))), S(G((1,2))) ], names='x,y') sage: L1 is L2 True sage: F.<x,y,z> = FreeAlgebra(QQ) sage: L1 = LieAlgebra(associative=F.algebra_generators(), names='x,y,z') sage: L2.<x,y,z> = LieAlgebra(associative=F.gens()) sage: L1 is L2 True """ # If A is not a ring, then we treat it as a set of generators if isinstance(A, Parent) and A.category().is_subcategory(Rings()): if gens is None and index_set is None: # Use the indexing set of the basis try: index_set = A.basis().keys() except (AttributeError, NotImplementedError): pass else: gens = A A = None if index_set is None: # See if we can get an index set from the generators try: index_set = gens.keys() except (AttributeError, ValueError): pass ngens = None if isinstance(gens, AbstractFamily): if index_set is None and names is None: index_set = gens.keys() if gens.cardinality() < float('inf'): # TODO: This makes the generators of a finitely generated # Lie algebra into an ordered list for uniqueness and then # reconstructs the family. Instead create a key for the # cache this way and then pass the family. try: gens = tuple([gens[i] for i in index_set]) except KeyError: gens = tuple(gens) ngens = len(gens) elif isinstance(gens, dict): if index_set is None and names is None: index_set = gens.keys() gens = gens.values() ngens = len(gens) elif gens is not None: # Assume it is list-like gens = tuple(gens) ngens = len(gens) if index_set is None and names is None: index_set = list(range(ngens)) if ngens is not None: if A is None: A = gens[0].parent() # Make sure all the generators have the same parent of A gens = tuple([A(g) for g in gens]) names, index_set = standardize_names_index_set(names, index_set, ngens) if isinstance(A, MatrixSpace): if gens is not None: for g in gens: g.set_immutable() return MatrixLieAlgebraFromAssociative(A, gens, names=names, index_set=index_set) return super(LieAlgebraFromAssociative, cls).__classcall__(cls, A, gens, names=names, index_set=index_set)
def __init__(self, R, s_coeff, index_set=None, central_elements=None, category=None, element_class=None, prefix=None, names=None, latex_names=None, parity=None, **kwds): """ Initialize self. TESTS:: sage: V = lie_conformal_algebras.NeveuSchwarz(QQ) sage: TestSuite(V).run() """ names, index_set = standardize_names_index_set(names, index_set) if central_elements is None: central_elements = tuple() if names is not None and names != tuple(index_set): names2 = names + tuple(central_elements) index_set2 = DisjointUnionEnumeratedSets( (index_set, Family(tuple(central_elements)))) d = {x: index_set2[i] for i, x in enumerate(names2)} try: #If we are given a dictionary with names as keys, #convert to index_set as keys s_coeff = {(d[k[0]], d[k[1]]): { a: {(d[x[1]], x[2]): s_coeff[k][a][x] for x in s_coeff[k][a]} for a in s_coeff[k] } for k in s_coeff.keys()} except KeyError: # We assume the dictionary was given with keys in the # index_set pass issuper = kwds.pop('super', False) if parity is None: parity = (0, ) * index_set.cardinality() else: issuper = True try: assert len(parity) == index_set.cardinality() except AssertionError: raise ValueError("parity should have the same length as the "\ "number of generators, got {}".format(parity)) s_coeff = LieConformalAlgebraWithStructureCoefficients\ ._standardize_s_coeff(s_coeff, index_set, central_elements, parity) if names is not None and central_elements is not None: names += tuple(central_elements) self._index_to_pos = {k: i for i, k in enumerate(index_set)} #Add central parameters to index_to_pos so that we can #represent names if central_elements is not None: for i, ce in enumerate(central_elements): self._index_to_pos[ce] = len(index_set) + i default_category = LieConformalAlgebras( R).WithBasis().FinitelyGenerated() if issuper: category = default_category.Super().or_subcategory(category) else: category = default_category.or_subcategory(category) if element_class is None: element_class = LCAStructureCoefficientsElement FinitelyFreelyGeneratedLCA.__init__(self, R, index_set=index_set, central_elements=central_elements, category=category, element_class=element_class, prefix=prefix, names=names, latex_names=latex_names, **kwds) s_coeff = dict(s_coeff) self._s_coeff = Family({ k: tuple((j, sum(c * self.monomial(i) for i, c in v)) for j, v in s_coeff[k]) for k in s_coeff }) self._parity = dict( zip(self.gens(), parity + (0, ) * len(central_elements)))
def __classcall_private__(cls, I, ambient=None, names=None, index_set=None, category=None): r""" Normalize input to ensure a unique representation. EXAMPLES: Specifying the ambient Lie algebra is not necessary:: sage: from sage.algebras.lie_algebras.quotient import LieQuotient_finite_dimensional_with_basis sage: L.<X,Y> = LieAlgebra(QQ, {('X','Y'): {'X': 1}}) sage: Q1 = LieQuotient_finite_dimensional_with_basis(X, ambient=L) sage: Q2 = LieQuotient_finite_dimensional_with_basis(X) sage: Q1 is Q2 True Variable names are extracted from the ambient Lie algebra by default:: sage: Q3 = L.quotient(X, names=['Y']) sage: Q1 is Q3 True """ if not isinstance(I, LieSubalgebra_finite_dimensional_with_basis): # assume I is an element or list of elements of some lie algebra if ambient is None: if not isinstance(I, (list, tuple)): ambient = I.parent() else: ambient = I[0].parent() I = ambient.ideal(I) if ambient is None: ambient = I.ambient() if not ambient.base_ring().is_field(): raise NotImplementedError("quotients over non-fields " "not implemented") # extract an index set from a complementary basis to the ideal I_supp = [X.leading_support() for X in I.leading_monomials()] inv = ambient.basis().inverse_family() sorted_indices = [inv[X] for X in ambient.basis()] index_set = [i for i in sorted_indices if i not in I_supp] if names is None: amb_names = dict(zip(sorted_indices, ambient.variable_names())) names = [amb_names[i] for i in index_set] elif isinstance(names, str): if len(index_set) == 1: names = [names] else: names = ['%s_%d' % (names, k + 1) for k in range(len(index_set))] names, index_set = standardize_names_index_set(names, index_set) cat = LieAlgebras(ambient.base_ring()).FiniteDimensional().WithBasis() if ambient in LieAlgebras(ambient.base_ring()).Nilpotent(): cat = cat.Nilpotent() category = cat.Subquotients().or_subcategory(category) sup = super(LieQuotient_finite_dimensional_with_basis, cls) return sup.__classcall__(cls, I, ambient, names, index_set, category=category)