def __call__(self, x, orientation=False): """ Input is a simplex of the domain. Output is the image simplex. If optional argument ``orientation`` is True, return a pair ``(image simplex, oriented)`` where ``oriented`` is 1 or `-1` depending on whether the map preserves or reverses the orientation of the image simplex. EXAMPLES:: sage: S = simplicial_complexes.Sphere(2) sage: T = simplicial_complexes.Sphere(3) sage: S Simplicial complex with vertex set (0, 1, 2, 3) and facets {(0, 2, 3), (0, 1, 2), (1, 2, 3), (0, 1, 3)} sage: T Simplicial complex with vertex set (0, 1, 2, 3, 4) and 5 facets sage: f = {0:0,1:1,2:2,3:3} sage: H = Hom(S,T) sage: x = H(f) sage: from sage.homology.simplicial_complex import Simplex sage: x(Simplex([0,2,3])) (0, 2, 3) An orientation-reversing example:: sage: X = SimplicialComplex(1, [[0,1]]) sage: g = Hom(X,X)({0:1, 1:0}) sage: g(Simplex([0,1])) (0, 1) sage: g(Simplex([0,1]), orientation=True) ((0, 1), -1) """ dim = self._domain.dimension() if not isinstance(x, simplicial_complex.Simplex) or x.dimension( ) > dim or not x in self._domain.faces()[x.dimension()]: raise ValueError, "x must be a simplex of the source of f" tup = x.tuple() fx = [] for j in tup: fx.append(self._vertex_dictionary[j]) if orientation: if len(set(fx)) == len(tup): oriented = Permutation(convert_perm(fx)).signature() else: oriented = 1 return (simplicial_complex.Simplex(set(fx)), oriented) else: return simplicial_complex.Simplex(set(fx))
def fiber_product(self, other, rename_vertices=True): """ Fiber product of ``self`` and ``other``. Both morphisms should have the same codomain. The method returns a morphism of simplicial complexes, which is the morphism from the space of the fiber product to the codomain. EXAMPLES:: sage: S = SimplicialComplex([[0,1],[1,2]], is_mutable=False) sage: T = SimplicialComplex([[0,2],[1]], is_mutable=False) sage: U = SimplicialComplex([[0,1],[2]], is_mutable=False) sage: H = Hom(S,U) sage: G = Hom(T,U) sage: f = {0:0,1:1,2:0} sage: g = {0:0,1:1,2:1} sage: x = H(f) sage: y = G(g) sage: z = x.fiber_product(y) sage: z Simplicial complex morphism {'L1R2': 1, 'L1R1': 1, 'L2R0': 0, 'L0R0': 0} from Simplicial complex with 4 vertices and facets {('L2R0',), ('L1R1',), ('L0R0', 'L1R2')} to Simplicial complex with vertex set (0, 1, 2) and facets {(2,), (0, 1)} """ if self._codomain != other._codomain: raise ValueError("self and other must have the same codomain.") X = self._domain.product(other._domain, rename_vertices=rename_vertices) v = [] f = dict() eff1 = self._domain._vertex_set eff2 = other._domain._vertex_set for i in eff1: for j in eff2: if self(simplicial_complex.Simplex([i])) == other( simplicial_complex.Simplex([j])): if rename_vertices: v.append("L" + str(i) + "R" + str(j)) f["L" + str(i) + "R" + str(j)] = self._vertex_dictionary[i] else: v.append((i, j)) f[(i, j)] = self._vertex_dictionary[i] return SimplicialComplexMorphism(f, X.generated_subcomplex(v), self._codomain)
def __init__(self, f, X, Y): """ Input is a dictionary f, the domain, and the codomain. One can define the dictionary either on the vertices of X or on the effective vertices of X (X.effective_vertices()). Note that this difference does matter. For instance, it changes the result of the image method, and hence it changes the result of the is_surjective method as well. This is because two SimplicialComplexes with the same faces but different vertex sets are not equal. EXAMPLES:: sage: S = SimplicialComplex(5,[[0,1],[3,4]]) sage: H = Hom(S,S) sage: f = {0:0,1:1,2:2,3:3,4:4,5:5} sage: g = {0:0,1:1,3:3,4:4} sage: x = H(f) sage: y = H(g) sage: x==y False sage: x.image() Simplicial complex with vertex set (0, 1, 2, 3, 4, 5) and facets {(3, 4), (0, 1)} sage: y.image() Simplicial complex with vertex set (0, 1, 3, 4) and facets {(3, 4), (0, 1)} sage: x.image()==y.image() False """ if not isinstance( X, simplicial_complex.SimplicialComplex) or not isinstance( Y, simplicial_complex.SimplicialComplex): raise ValueError, "X and Y must be SimplicialComplexes." if not set(f.keys()) == X._vertex_set.set() and not set( f.keys()) == X.effective_vertices().set(): raise ValueError, "f must be a dictionary from the vertex set of X to single values in the vertex set of Y." dim = X.dimension() Y_faces = Y.faces() for k in range(dim + 1): for i in X.faces()[k]: tup = i.tuple() fi = [] for j in tup: fi.append(f[j]) v = simplicial_complex.Simplex(set(fi)) if not v in Y_faces[v.dimension()]: raise ValueError, "f must be a dictionary from the vertices of X to the vertices of Y." self._vertex_dictionary = f self._domain = X self._codomain = Y
def __init__(self, f, X, Y): """ Input is a dictionary ``f``, the domain ``X``, and the codomain ``Y``. One can define the dictionary on the vertices of `X`. EXAMPLES:: sage: S = SimplicialComplex([[0,1],[2],[3,4],[5]], is_mutable=False) sage: H = Hom(S,S) sage: f = {0:0,1:1,2:2,3:3,4:4,5:5} sage: g = {0:0,1:1,2:0,3:3,4:4,5:0} sage: x = H(f) sage: y = H(g) sage: x == y False sage: x.image() Simplicial complex with vertex set (0, 1, 2, 3, 4, 5) and facets {(3, 4), (5,), (2,), (0, 1)} sage: y.image() Simplicial complex with vertex set (0, 1, 3, 4) and facets {(3, 4), (0, 1)} sage: x.image() == y.image() False """ if not isinstance( X, simplicial_complex.SimplicialComplex) or not isinstance( Y, simplicial_complex.SimplicialComplex): raise ValueError("X and Y must be SimplicialComplexes.") if not set(f.keys()) == X._vertex_set.set(): raise ValueError( "f must be a dictionary from the vertex set of X to single values in the vertex set of Y." ) dim = X.dimension() Y_faces = Y.faces() for k in range(dim + 1): for i in X.faces()[k]: tup = i.tuple() fi = [] for j in tup: fi.append(f[j]) v = simplicial_complex.Simplex(set(fi)) if not v in Y_faces[v.dimension()]: raise ValueError( "f must be a dictionary from the vertices of X to the vertices of Y." ) self._vertex_dictionary = f self._domain = X self._codomain = Y