def __init__(self, base_ring, even_coordinates=None, names='xi', simplify=None, is_zero='is_zero'): """ Initialize this superfunction algebra. INPUT: - ``base_ring`` -- a commutative ring, considered as a ring of (even, degree 0) functions - ``even_coordinates`` -- (default: ``None``) a list or tuple of elements of ``base_ring``; if none is provided, then it is set to ``base_ring.gens()`` - ``names`` -- (default: ``'xi'``) a list or tuple of strings or a comma separated string, consisting of names for the odd coordinates; or a single string consisting of a prefix that will be used to generate a list of numbered names - ``simplify`` -- (default: ``None``) a string, containing the name of a method of an element of the base ring; that method should return a simplification of the element (will be used in each operation on elements that affects coefficients), or ``None`` (which amounts to no simplification). - ``is_zero`` -- (default: ``'is_zero'``) a string, containing the name of a method of an element of the base ring; that method should return ``True`` when a simplified element of the base ring is equal to zero (will be used to decide equality of elements, to calculate the degree of elements, and to skip terms in some operations on elements) """ self.element_class = Superfunction self._base_ring = base_ring if even_coordinates: self._even_coordinates = even_coordinates elif hasattr(base_ring, 'gens'): self._even_coordinates = base_ring.gens() else: raise ValueError('Even coordinates not specified and could not be determined from base ring') if isinstance(names, str): if ',' in names: names = names.split(',') else: names = ['{}{}'.format(names, k) for k in range(len(self._even_coordinates))] elif not isinstance(names, Iterable) or not all(isinstance(name, str) for name in names): raise ValueError('Format of odd coordinate names {} not recognized'.format(names)) if len(names) != len(self._even_coordinates): raise ValueError("Number of odd coordinate names in {} does not match number of even coordinates".format(names)) self._names = tuple(names) self.__ngens = len(names) self._gens = tuple(self.element_class(self, {1 : [self._base_ring.one() if j == k else self._base_ring.zero() for j in range(self.__ngens)]}) for k in range(self.__ngens)) self._basis = keydefaultdict(partial(list_combinations, self.__ngens)) if simplify is None: self._simplify = identity else: if not isinstance(simplify, str): raise ValueError('simplify must be a string (the name of a method of an element of the base ring)') self._simplify = partial(call_method, simplify) if not isinstance(is_zero, str): raise ValueError('is_zero must be a string (the name of a method of an element of the base ring)') self._is_zero = partial(call_method, is_zero) self._tensor_powers = keydefaultdict(partial(tensor_power, self)) self._schouten_bracket = SuperfunctionAlgebraSchoutenBracket(self._tensor_powers[2], self)
def __init__(self, base_ring, vector_constructor, matrix_constructor, connected=None, biconnected=None, min_degree=0, loops=True): """ Initialize this graph complex. """ if vector_constructor is None: raise ValueError('vector_constructor is required') if matrix_constructor is None: raise ValueError('matrix_constructor is required') graph_basis = DirectedGraphComplexBasis(connected=connected, biconnected=biconnected, min_degree=min_degree, loops=loops) super().__init__(base_ring, graph_basis, vector_constructor, matrix_constructor) self.element_class = DirectedGraphCochain_vector # TODO: load differentials from files self._differentials = keydefaultdict( partial(__class__._differential_matrix, self))
def __init__(self, base_ring, vector_constructor, matrix_constructor, connected=None, biconnected=None, min_degree=0): """ Initialize this graph complex. INPUT: - ``base_ring`` -- a ring, to be used as the ring of coefficients - ``graph_basis`` -- a GraphBasis - ``vector_constructor`` -- constructor of (sparse) vectors - ``matrix_constructor`` -- constructor of (sparse) matrices """ if vector_constructor is None: raise ValueError('vector_constructor is required') if matrix_constructor is None: raise ValueError('matrix_constructor is required') graph_basis = UndirectedGraphComplexBasis(connected=connected, biconnected=biconnected, min_degree=min_degree) super().__init__(base_ring, graph_basis, vector_constructor, matrix_constructor) self.element_class = UndirectedGraphCochain_vector # TODO: load differentials from files self._differentials = keydefaultdict( partial(__class__._differential_matrix, self))
def __init__(self, positive_differential_order=None): """ Initialize this basis. """ self._positive_differential_order = positive_differential_order self._graphs = keydefaultdict( partial(formality_graph_cache.graphs, positive_differential_order=positive_differential_order, has_odd_automorphism=False))
def map_coefficients(self, f, new_parent=None): """ Apply ``f`` to each of this superfunction's coefficients and return the resulting superfunction. """ if new_parent is None: new_parent = self._parent monomial_coefficients = keydefaultdict(partial(zero_vector, new_parent)) for degree in self._monomial_coefficients: for k in range(len(self._monomial_coefficients[degree])): monomial_coefficients[degree][k] = new_parent._simplify(f(self._monomial_coefficients[degree][k])) return self.__class__(new_parent, monomial_coefficients)
def derivative(self, *args): """ Return the derivative of this superfunction with respect to ``args``. INPUT: - ``args`` -- an odd coordinate or an even coordinate, or a list of such """ if len(args) > 1: result = self for arg in args: result = result.derivative(arg) return result elif len(args) == 1 and any(args[0] is xi for xi in self._parent.gens()): j = self._parent.gens().index(args[0]) monomial_coefficients = keydefaultdict(partial(zero_vector, self._parent)) for degree in self._monomial_coefficients: for k in range(len(self._monomial_coefficients[degree])): derivative, sign = self._parent._derivative_on_basis(degree, k, j) if derivative is not None: monomial_coefficients[degree-1][derivative] = self._parent._simplify(sign * self._monomial_coefficients[degree][k]) return self.__class__(self._parent, monomial_coefficients) elif len(args) == 1 and any(args[0] is x for x in self._parent.even_coordinates()): monomial_coefficients = keydefaultdict(partial(zero_vector, self._parent)) for degree in self._monomial_coefficients: for k in range(len(self._monomial_coefficients[degree])): monomial_coefficients[degree][k] = self._parent._simplify(self._monomial_coefficients[degree][k].derivative(args[0])) return self.__class__(self._parent, monomial_coefficients) elif len(args) == 1: # by now we know args[0] is not identically a coordinate, but maybe it is equal to one: try: actual_xi_idx = self._parent.gens().index(args[0]) return self.derivative(self._parent.gen(actual_xi_idx)) except ValueError: try: actual_x_idx = self._parent.even_coordinates().index(args[0]) return self.derivative(self._parent.even_coordinate(actual_x_idx)) except ValueError: raise ValueError("{} not recognized as a coordinate".format(args[0])) else: raise ValueError("Don't know how to take derivative with respect to {}".format(args))
def __init__(self, connected=None, biconnected=None, min_degree=0): """ Initialize this basis. """ if not min_degree in [0, 3]: raise ValueError('min_degree can only be 0 or 3') self._connected = connected self._biconnected = biconnected self._min_degree = min_degree self._graphs = keydefaultdict( partial(undirected_graph_cache.graphs, connected=connected, biconnected=biconnected, min_degree=min_degree, has_odd_automorphism=False))
def __init__(self, parent, vectors): """ Initialize this graph vector. INPUT: - ``parent`` -- a GraphModule - ``vectors`` -- a dictionary, mapping gradings to sparse vectors of coefficients with respect to the basis of ``parent`` """ if not isinstance(parent, GraphModule_vector): raise ValueError("parent must be a GraphModule_vector") self._parent = parent self._vectors = keydefaultdict(partial(zero_vector, self._parent)) for grading in vectors: self._vectors[grading] = vectors[grading]
def __sub__(self, other): """ Return this superfunction minus ``other``. """ monomial_coefficients = keydefaultdict(partial(zero_vector, self._parent)) for degree in self._monomial_coefficients: for k in range(len(self._monomial_coefficients[degree])): monomial_coefficients[degree][k] = self._monomial_coefficients[degree][k] if isinstance(other, self.__class__): for degree in other._monomial_coefficients: for k in range(len(other._monomial_coefficients[degree])): monomial_coefficients[degree][k] = self._parent._simplify(monomial_coefficients[degree][k] - other._monomial_coefficients[degree][k]) elif other in self._parent.base_ring(): monomial_coefficients[0][0] -= other else: return NotImplemented return self.__class__(self._parent, monomial_coefficients)
def __init__(self, parent, monomial_coefficients): """ Initialize this superfunction. INPUT: - ``parent`` - a SuperfunctionAlgebra (which has an ordered basis of monomials in the odd coordinates) - ``monomial_coefficients`` - a dictionary, taking a natural number ``d`` to a list of coefficients of the monomials of degree ``d`` in the ordered basis of ``parent`` """ if not isinstance(parent, SuperfunctionAlgebra): raise TypeError('parent must be a SuperfunctionAlgebra') self._parent = parent if not isinstance(monomial_coefficients, MutableMapping): raise TypeError('monomial_coefficients must be a dictionary') self._monomial_coefficients = keydefaultdict(partial(zero_vector, self._parent)) for degree in monomial_coefficients: self._monomial_coefficients[degree] = monomial_coefficients[degree] for k in range(len(self._monomial_coefficients[degree])): self._monomial_coefficients[degree][k] = self._parent.base_ring()(self._monomial_coefficients[degree][k]) # conversion
def __mul__(self, other): """ Return this superfunction multiplied by ``other``. """ monomial_coefficients = keydefaultdict(partial(zero_vector, self._parent)) if isinstance(other, self.__class__): for degree1 in self._monomial_coefficients: for k1 in range(len(self._monomial_coefficients[degree1])): if self._parent._is_zero(self._monomial_coefficients[degree1][k1]): continue for degree2 in other._monomial_coefficients: for k2 in range(len(other._monomial_coefficients[degree2])): if self._parent._is_zero(other._monomial_coefficients[degree2][k2]): continue prod, sign = self._parent._mul_on_basis(degree1,k1,degree2,k2) if prod is not None: monomial_coefficients[degree1+degree2][prod] = self._parent._simplify(monomial_coefficients[degree1+degree2][prod] + sign * self._monomial_coefficients[degree1][k1] * other._monomial_coefficients[degree2][k2]) elif other in self._parent.base_ring(): for degree in self._monomial_coefficients: for k in range(len(self._monomial_coefficients[degree])): monomial_coefficients[degree][k] = self._parent._simplify(self._monomial_coefficients[degree][k] * other) else: return NotImplemented return self.__class__(self._parent, monomial_coefficients)
def __init__(self): """ Initialize this basis. """ self._graphs = keydefaultdict( partial(undirected_graph_cache.graphs, has_odd_automorphism=False))