def _generate_hall_set(self, k): """ Generate the Hall set of grade ``k``. OUTPUT: A sorted tuple of :class:`GradedLieBracket` elements. EXAMPLES:: sage: L = LieAlgebra(QQ, 3, 'x') sage: H = L.Hall() sage: H._generate_hall_set(3) ([x0, [x0, x1]], [x0, [x0, x2]], [x1, [x0, x1]], [x1, [x0, x2]], [x1, [x1, x2]], [x2, [x0, x1]], [x2, [x0, x2]], [x2, [x1, x2]]) """ if k <= 0: return () if k == 1: return tuple(map(LieGenerator, self.variable_names())) if k == 2: basis = self._generate_hall_set(1) ret = [] for i,a in enumerate(basis): for b in basis[i+1:]: ret.append( GradedLieBracket(a, b, 2) ) return tuple(ret) # We don't want to do the middle when we're even, so we add 1 and # take the floor after dividing by 2. ret = [GradedLieBracket(a, b, k) for i in range(1, (k+1) // 2) for a in self._generate_hall_set(i) for b in self._generate_hall_set(k-i) if b._left <= a] # Special case for when k = 4, we get the pairs [[a, b], [x, y]] # where a,b,x,y are all grade 1 elements. Thus if we take # [a, b] < [x, y], we will always be in the Hall set. if k == 4: basis = self._generate_hall_set(2) for i,a in enumerate(basis): for b in basis[i+1:]: ret.append(GradedLieBracket(a, b, k)) # Do the middle case when we are even and k > 4 elif k % 2 == 0: basis = self._generate_hall_set(k // 2) # grade >= 2 for i,a in enumerate(basis): for b in basis[i+1:]: if b._left <= a: ret.append(GradedLieBracket(a, b, k)) # We sort the returned tuple in order to make computing the higher # graded parts of the Hall set easier. return tuple(sorted(ret))
def _rewrite_bracket(self, l, r): """ Rewrite the bracket ``[l, r]`` in terms of the Hall basis. INPUT: - ``l``, ``r`` -- two keys of the Hall basis with ``l < r`` OUTPUT: A dictionary ``{b: c}`` where ``b`` is a Hall basis key and ``c`` is the corresponding coefficient. EXAMPLES:: sage: L = LieAlgebra(QQ, 'x,y,z') sage: H = L.Hall() sage: x,y,z = H.gens() sage: H([x, [y, [z, x]]]) # indirect doctest -[y, [x, [x, z]]] - [[x, y], [x, z]] """ # NOTE: If r is not a graded Lie bracket, then l cannot be a # graded Lie bracket by the order respecting the grading if not isinstance(r, GradedLieBracket) or r._left <= l: # Compute the grade of the new element grade = 0 # If not a graded Lie bracket, it must be a generator so the grade is 1 if isinstance(l, GradedLieBracket): grade += l._grade else: grade += 1 if isinstance(r, GradedLieBracket): grade += r._grade else: grade += 1 return {GradedLieBracket(l, r, grade): self.base_ring().one()} ret = {} # Rewrite [a, [b, c]] = [b, [a, c]] + [[a, b], c] with a < b < c # Compute the left summand for m, inner_coeff in self._rewrite_bracket(l, r._right).items(): if r._left == m: continue elif r._left < m: x, y = r._left, m else: # r._left > m x, y = m, r._left inner_coeff = -inner_coeff for b_elt, coeff in self._rewrite_bracket(x, y).items(): ret[b_elt] = ret.get(b_elt, 0) + coeff * inner_coeff # Compute the right summand for m, inner_coeff in self._rewrite_bracket(l, r._left).items(): if m == r._right: continue elif m < r._right: x, y = m, r._right else: # m > r._right x, y = r._right, m inner_coeff = -inner_coeff for b_elt, coeff in self._rewrite_bracket(x, y).items(): ret[b_elt] = ret.get(b_elt, 0) + coeff * inner_coeff return ret