Ticket #6099: 6099-1.patch

File 6099-1.patch, 28.9 KB (added by bantieau, 10 years ago)

This patch implements the chain complex morphisms part of this trac ticket.

  • sage/categories/category_types.py

    # HG changeset patch
    # User Benjamin Antieau <antieau@math.uic.edu>
    # Date 1243879584 25200
    # Node ID 5e63080e334f90780fdc0ed2f10e139e8dc09d20
    # Parent  9ae4f3cacf19ec17942ace6e0d557432b31b0359
    First patch for trac #6099; implemented morphisms of simplicial complexes.
    
    diff -r 9ae4f3cacf19 -r 5e63080e334f sage/categories/category_types.py
    a b  
    373373#############################################################
    374374# Semigroup
    375375#############################################################
    376 
    377376class Semigroups(Category_uniq):
    378377    """
    379378    The category of all semigroups.
     
    12881287    Objects                : [Sets],\
    12891288    Sets                   : [],\
    12901289    GSets                  : [Sets],\
     1290    SimplicialComplexes    : [Sets],\
    12911291    Semigroups             : [Sets],\
    12921292    Monoids                : [Semigroups, Sets],\
    12931293    Groups                 : [Monoids, Semigroups, Sets],\
  • sage/categories/homset.py

    diff -r 9ae4f3cacf19 -r 5e63080e334f sage/categories/homset.py
    a b  
    154154        from sage.schemes.generic.homset import SchemeHomset
    155155        H = SchemeHomset(X, Y)
    156156       
     157    elif cat._is_subclass(category_types.SimplicialComplexes):
     158
     159        from sage.homology.simplicial_complex_homset import SimplicialComplexHomset
     160        H = SimplicialComplexHomset(X,Y)
     161
    157162    else:  # default
    158163        if hasattr(X, '_base') and X._base is not X and X._base is not None:
    159164            H = HomsetWithBase(X, Y, cat)
  • sage/homology/all.py

    diff -r 9ae4f3cacf19 -r 5e63080e334f sage/homology/all.py
    a b  
    22
    33from simplicial_complex import SimplicialComplex
    44
     5from simplicial_complex_morphism import SimplicialComplexMorphism
     6
    57from examples import simplicial_complexes
  • sage/homology/simplicial_complex.py

    diff -r 9ae4f3cacf19 -r 5e63080e334f sage/homology/simplicial_complex.py
    a b  
    762762        """
    763763        return self._vertex_set
    764764
     765    def effective_vertices(self):
     766        """
     767        The set of vertices belonging to some face.
     768
     769        EXAMPLES::
     770
     771            sage: S = SimplicialComplex(15)
     772            sage: S
     773            Simplicial complex with 16 vertices and facets {()}
     774            sage: S.effective_vertices()
     775            ()
     776
     777            sage: S = SimplicialComplex(15,[[0,1,2,3],[6,7]])
     778            sage: S
     779            Simplicial complex with 16 vertices and facets {(6, 7), (0, 1, 2, 3)}
     780            sage: S.effective_vertices()
     781            (0, 1, 2, 3, 6, 7)
     782
     783        """
     784        try:
     785            v = self.faces()[0]
     786        except KeyError:
     787            return Simplex(-1)
     788        f = []
     789        for i in v:
     790            f.append(i[0])
     791        return Simplex(set(f))
     792
     793
    765794    def maximal_faces(self):
    766795        """
    767796        The maximal faces (a.k.a. facets) of this simplicial complex.
     
    21602189        if len(facet_string) > facet_limit:
    21612190            facet_string = "%s facets" % len(facets)
    21622191        return "Simplicial complex " + vertex_string + " and " + facet_string
     2192
     2193    def generated_subcomplex(self,sub_vertex_set):
     2194        """
     2195        Returns the largest sub SimplicialComplex of self containing exactly the sub_vertex_set as vertices.
     2196
     2197        EXAMPLES::
     2198
     2199            sage: S = simplicial_complexes.Sphere(2)
     2200            sage: S
     2201            Simplicial complex with vertex set (0, 1, 2, 3) and facets {(0, 2, 3), (0, 1, 2), (1, 2, 3), (0, 1, 3)}
     2202            sage: S.generated_subcomplex([0,1,2])
     2203            Simplicial complex with vertex set (0, 1, 2) and facets {(0, 1, 2)}
     2204
     2205        """
     2206        if not self.vertices().set().issuperset(sub_vertex_set):
     2207            raise TypeError, "input must be a subset of the vertex set."
     2208        faces = []
     2209        for i in range(self.dimension()+1):
     2210            for j in self.faces()[i]:
     2211                if j.set().issubset(sub_vertex_set):
     2212                    faces.append(j)
     2213        return SimplicialComplex(sub_vertex_set,faces,maximality_check=True)
  • new file sage/homology/simplicial_complex_homset.py

    diff -r 9ae4f3cacf19 -r 5e63080e334f sage/homology/simplicial_complex_homset.py
    - +  
     1r"""
     2Homsets between simplicial complexes
     3
     4EXAMPLES:
     5
     6::
     7
     8    sage: S = simplicial_complexes.Sphere(1)
     9    sage: T = simplicial_complexes.Sphere(2)
     10    sage: H = Hom(S,T)
     11    sage: from sage.homology.simplicial_complex import Simplex
     12    sage: f = {0:0,1:1,2:3}
     13    sage: x = H(f)
     14    sage: x
     15    Simplicial complex morphism {0: 0, 1: 1, 2: 3} from Simplicial complex with vertex set (0, 1, 2) and facets {(1, 2), (0, 2), (0, 1)} to Simplicial complex with vertex set (0, 1, 2, 3) and facets {(0, 2, 3), (0, 1, 2), (1, 2, 3), (0, 1, 3)}
     16    sage: x.is_injective()
     17    True
     18    sage: x.is_surjective()
     19    False
     20    sage: x.image()
     21    Simplicial complex with vertex set (0, 1, 3) and facets {(1, 3), (0, 3), (0, 1)}
     22    sage: s = Simplex([1,2])
     23    sage: x(s)
     24    (1, 3)
     25
     26TESTS::
     27
     28    sage: S = simplicial_complexes.Sphere(1)
     29    sage: T = simplicial_complexes.Sphere(2)
     30    sage: H = Hom(S,T)
     31    sage: loads(dumps(H))==H
     32    True
     33
     34"""
     35
     36#*****************************************************************************
     37# Copyright (C) 2009 D. Benjamin Antieau <d.ben.antieau@gmail.com>
     38#
     39#  Distributed under the terms of the GNU General Public License (GPL)
     40#
     41#    This code is distributed in the hope that it will be useful,
     42#    but WITHOUT ANY WARRANTY; without even the implied warranty
     43#    of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
     44#
     45#  See the GNU General Public License for more details; the full text
     46#  is available at:
     47#
     48#                  http://www.gnu.org/licenses/
     49#
     50#*****************************************************************************
     51
     52import sage.categories.homset
     53import sage.homology.simplicial_complex as simplicial_complex
     54import sage.homology.simplicial_complex_morphism as simplicial_complex_morphism
     55
     56def is_SimplicialComplexHomset(x):
     57    """
     58    Return True if and only if x is a simplicial complex homspace.
     59
     60    EXAMPLES::
     61
     62        sage: H = Hom(SimplicialComplex(2),SimplicialComplex(3))
     63        sage: H
     64        Set of Morphisms from Simplicial complex with vertex set (0, 1, 2) and facets {()} to Simplicial complex with vertex set (0, 1, 2, 3) and facets {()} in Category of simplicial complexes
     65        sage: from sage.homology.simplicial_complex_homset import is_SimplicialComplexHomset
     66        sage: is_SimplicialComplexHomset(H)
     67        True
     68    """
     69    return isinstance(x, SimplicialComplexHomset)
     70
     71class SimplicialComplexHomset(sage.categories.homset.Homset):
     72    def __call__(self, f):
     73        """
     74        INPUT:
     75            f -- a dictionary with keys exactly the vertices of the domain and values vertices of the codomain
     76
     77        EXAMPLE::
     78
     79            sage: S = simplicial_complexes.Sphere(3)
     80            sage: T = simplicial_complexes.Sphere(2)
     81            sage: f = {0:0,1:1,2:2,3:2,4:2}
     82            sage: H = Hom(S,T)
     83            sage: x = H(f)
     84            sage: x
     85            Simplicial complex morphism {0: 0, 1: 1, 2: 2, 3: 2, 4: 2} from Simplicial complex with vertex set (0, 1, 2, 3, 4) and 5 facets to Simplicial complex with vertex set (0, 1, 2, 3) and facets {(0, 2, 3), (0, 1, 2), (1, 2, 3), (0, 1, 3)}
     86
     87           
     88        """
     89        return simplicial_complex_morphism.SimplicialComplexMorphism(f,self.domain(),self.codomain())
     90
     91    def diagonal_morphism(self,rename_vertices=True):
     92        """
     93        Returns the diagonal morphism in Hom(S,SxS).
     94
     95        EXAMPLES::
     96
     97            sage: S = simplicial_complexes.Sphere(2)
     98            sage: H = Hom(S,S.product(S))
     99            sage: d = H.diagonal_morphism()
     100            sage: d
     101            Simplicial complex morphism {0: 'L0R0', 1: 'L1R1', 2: 'L2R2', 3: 'L3R3'} from Simplicial complex with vertex set (0, 1, 2, 3) and facets {(0, 2, 3), (0, 1, 2), (1, 2, 3), (0, 1, 3)} to Simplicial complex with 16 vertices and 96 facets
     102       
     103            sage: T = SimplicialComplex(3)
     104            sage: U = T.product(T,rename_vertices = False)
     105            sage: G = Hom(T,U)
     106            sage: e = G.diagonal_morphism(rename_vertices = False)
     107            sage: e
     108            Simplicial complex morphism {0: (0, 0), 1: (1, 1), 2: (2, 2), 3: (3, 3)} from Simplicial complex with vertex set (0, 1, 2, 3) and facets {()} to Simplicial complex with 16 vertices and facets {()}
     109
     110        """
     111
     112        if self._codomain == self._domain.product(self._domain,rename_vertices=rename_vertices):
     113            X = self._domain.product(self._domain,rename_vertices=rename_vertices)
     114            f = dict()
     115            if rename_vertices:
     116                for i in self._domain.vertices().set():
     117                    f[i] = "L"+str(i)+"R"+str(i)
     118            else:
     119                for i in self._domain.vertices().set():
     120                    f[i] = (i,i)
     121            return simplicial_complex_morphism.SimplicialComplexMorphism(f,self._domain,X)
     122        else:
     123            raise TypeError, "Diagonal morphism is only defined for Hom(X,XxX)."
     124       
     125    def identity(self):
     126        """
     127        Returns the identity morphism of Hom(S,S).
     128
     129        EXAMPLES::
     130
     131            sage: S = simplicial_complexes.Sphere(2)
     132            sage: H = Hom(S,S)
     133            sage: i = H.identity()
     134            sage: i.is_identity()
     135            True
     136
     137            sage: T = SimplicialComplex(3,[[0,1]])
     138            sage: G = Hom(T,T)
     139            sage: G.identity()
     140            Simplicial complex morphism {0: 0, 1: 1, 2: 2, 3: 3} from Simplicial complex with vertex set (0, 1, 2, 3) and facets {(0, 1)} to Simplicial complex with vertex set (0, 1, 2, 3) and facets {(0, 1)}
     141
     142        """
     143        if self.is_endomorphism_set():
     144            f = dict()
     145            for i in self._domain.vertices().set():
     146                f[i]=i
     147            return simplicial_complex_morphism.SimplicialComplexMorphism(f,self._domain,self._codomain)
     148        else:
     149            raise TypeError, "Identity map is only defined for endomorphism sets."
     150
     151    def an_element(self):
     152        """
     153        Returns a (non-random) element of self.
     154
     155        EXAMPLES::
     156
     157            sage: S = simplicial_complexes.KleinBottle()
     158            sage: T = simplicial_complexes.Sphere(5)
     159            sage: H = Hom(S,T)
     160            sage: x = H.an_element()
     161            sage: x
     162            Simplicial complex morphism {0: 0, 1: 0, 2: 0, 'R3': 0, 'L4': 0, 'L5': 0, 'L3': 0, 'R5': 0, 'R4': 0} from Simplicial complex with 9 vertices and 18 facets to Simplicial complex with vertex set (0, 1, 2, 3, 4, 5, 6) and 7 facets
     163
     164        """
     165        X_vertices = self._domain.vertices().set()
     166        try:
     167            i = self._codomain.vertices().set().__iter__().next()
     168        except StopIteration:
     169            if len(X_vertices) == 0:
     170                return dict()
     171            else:
     172                raise TypeError, "There are no morphisms from a non-empty simplicial complex to an empty simplicial comples."
     173        f = dict()
     174        for x in X_vertices:
     175            f[x]=i
     176        return simplicial_complex_morphism.SimplicialComplexMorphism(f,self._domain,self._codomain)
  • new file sage/homology/simplicial_complex_morphism.py

    diff -r 9ae4f3cacf19 -r 5e63080e334f sage/homology/simplicial_complex_morphism.py
    - +  
     1r"""
     2Morphisms of simplicial complexes
     3
     4AUTHORS:
     5
     6- D. Benjamin Antieau <d.ben.antieau@gmail.com> (2009.06)
     7
     8This module implements morphisms of simplicial complexes. The input is given
     9by a dictionary on the vertex set or the effective vertex set of a simplicial complex.
     10The initialization checks that faces are sent to faces.
     11
     12There is also the capability to create the fiber product of two morphisms with the same codomain.
     13
     14EXAMPLES::
     15
     16    sage: S = SimplicialComplex(5,[[0,2],[1,5],[3,4]])
     17    sage: H = Hom(S,S.product(S))
     18    sage: H.diagonal_morphism()
     19    Simplicial complex morphism {0: 'L0R0', 1: 'L1R1', 2: 'L2R2', 3: 'L3R3', 4: 'L4R4', 5: 'L5R5'} from Simplicial complex with vertex set (0, 1, 2, 3, 4, 5) and facets {(3, 4), (1, 5), (0, 2)} to Simplicial complex with 36 vertices and 18 facets
     20
     21    sage: S = SimplicialComplex(5,[[0,2],[1,5],[3,4]])
     22    sage: T = SimplicialComplex(4,[[0,2],[1,3]])
     23    sage: f = {0:0,1:1,2:2,3:1,4:3,5:3}
     24    sage: H = Hom(S,T)
     25    sage: x = H(f)
     26    sage: x.image()
     27    Simplicial complex with vertex set (0, 1, 2, 3) and facets {(1, 3), (0, 2)}
     28    sage: x.is_surjective()
     29    False
     30    sage: x.is_injective()
     31    False
     32    sage: x.is_identity()
     33    False
     34
     35    sage: S = simplicial_complexes.Sphere(2)
     36    sage: H = Hom(S,S)
     37    sage: i = H.identity()
     38    sage: i.image()
     39    Simplicial complex with vertex set (0, 1, 2, 3) and facets {(0, 2, 3), (0, 1, 2), (1, 2, 3), (0, 1, 3)}
     40    sage: i.is_surjective()
     41    True
     42    sage: i.is_injective()
     43    True
     44    sage: i.is_identity()
     45    True
     46
     47    sage: S = simplicial_complexes.Sphere(2)
     48    sage: H = Hom(S,S)
     49    sage: i = H.identity()
     50    sage: j = i.product(i)
     51    sage: j
     52    Simplicial complex morphism {'L1R1': 1, 'L3R3': 3, 'L2R2': 2, 'L0R0': 0} from Simplicial complex with 4 vertices and 4 facets to Simplicial complex with vertex set (0, 1, 2, 3) and facets {(0, 2, 3), (0, 1, 2), (1, 2, 3), (0, 1, 3)}
     53
     54    sage: S = simplicial_complexes.Sphere(2)
     55    sage: T = S.product(SimplicialComplex(1,[[0,1]]),rename_vertices = False)
     56    sage: H = Hom(T,S)
     57    sage: T
     58    Simplicial complex with 8 vertices and 12 facets
     59    sage: T.vertices()
     60    ((0, 0), (0, 1), (1, 0), (1, 1), (2, 0), (2, 1), (3, 0), (3, 1))
     61    sage: f = {(0, 0): 0, (0, 1): 0, (1, 0): 1, (1, 1): 1, (2, 0): 2, (2, 1): 2, (3, 0): 3, (3, 1): 3}
     62    sage: x = H(f)
     63    sage: U = simplicial_complexes.Sphere(1)
     64    sage: G = Hom(U,S)
     65    sage: U
     66    Simplicial complex with vertex set (0, 1, 2) and facets {(1, 2), (0, 2), (0, 1)}
     67    sage: g = {0:0,1:1,2:2}
     68    sage: y = G(g)
     69    sage: z = y.product(x)
     70    sage: z                                     # this is the mapping path space
     71    Simplicial complex morphism {'L2R(2, 0)': 2, 'L2R(2, 1)': 2, 'L0R(0, 0)': 0, 'L0R(0, 1)': 0, 'L1R(1, 0)': 1, 'L1R(1, 1)': 1} from Simplicial complex with 6 vertices and 6 facets to Simplicial complex with vertex set (0, 1, 2, 3) and facets {(0, 2, 3), (0, 1, 2), (1, 2, 3), (0, 1, 3)}
     72
     73
     74"""
     75
     76#*****************************************************************************
     77# Copyright (C) 2009 D. Benjamin Antieau <d.ben.antieau@gmail.com>
     78#
     79#  Distributed under the terms of the GNU General Public License (GPL)
     80#
     81#    This code is distributed in the hope that it will be useful,
     82#    but WITHOUT ANY WARRANTY; without even the implied warranty
     83#    of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
     84#
     85#  See the GNU General Public License for more details; the full text
     86#  is available at:
     87#
     88#                  http://www.gnu.org/licenses/
     89#
     90#*****************************************************************************
     91
     92import sage.homology.simplicial_complex as simplicial_complex
     93import sage.matrix.all as matrix
     94import sage.categories.category_types as category_types
     95
     96def is_SimplicialComplexMorphism(x):
     97    return isinstance(x,SimplicialComplexMorphism)
     98
     99class SimplicialComplexMorphism(category_types.SageObject):
     100    """
     101    An element of this class is a morphism of simplicial complexes.
     102    """
     103    def __init__(self,f,X,Y):
     104        """
     105        Input is a dictionary f, the domain, and the codomain.
     106
     107        One can define the dictionary either on the vertices of X or on the effective vertices of X (X.effective_vertices()). Note that this
     108        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.
     109        This is because two SimplicialComplexes with the same faces but different vertex sets are not equal.
     110
     111        EXAMPLES::
     112
     113            sage: S = SimplicialComplex(5,[[0,1],[3,4]])
     114            sage: H = Hom(S,S)
     115            sage: f = {0:0,1:1,2:2,3:3,4:4,5:5}
     116            sage: g = {0:0,1:1,3:3,4:4}
     117            sage: x = H(f)
     118            sage: y = H(g)
     119            sage: x==y
     120            False
     121            sage: x.image()
     122            Simplicial complex with vertex set (0, 1, 2, 3, 4, 5) and facets {(3, 4), (0, 1)}
     123            sage: y.image()
     124            Simplicial complex with vertex set (0, 1, 3, 4) and facets {(3, 4), (0, 1)}
     125            sage: x.image()==y.image()
     126            False
     127
     128        """
     129        if not isinstance(X,simplicial_complex.SimplicialComplex) or not isinstance(Y,simplicial_complex.SimplicialComplex):
     130            raise ValueError, "X and Y must be SimplicialComplexes."
     131        if not set(f.keys())==X._vertex_set.set() and not set(f.keys())==X.effective_vertices().set():
     132            raise ValueError, "f must be a dictionary from the vertex set of X to single values in the vertex set of Y."
     133        dim = X.dimension()
     134        Y_faces = Y.faces()
     135        for k in range(dim+1):
     136            for i in X.faces()[k]:
     137                tup = i.tuple()
     138                fi = []
     139                for j in tup:
     140                    fi.append(f[j])
     141                v = simplicial_complex.Simplex(set(fi))
     142            if not v in Y_faces[v.dimension()]:
     143                raise ValueError, "f must be a dictionary from the vertices of X to the vertices of Y."
     144        self._vertex_dictionary = f
     145        self._domain = X
     146        self._codomain = Y
     147   
     148    def __eq__(self,x):
     149        """
     150        Returns True if and only if self == x.
     151       
     152        EXAMPLES::
     153
     154            sage: S = simplicial_complexes.Sphere(2)
     155            sage: H = Hom(S,S)
     156            sage: i = H.identity()
     157            sage: i
     158            Simplicial complex morphism {0: 0, 1: 1, 2: 2, 3: 3} from Simplicial complex with vertex set (0, 1, 2, 3) and facets {(0, 2, 3), (0, 1, 2), (1, 2, 3), (0, 1, 3)} to Simplicial complex with vertex set (0, 1, 2, 3) and facets {(0, 2, 3), (0, 1, 2), (1, 2, 3), (0, 1, 3)}
     159            sage: f = {0:0,1:1,2:2,3:2}
     160            sage: j = H(f)
     161            sage: i==j
     162            False
     163           
     164            sage: T = SimplicialComplex(3,[[1,2]])
     165            sage: T
     166            Simplicial complex with vertex set (0, 1, 2, 3) and facets {(1, 2)}
     167            sage: G = Hom(T,T)
     168            sage: k = G.identity()
     169            sage: g = {0:0,1:1,2:2,3:3}
     170            sage: l = G(g)
     171            sage: k==l
     172            True
     173
     174        """
     175        if not isinstance(x,SimplicialComplexMorphism) or self._codomain != x._codomain or self._domain != x._domain or self._vertex_dictionary != x._vertex_dictionary:
     176            return False
     177        else:
     178            return True
     179
     180    def __call__(self,x):
     181        """
     182        Input is a simplex of the domain. Output is the image simplex.
     183       
     184        EXAMPLES::
     185
     186            sage: S = simplicial_complexes.Sphere(2)
     187            sage: T = simplicial_complexes.Sphere(3)
     188            sage: S
     189            Simplicial complex with vertex set (0, 1, 2, 3) and facets {(0, 2, 3), (0, 1, 2), (1, 2, 3), (0, 1, 3)}
     190            sage: T
     191            Simplicial complex with vertex set (0, 1, 2, 3, 4) and 5 facets
     192            sage: f = {0:0,1:1,2:2,3:3}
     193            sage: H = Hom(S,T)
     194            sage: x = H(f)
     195            sage: from sage.homology.simplicial_complex import Simplex
     196            sage: x(Simplex([0,2,3]))
     197            (0, 2, 3)
     198
     199        """
     200        dim = self._domain.dimension()
     201        if not isinstance(x,simplicial_complex.Simplex) or x.dimension() > dim or not x in self._domain.faces()[x.dimension()]:
     202            raise ValueError, "x must be a simplex of the source of f"
     203        tup=x.tuple()
     204        fx=[]
     205        for j in tup:
     206            fx.append(self._vertex_dictionary[j])
     207        return simplicial_complex.Simplex(set(fx))
     208
     209    def _repr_(self):
     210        """
     211        Print representation
     212
     213        EXAMPLES::
     214
     215            sage: S = simplicial_complexes.Sphere(2)
     216            sage: H = Hom(S,S)
     217            sage: i = H.identity()
     218            sage: i
     219            Simplicial complex morphism {0: 0, 1: 1, 2: 2, 3: 3} from Simplicial complex with vertex set (0, 1, 2, 3) and facets {(0, 2, 3), (0, 1, 2), (1, 2, 3), (0, 1, 3)} to Simplicial complex with vertex set (0, 1, 2, 3) and facets {(0, 2, 3), (0, 1, 2), (1, 2, 3), (0, 1, 3)}
     220
     221        """
     222        return "Simplicial complex morphism " + str(self._vertex_dictionary) + " from " + self._domain._repr_() + " to " + self._codomain._repr_()
     223
     224#    This is going to be implemented in the near future.
     225#
     226#    def associated_chain_complex_morphism(self,base_ring=ZZ,augmented=False,cochain=False):
     227#        max_dim = max(self._domain.dimension(),self._codomain.dimension())
     228#        min_dim = min(self._domain.dimension(),self._codomain.dimension())
     229#        matrices={}
     230#        if augmented is True:
     231#            m=matrix.Matrix(base_ring,1,1,1)
     232#            if not cochain:
     233#                matrices[-1] = m
     234#            else:
     235#                matrices[-1] = m.transpose()
     236#        for dim in range(min_dim+1):
     237#            X_faces = list(self._domain.faces()[dim])
     238#            Y_faces = list(self._codomain.faces()[dim])
     239#            num_faces_X = len(X_faces)
     240#            num_faces_Y = len(Y_faces)
     241#            mval = [0 for i in range(num_faces_X*num_faces_Y)]
     242#            for i in X_faces:
     243#                y=self(i)
     244#                if y.dimension() < dim:
     245#                    pass
     246#                else:
     247#                    mval[X_faces.index(i)+(Y_faces.index(y)*num_faces_X)] = 1
     248#            m = matrix.Matrix(base_ring,num_faces_Y,num_faces_X,mval,sparse=True)
     249#            if not cochain:
     250#                matrices[dim] = m
     251#            else:
     252#                matrices[dim] = m.transpose()
     253#        for dim in range(min_dim+1,max_dim+1):
     254#            m = zero_matrix(base_ring,len(self._codomain.faces()[dim]),len(self._domain.faces()[dim]),sparse=True)
     255#            if not cochain:
     256#                matrices[dim] = m
     257#            else:
     258#                matrices[dim] = m.transpose()
     259#        if not cochain:
     260#            return ChainComplexMorphism(matrices,self._domain.chain_complex(base_ring=base_ring,augmented=augmented,cochain=cochain),self._codomain.chain_complex(base_ring=base_ring,augmented=augmented,cochain=cochain))
     261#        else:
     262#            return ChainComplexMorphism(matrices,self._codomain.chain_complex(base_ring=base_ring,augmented=augmented,cochain=cochain),self._domain.chain_complex(base_ring=base_ring,augmented=augmented,cochain=cochain))
     263       
     264    def image(self):
     265        """
     266        Computes the image simplicial complex of f.
     267       
     268        EXAMPLES::
     269
     270            sage: S = SimplicialComplex(3,[[0,1],[2,3]])
     271            sage: T = SimplicialComplex(1,[[0,1]])
     272            sage: f = {0:0,1:1,2:0,3:1}
     273            sage: H = Hom(S,T)
     274            sage: x = H(f)
     275            sage: x.image()
     276            Simplicial complex with vertex set (0, 1) and facets {(0, 1)}
     277
     278            sage: S = SimplicialComplex(2)
     279            sage: H = Hom(S,S)
     280            sage: i = H.identity()
     281            sage: i.image()
     282            Simplicial complex with vertex set (0, 1, 2) and facets {()}
     283            sage: i.is_surjective()
     284            True
     285            sage: S = SimplicialComplex(5,[[0,1]])
     286            sage: T = SimplicialComplex(3,[[0,1]])
     287            sage: f = {0:0,1:1}
     288            sage: g = {0:0,1:1,2:2,3:3,4:4,5:5}
     289            sage: H = Hom(S,T)
     290            sage: x = H(f)
     291            sage: y = H(g)
     292            sage: x == y
     293            False
     294            sage: x.image()
     295            Simplicial complex with vertex set (0, 1) and facets {(0, 1)}
     296            sage: y.image()
     297            Simplicial complex with vertex set (0, 1, 2, 3, 4, 5) and facets {(0, 1)}
     298
     299        """
     300        fa = [self(i) for i in self._domain.facets]
     301        return simplicial_complex.SimplicialComplex(set(self._vertex_dictionary.values()),fa,maximality_check=True)
     302       
     303    def is_surjective(self):
     304        """
     305        Returns True if and only if self is surjective.
     306
     307        EXAMPLES::
     308
     309            sage: S = SimplicialComplex(3,[(0,1,2)])
     310            sage: S
     311            Simplicial complex with vertex set (0, 1, 2, 3) and facets {(0, 1, 2)}
     312            sage: T = SimplicialComplex(2,[(0,1)])
     313            sage: T
     314            Simplicial complex with vertex set (0, 1, 2) and facets {(0, 1)}
     315            sage: H = Hom(S,T)
     316            sage: x = H({0:0,1:1,2:1,3:2})
     317            sage: x.is_surjective()
     318            True
     319
     320            sage: S = SimplicialComplex(3,[[0,1],[2,3]])
     321            sage: T = SimplicialComplex(1,[[0,1]])
     322            sage: f = {0:0,1:1,2:0,3:1}
     323            sage: H = Hom(S,T)
     324            sage: x = H(f)
     325            sage: x.is_surjective()
     326            True
     327
     328        """   
     329        return self._codomain == self.image()
     330       
     331    def is_injective(self):
     332        """
     333        Returns True if and only if self is injective.
     334
     335        EXAMPLES::
     336
     337            sage: S = simplicial_complexes.Sphere(1)
     338            sage: T = simplicial_complexes.Sphere(2)
     339            sage: U = simplicial_complexes.Sphere(3)
     340            sage: H = Hom(T,S)
     341            sage: G = Hom(T,U)
     342            sage: f = {0:0,1:1,2:0,3:1}
     343            sage: x = H(f)
     344            sage: g = {0:0,1:1,2:2,3:3}
     345            sage: y = G(g)
     346            sage: x.is_injective()
     347            False
     348            sage: y.is_injective()
     349            True
     350
     351        """
     352        v = [self._vertex_dictionary[i[0]] for i in self._domain.faces()[0]]
     353        for i in v:
     354            if v.count(i) > 1:
     355                return False
     356        return True
     357
     358    def is_identity(self):
     359        """
     360        If x is an identity morphism, returns True. Otherwise, False.
     361
     362        EXAMPLES::
     363
     364            sage: T = simplicial_complexes.Sphere(1)
     365            sage: G = Hom(T,T)
     366            sage: T
     367            Simplicial complex with vertex set (0, 1, 2) and facets {(1, 2), (0, 2), (0, 1)}
     368            sage: j = G({0:0,1:1,2:2})
     369            sage: j.is_identity()
     370            True
     371
     372            sage: S = simplicial_complexes.Sphere(2)
     373            sage: T = simplicial_complexes.Sphere(3)
     374            sage: H = Hom(S,T)
     375            sage: f = {0:0,1:1,2:2,3:3}
     376            sage: x = H(f)
     377            sage: x
     378            Simplicial complex morphism {0: 0, 1: 1, 2: 2, 3: 3} from Simplicial complex with vertex set (0, 1, 2, 3) and facets {(0, 2, 3), (0, 1, 2), (1, 2, 3), (0, 1, 3)} to Simplicial complex with vertex set (0, 1, 2, 3, 4) and 5 facets
     379            sage: x.is_identity()
     380            False
     381
     382        """
     383        if self._domain != self._codomain:
     384            return False
     385        else:
     386            f = dict()
     387            for i in self._domain.vertices().set():
     388                f[i] = i
     389            if self._vertex_dictionary != f:
     390                return False
     391            else:
     392                return True
     393
     394    def product(self,other,rename_vertices = True):
     395        """
     396        Fiber product of self and other. Both morphisms should have the same codomain. The method returns a morphism of simplicial complexes, which
     397        is the morphism from the space of the fiber product to the codomain.
     398
     399        EXAMPLES::
     400           
     401            sage: S = SimplicialComplex(2,[[0,1],[1,2]])
     402            sage: T = SimplicialComplex(2,[[0,2]])
     403            sage: U = SimplicialComplex(1,[[0,1]])
     404            sage: H = Hom(S,U)
     405            sage: G = Hom(T,U)
     406            sage: f = {0:0,1:1,2:0}
     407            sage: g = {0:0,1:1,2:1}
     408            sage: x = H(f)
     409            sage: y = G(g)
     410            sage: z = x.product(y)
     411            sage: z
     412            Simplicial complex morphism {'L1R2': 1, 'L2R0': 0, 'L0R0': 0} from Simplicial complex with vertex set ('L0R0', 'L1R2', 'L2R0') and facets {('L2R0',), ('L0R0', 'L1R2')} to Simplicial complex with vertex set (0, 1) and facets {(0, 1)}
     413
     414        """
     415        if self._codomain != other._codomain:
     416            raise ValueError, "self and other must have the same codomain."
     417        X = self._domain.product(other._domain,rename_vertices = rename_vertices)
     418        v = []
     419        f = dict()
     420        eff1 = self._domain.effective_vertices()
     421        eff2 = other._domain.effective_vertices()
     422        for i in eff1:
     423            for j in eff2:
     424                if self(simplicial_complex.Simplex([i])) == other(simplicial_complex.Simplex([j])):
     425                    if rename_vertices:
     426                        v.append("L"+str(i)+"R"+str(j))
     427                        f["L"+str(i)+"R"+str(j)] = self._vertex_dictionary[i]
     428                    else:
     429                        v.append((i,j))
     430                        f[(i,j)] = self._vertex_dictionary[i]
     431        return SimplicialComplexMorphism(f,X.generated_subcomplex(v),self._codomain)