Ticket #6099: 6099-merged.patch

File 6099-merged.patch, 52.7 KB (added by bantieau, 9 years ago)

Hopefully final merged patch.

  • doc/en/reference/homology.rst

    # HG changeset patch
    # User Benjamin Antieau <antieau@math.uic.edu>
    # Date 1257542166 21600
    # Node ID 6014c5979a5976c0228cfacd81318fca57884b53
    # Parent  f872a92f5f9afff4b4971afc82bf9270faec269b
    This is the hopefully final patch for ticket #6099, which implements morphisms of simplicial complexes.
    
    diff -r f872a92f5f9a -r 6014c5979a59 doc/en/reference/homology.rst
    a b  
    88   :maxdepth: 2
    99
    1010   sage/homology/simplicial_complex
     11   sage/homology/simplicial_complex_morphism
     12   sage/homology/simplicial_complex_homset
    1113   sage/homology/chain_complex
     14   sage/homology/chain_complex_morphism
     15   sage/homology/chain_complex_homset
    1216   sage/homology/examples
  • sage/categories/category_types.py

    diff -r f872a92f5f9a -r 6014c5979a59 sage/categories/category_types.py
    a b  
    12931293    Objects                : [Sets],\
    12941294    Sets                   : [],\
    12951295    GSets                  : [Sets],\
     1296    SimplicialComplexes    : [Sets],\
    12961297    Semigroups             : [Sets],\
    12971298    Monoids                : [Semigroups, Sets],\
    12981299    Groups                 : [Monoids, Semigroups, Sets],\
     
    13101311    GroupAlgebras          : [MonoidAlgebras, Algebras, Sets],\
    13111312    MatrixAlgebras         : [Algebras, Sets],\
    13121313    RingModules            : [AbelianGroups, Sets],\
     1314    ChainComplexes         : [],\
    13131315    FreeModules            : [RingModules, AbelianGroups, Sets],\
    13141316    VectorSpaces           : [FreeModules, RingModules, AbelianGroups, Sets],\
    13151317    HeckeModules           : [FreeModules, RingModules, AbelianGroups, Sets],\
  • sage/categories/homset.py

    diff -r f872a92f5f9a -r 6014c5979a59 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
     162    elif cat._is_subclass(category_types.ChainComplexes):
     163
     164        from sage.homology.chain_complex_homspace import ChainComplexHomspace
     165        H = ChainComplexHomspace(X,Y)
     166
     167
     168
    157169    else:  # default
    158170        if hasattr(X, '_base') and X._base is not X and X._base is not None:
    159171            H = HomsetWithBase(X, Y, cat)
  • sage/homology/all.py

    diff -r f872a92f5f9a -r 6014c5979a59 sage/homology/all.py
    a b  
    11from chain_complex import ChainComplex
    22
     3from chain_complex_morphism import ChainComplexMorphism
     4
    35from simplicial_complex import SimplicialComplex
    46
     7from simplicial_complex_morphism import SimplicialComplexMorphism
     8
    59from examples import simplicial_complexes
  • new file sage/homology/chain_complex_homspace.py

    diff -r f872a92f5f9a -r 6014c5979a59 sage/homology/chain_complex_homspace.py
    - +  
     1r"""
     2Homspaces between chain complexes
     3
     4Note that some significant functionality is lacking. Namely, the homspaces
     5are not actually modules over the base ring. It will be necessary to
     6enrich some of the structure of chain complexes for this to be naturally
     7available. On other hand, there are various overloaded operators. __mul__
     8acts as composition. One can __add__, and one can __mul__ with a ring element
     9on the right.
     10
     11EXAMPLES::
     12
     13    sage: S = simplicial_complexes.Sphere(2)
     14    sage: T = simplicial_complexes.Torus()
     15    sage: C = S.chain_complex(augmented=True,cochain=True)
     16    sage: D = T.chain_complex(augmented=True,cochain=True)
     17    sage: G = Hom(C,D)
     18    sage: G
     19    Set of Morphisms from Chain complex with at most 4 nonzero terms over Integer Ring. to Chain complex with at most 4 nonzero terms over Integer Ring. in Category of chain complexes over Integer Ring
     20
     21    sage: S = simplicial_complexes.ChessboardComplex(3,3)
     22    sage: H = Hom(S,S)
     23    sage: i = H.identity()
     24    sage: x = i.associated_chain_complex_morphism(augmented=True)
     25    sage: x
     26    Chain complex morphism from Chain complex with at most 4 nonzero terms over Integer Ring. to Chain complex with at most 4 nonzero terms over Integer Ring.
     27    sage: x._matrix_dictionary
     28    {0: [1 0 0 0 0 0 0 0 0]
     29    [0 1 0 0 0 0 0 0 0]
     30    [0 0 1 0 0 0 0 0 0]
     31    [0 0 0 1 0 0 0 0 0]
     32    [0 0 0 0 1 0 0 0 0]
     33    [0 0 0 0 0 1 0 0 0]
     34    [0 0 0 0 0 0 1 0 0]
     35    [0 0 0 0 0 0 0 1 0]
     36    [0 0 0 0 0 0 0 0 1], 1: [1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]
     37    [0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]
     38    [0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]
     39    [0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0]
     40    [0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0]
     41    [0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0]
     42    [0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0]
     43    [0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0]
     44    [0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0]
     45    [0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0]
     46    [0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0]
     47    [0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0]
     48    [0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0]
     49    [0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0]
     50    [0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0]
     51    [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0]
     52    [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0]
     53    [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1], 2: [1 0 0 0 0 0]
     54    [0 1 0 0 0 0]
     55    [0 0 1 0 0 0]
     56    [0 0 0 1 0 0]
     57    [0 0 0 0 1 0]
     58    [0 0 0 0 0 1], -1: [1]}
     59
     60    sage: S = simplicial_complexes.Sphere(2)
     61    sage: A = Hom(S,S)
     62    sage: i = A.identity()
     63    sage: x = i.associated_chain_complex_morphism()
     64    sage: x
     65    Chain complex morphism from Chain complex with at most 3 nonzero terms over Integer Ring. to Chain complex with at most 3 nonzero terms over Integer Ring.
     66    sage: y = x*4
     67    sage: z = y*y
     68    sage: (y+z)
     69    Chain complex morphism from Chain complex with at most 3 nonzero terms over Integer Ring. to Chain complex with at most 3 nonzero terms over Integer Ring.
     70    sage: f = x._matrix_dictionary
     71    sage: C = S.chain_complex()
     72    sage: G = Hom(C,C)
     73    sage: w = G(f)
     74    sage: w==x
     75    True
     76
     77"""
     78
     79#*****************************************************************************
     80# Copyright (C) 2009 D. Benjamin Antieau <d.ben.antieau@gmail.com>
     81#
     82#  Distributed under the terms of the GNU General Public License (GPL)
     83#
     84#    This code is distributed in the hope that it will be useful,
     85#    but WITHOUT ANY WARRANTY; without even the implied warranty
     86#    of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
     87#
     88#  See the GNU General Public License for more details; the full text
     89#  is available at:
     90#
     91#                  http://www.gnu.org/licenses/
     92#
     93#*****************************************************************************
     94
     95import sage.categories.homset
     96import sage.homology.chain_complex as chain_complex
     97import sage.homology.chain_complex_morphism as chain_complex_morphism
     98
     99def is_ChainComplexHomspace(x):
     100    """
     101    Returns True if and only if x is a morphism of chain complexes.
     102
     103    EXAMPLES::
     104
     105        sage: from sage.homology.chain_complex_homspace import is_ChainComplexHomspace
     106        sage: T = SimplicialComplex(17,[[1,2,3,4],[7,8,9]])
     107        sage: C = T.chain_complex(augmented=True,cochain=True)
     108        sage: G = Hom(C,C)
     109        sage: is_ChainComplexHomspace(G)
     110        True
     111
     112    """
     113    return isinstance(x,ChainComplexHomspace)
     114
     115class ChainComplexHomspace(sage.categories.homset.Homset):
     116    """
     117    Class of homspaces of chain complex morphisms.
     118   
     119    EXAMPLES::
     120
     121        sage: T = SimplicialComplex(17,[[1,2,3,4],[7,8,9]])
     122        sage: C = T.chain_complex(augmented=True,cochain=True)
     123        sage: G = Hom(C,C)
     124        sage: G
     125        Set of Morphisms from Chain complex with at most 5 nonzero terms over Integer Ring. to Chain complex with at most 5 nonzero terms over Integer Ring. in Category of chain complexes over Integer Ring
     126
     127    """
     128    def __call__(self, f):
     129        """
     130        f is a dictionary of matrices in the basis of the chain complex.
     131
     132        EXAMPLES::
     133
     134            sage: S = simplicial_complexes.Sphere(5)
     135            sage: H = Hom(S,S)
     136            sage: i = H.identity()
     137            sage: C = S.chain_complex()
     138            sage: G = Hom(C,C)
     139            sage: x = i.associated_chain_complex_morphism()
     140            sage: f = x._matrix_dictionary
     141            sage: y = G(f)
     142            sage: x==y
     143            True
     144
     145        """
     146        return chain_complex_morphism.ChainComplexMorphism(f, self.domain(), self.codomain())
  • new file sage/homology/chain_complex_morphism.py

    diff -r f872a92f5f9a -r 6014c5979a59 sage/homology/chain_complex_morphism.py
    - +  
     1r"""
     2Morphisms of chain complexes
     3
     4AUTHORS:
     5
     6- Benjamin Antieau <d.ben.antieau@gmail.com> (2009.06)
     7
     8This module implements morphisms of simplicial complexes. The input is a dictionary whose
     9keys are in the grading group of the chain complex and whose values are matrix morphisms.
     10
     11EXAMPLES::
     12
     13    from sage.matrix.constructor import zero_matrix
     14    sage: S = simplicial_complexes.Sphere(1)
     15    sage: S
     16    Simplicial complex with vertex set (0, 1, 2) and facets {(1, 2), (0, 2), (0, 1)}
     17    sage: C = S.chain_complex()
     18    sage: C.differential()
     19    {0: [], 1: [ 1  1  0]
     20    [ 0 -1 -1]
     21    [-1  0  1]}
     22    sage: f = {0:zero_matrix(ZZ,3,3),1:zero_matrix(ZZ,3,3)}
     23    sage: G = Hom(C,C)
     24    sage: x = G(f)
     25    sage: x
     26    Chain complex morphism from Chain complex with at most 2 nonzero terms over Integer Ring. to Chain complex with at most 2 nonzero terms over Integer Ring.
     27    sage: x._matrix_dictionary
     28    {0: [0 0 0]
     29    [0 0 0]
     30    [0 0 0], 1: [0 0 0]
     31    [0 0 0]
     32    [0 0 0]}
     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.homology.simplicial_complex as simplicial_complex
     53import sage.matrix.all as matrix
     54import sage.categories.category_types as category_types
     55from sage.rings.integer_ring import ZZ
     56
     57def is_ChainComplexMorphism(x):
     58    """
     59    Returns True if and only if x is a chain complex morphism.
     60
     61    EXAMPLES::
     62
     63        sage: from sage.homology.chain_complex_morphism import is_ChainComplexMorphism
     64        sage: S = simplicial_complexes.Sphere(14)
     65        sage: H = Hom(S,S)
     66        sage: i = H.identity()
     67        sage: S = simplicial_complexes.Sphere(6)
     68        sage: H = Hom(S,S)
     69        sage: i = H.identity()
     70        sage: x = i.associated_chain_complex_morphism()
     71        sage: x # indirect doctest
     72        Chain complex morphism from Chain complex with at most 7 nonzero terms over Integer Ring. to Chain complex with at most 7 nonzero terms over Integer Ring.
     73        sage: is_ChainComplexMorphism(x)
     74        True
     75
     76    """
     77    return isinstance(x,ChainComplexMorphism)
     78
     79class ChainComplexMorphism(category_types.SageObject):
     80    """
     81    An element of this class is a morphism of chain complexes.
     82    """
     83    def __init__(self,matrices,C,D):
     84        """
     85        Create a morphism from a dictionary of matrices.
     86
     87        EXAMPLES::
     88
     89            from sage.matrix.constructor import zero_matrix
     90            sage: S = simplicial_complexes.Sphere(1)
     91            sage: S
     92            Simplicial complex with vertex set (0, 1, 2) and facets {(1, 2), (0, 2), (0, 1)}
     93            sage: C = S.chain_complex()
     94            sage: C.differential()
     95            {0: [], 1: [ 1  1  0]
     96            [ 0 -1 -1]
     97            [-1  0  1]}
     98            sage: f = {0:zero_matrix(ZZ,3,3),1:zero_matrix(ZZ,3,3)}
     99            sage: G = Hom(C,C)
     100            sage: x = G(f)
     101            sage: x
     102            Chain complex morphism from Chain complex with at most 2 nonzero terms over Integer Ring. to Chain complex with at most 2 nonzero terms over Integer Ring.
     103            sage: x._matrix_dictionary
     104            {0: [0 0 0]
     105            [0 0 0]
     106            [0 0 0], 1: [0 0 0]
     107            [0 0 0]
     108            [0 0 0]}
     109
     110        """
     111        if C._grading_group != ZZ:
     112            raise NotImplementedError, "Chain complex morphisms are not implemented over gradings other than ZZ."
     113        d = C._degree
     114        if d != D._degree:
     115            raise ValueError, "Chain complex morphisms are not defined for chain complexes of different degrees."
     116        if d != -1 and d != 1:
     117            raise NotImplementedError, "Chain complex morphisms are not implemented for degrees besides -1 and 1."
     118        dim_min = min(min(C.differential().keys()),min(D.differential().keys()))
     119        dim_max = max(max(C.differential().keys()),max(D.differential().keys()))
     120        if not C.base_ring()==D.base_ring():
     121            raise NotImplementedError, "Chain complex morphisms between chain complexes of different base rings are not implemented."
     122        for i in range(dim_min,dim_max):
     123            try:
     124                matrices[i]
     125            except KeyError:
     126                matrices[i] = matrix.zero_matrix(C.base_ring(),D.differential()[i].ncols(),C.differential()[i].ncols(),sparse=True)
     127            try:
     128                matrices[i+1]
     129            except KeyError:
     130                matrices[i+1] = matrix.zero_matrix(C.base_ring(),D.differential()[i+1].ncols(),C.differential()[i+1].ncols(),sparse=True)
     131            if d==-1:
     132                if (i+1) in C.differential().keys() and (i+1) in D.differential().keys():
     133                    if not matrices[i]*C.differential()[i+1]==D.differential()[i+1]*matrices[i+1]:
     134                        raise ValueError, "Matrices must define a chain complex morphism."
     135                elif (i+1) in C.differential().keys():
     136                    if not matrices[i]*C.differential()[i+1].is_zero():
     137                        raise ValueError, "Matrices must define a chain complex morphism."
     138                elif (i+1) in D.differential().keys():
     139                    if not D.differential()[i+1]*matrices[i+1].is_zero():
     140                        raise ValueError, "Matrices must define a chain complex morphism."
     141            else:
     142                if i in C.differential().keys() and i in D.differential().keys():
     143                    if not matrices[i+1]*C.differential()[i]==D.differential()[i]*matrices[i]:
     144                        raise ValueError, "Matrices must define a chain complex morphism."
     145                elif i in C.differential().keys():
     146                    if not matrices[i+1]*C.differential()[i].is_zero():
     147                        raise ValueError, "Matrices must define a chain complex morphism."
     148                elif i in D.differential().keys():
     149                    if not D.differential()[i]*matrices[i].is_zero():
     150                        raise ValueError, "Matrices must define a chain complex morphism."
     151        self._matrix_dictionary = matrices
     152        self._domain = C
     153        self._codomain = D
     154 
     155    def __neg__(self):
     156        """
     157        Returns -x.
     158
     159        EXAMPLES::
     160
     161            sage: S = simplicial_complexes.Sphere(2)
     162            sage: H = Hom(S,S)
     163            sage: i = H.identity()
     164            sage: x = i.associated_chain_complex_morphism()
     165            sage: w = -x
     166            sage: w._matrix_dictionary
     167            {0: [-1  0  0  0]
     168            [ 0 -1  0  0]
     169            [ 0  0 -1  0]
     170            [ 0  0  0 -1],
     171             1: [-1  0  0  0  0  0]
     172            [ 0 -1  0  0  0  0]
     173            [ 0  0 -1  0  0  0]
     174            [ 0  0  0 -1  0  0]
     175            [ 0  0  0  0 -1  0]
     176            [ 0  0  0  0  0 -1],
     177             2: [-1  0  0  0]
     178            [ 0 -1  0  0]
     179            [ 0  0 -1  0]
     180            [ 0  0  0 -1]}
     181       
     182        """
     183        f = dict()
     184        for i in self._matrix_dictionary.keys():
     185            f[i] = -self._matrix_dictionary[i]
     186        return ChainComplexMorphism(f,self._domain,self._codomain)
     187
     188    def __add__(self,x):
     189        """
     190        Returns self+x.
     191
     192        EXAMPLES::
     193
     194            sage: S = simplicial_complexes.Sphere(2)
     195            sage: H = Hom(S,S)
     196            sage: i = H.identity()
     197            sage: x = i.associated_chain_complex_morphism()
     198            sage: z = x+x
     199            sage: z._matrix_dictionary
     200            {0: [2 0 0 0]
     201            [0 2 0 0]
     202            [0 0 2 0]
     203            [0 0 0 2],
     204             1: [2 0 0 0 0 0]
     205            [0 2 0 0 0 0]
     206            [0 0 2 0 0 0]
     207            [0 0 0 2 0 0]
     208            [0 0 0 0 2 0]
     209            [0 0 0 0 0 2],
     210             2: [2 0 0 0]
     211            [0 2 0 0]
     212            [0 0 2 0]
     213            [0 0 0 2]}
     214
     215        """
     216        if not isinstance(x,ChainComplexMorphism) or self._codomain != x._codomain or self._domain != x._domain or self._matrix_dictionary.keys() != x._matrix_dictionary.keys():
     217            raise TypeError, "Unsupported operation."
     218        f = dict()
     219        for i in self._matrix_dictionary.keys():
     220            f[i] = self._matrix_dictionary[i] + x._matrix_dictionary[i]
     221        return ChainComplexMorphism(f,self._domain,self._codomain)
     222
     223    def __mul__(self,x):
     224        """
     225        Returns self*x if self and x are composable morphisms or if x is an element of the base_ring.
     226
     227        EXAMPLES::
     228            sage: S = simplicial_complexes.Sphere(2)
     229            sage: H = Hom(S,S)
     230            sage: i = H.identity()
     231            sage: x = i.associated_chain_complex_morphism()
     232            sage: y = x*2
     233            sage: y._matrix_dictionary
     234            {0: [2 0 0 0]
     235            [0 2 0 0]
     236            [0 0 2 0]
     237            [0 0 0 2],
     238             1: [2 0 0 0 0 0]
     239            [0 2 0 0 0 0]
     240            [0 0 2 0 0 0]
     241            [0 0 0 2 0 0]
     242            [0 0 0 0 2 0]
     243            [0 0 0 0 0 2],
     244             2: [2 0 0 0]
     245            [0 2 0 0]
     246            [0 0 2 0]
     247            [0 0 0 2]}
     248            sage: z = y*y
     249            sage: z._matrix_dictionary
     250            {0: [4 0 0 0]
     251            [0 4 0 0]
     252            [0 0 4 0]
     253            [0 0 0 4],
     254             1: [4 0 0 0 0 0]
     255            [0 4 0 0 0 0]
     256            [0 0 4 0 0 0]
     257            [0 0 0 4 0 0]
     258            [0 0 0 0 4 0]
     259            [0 0 0 0 0 4],
     260             2: [4 0 0 0]
     261            [0 4 0 0]
     262            [0 0 4 0]
     263            [0 0 0 4]}
     264
     265        """
     266        if not isinstance(x,ChainComplexMorphism) or self._codomain != x._domain:
     267            try:
     268                y = self._domain.base_ring()(x)
     269            except TypeError:
     270                raise TypeError, "Multiplication is not defined."
     271            f = dict()
     272            for i in self._matrix_dictionary.keys():
     273                f[i] = y * self._matrix_dictionary[i]
     274            return ChainComplexMorphism(f,self._domain,self._codomain)
     275        f = dict()
     276        for i in self._matrix_dictionary.keys():
     277            f[i] = x._matrix_dictionary[i]*self._matrix_dictionary[i]
     278        return ChainComplexMorphism(f,self._domain,x._codomain)
     279
     280    def __sub__(self,x):
     281        """
     282        Returns self-x.
     283
     284        EXAMPLES::
     285
     286            sage: S = simplicial_complexes.Sphere(2)
     287            sage: H = Hom(S,S)
     288            sage: i = H.identity()
     289            sage: x = i.associated_chain_complex_morphism()
     290            sage: y = x-x
     291            sage: y._matrix_dictionary
     292            {0: [0 0 0 0]
     293            [0 0 0 0]
     294            [0 0 0 0]
     295            [0 0 0 0],
     296             1: [0 0 0 0 0 0]
     297            [0 0 0 0 0 0]
     298            [0 0 0 0 0 0]
     299            [0 0 0 0 0 0]
     300            [0 0 0 0 0 0]
     301            [0 0 0 0 0 0],
     302             2: [0 0 0 0]
     303            [0 0 0 0]
     304            [0 0 0 0]
     305            [0 0 0 0]}
     306
     307        """   
     308        return self + (-x)
     309
     310    def __eq__(self,x):
     311        """
     312        Returns True if and only if self==x.
     313
     314        EXAMPLES::
     315
     316            sage: S = SimplicialComplex(3)
     317            sage: H = Hom(S,S)
     318            sage: i = H.identity()
     319            sage: x = i.associated_chain_complex_morphism()
     320            sage: x
     321            Chain complex morphism from Chain complex with at most 0 nonzero terms over Integer Ring. to Chain complex with at most 0 nonzero terms over Integer Ring.
     322            sage: f = x._matrix_dictionary
     323            sage: C = S.chain_complex()
     324            sage: G = Hom(C,C)
     325            sage: y = G(f)
     326            sage: x==y
     327            True
     328
     329        """
     330        if not isinstance(x,ChainComplexMorphism) or self._codomain != x._codomain or self._domain != x._domain or self._matrix_dictionary != x._matrix_dictionary:
     331            return False
     332        else:
     333            return True
     334
     335    def _repr_(self):
     336        """
     337        Returns the string representation of self.
     338
     339        EXAMPLES::
     340
     341            sage: S = SimplicialComplex(3)
     342            sage: H = Hom(S,S)
     343            sage: i = H.identity()
     344            sage: x = i.associated_chain_complex_morphism()
     345            sage: x
     346            Chain complex morphism from Chain complex with at most 0 nonzero terms over Integer Ring. to Chain complex with at most 0 nonzero terms over Integer Ring.
     347            sage: x._repr_()
     348            'Chain complex morphism from Chain complex with at most 0 nonzero terms over Integer Ring. to Chain complex with at most 0 nonzero terms over Integer Ring.'
     349
     350        """
     351        return "Chain complex morphism from " + self._domain._repr_() + " to " + self._codomain._repr_()
  • sage/homology/simplicial_complex.py

    diff -r f872a92f5f9a -r 6014c5979a59 sage/homology/simplicial_complex.py
    a b  
    16621662                faces.append(Simplex(list(f.set().difference(s.set()))))
    16631663        return SimplicialComplex(self.vertices(), faces)
    16641664
     1665    def effective_vertices(self):
     1666        """
     1667        The set of vertices belonging to some face. Returns a Simplex.
     1668
     1669        EXAMPLES::
     1670
     1671            sage: S = SimplicialComplex(15)
     1672            sage: S
     1673            Simplicial complex with 16 vertices and facets {()}
     1674            sage: S.effective_vertices()
     1675            ()
     1676
     1677            sage: S = SimplicialComplex(15,[[0,1,2,3],[6,7]])
     1678            sage: S
     1679            Simplicial complex with 16 vertices and facets {(6, 7), (0, 1, 2, 3)}
     1680            sage: S.effective_vertices()
     1681            (0, 1, 2, 3, 6, 7)
     1682
     1683            sage: type(S.effective_vertices())
     1684            <class 'sage.homology.simplicial_complex.Simplex'>
     1685
     1686        """
     1687        try:
     1688            v = self.faces()[0]
     1689        except KeyError:
     1690            return Simplex(-1)
     1691        f = []
     1692        for i in v:
     1693            f.append(i[0])
     1694        return Simplex(set(f))
     1695
     1696
     1697    def generated_subcomplex(self,sub_vertex_set):
     1698        """
     1699        Returns the largest sub SimplicialComplex of self containing exactly the sub_vertex_set as vertices.
     1700
     1701        EXAMPLES::
     1702
     1703            sage: S = simplicial_complexes.Sphere(2)
     1704            sage: S
     1705            Simplicial complex with vertex set (0, 1, 2, 3) and facets {(0, 2, 3), (0, 1, 2), (1, 2, 3), (0, 1, 3)}
     1706            sage: S.generated_subcomplex([0,1,2])
     1707            Simplicial complex with vertex set (0, 1, 2) and facets {(0, 1, 2)}
     1708
     1709        """
     1710        if not self.vertices().set().issuperset(sub_vertex_set):
     1711            raise TypeError, "input must be a subset of the vertex set."
     1712        faces = []
     1713        for i in range(self.dimension()+1):
     1714            for j in self.faces()[i]:
     1715                if j.set().issubset(sub_vertex_set):
     1716                    faces.append(j)
     1717        return SimplicialComplex(sub_vertex_set,faces,maximality_check=True)
     1718
    16651719    def _complement(self, simplex):
    16661720        """
    16671721        Return the complement of a simplex in the vertex set of this
  • new file sage/homology/simplicial_complex_homset.py

    diff -r f872a92f5f9a -r 6014c5979a59 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 f872a92f5f9a -r 6014c5979a59 sage/homology/simplicial_complex_morphism.py
    - +  
     1r"""
     2Morphisms of simplicial complexes
     3
     4AUTHORS:
     5
     6- 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.fiber_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.fiber_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
     95from sage.rings.integer_ring import ZZ
     96from sage.homology.chain_complex_morphism import ChainComplexMorphism
     97
     98def is_SimplicialComplexMorphism(x):
     99    """
     100    Returns True if and only if x is a morphism of simplicial complexes.
     101
     102    EXAMPLES::
     103
     104        sage: from sage.homology.simplicial_complex_morphism import is_SimplicialComplexMorphism
     105        sage: S = SimplicialComplex(5,[[0,1],[3,4]])
     106        sage: H = Hom(S,S)
     107        sage: f = {0:0,1:1,2:2,3:3,4:4,5:5}
     108        sage: x = H(f)
     109        sage: is_SimplicialComplexMorphism(x)
     110        True
     111
     112    """
     113    return isinstance(x,SimplicialComplexMorphism)
     114
     115class SimplicialComplexMorphism(category_types.SageObject):
     116    """
     117    An element of this class is a morphism of simplicial complexes.
     118    """
     119    def __init__(self,f,X,Y):
     120        """
     121        Input is a dictionary f, the domain, and the codomain.
     122
     123        One can define the dictionary either on the vertices of X or on the effective vertices of X (X.effective_vertices()). Note that this
     124        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.
     125        This is because two SimplicialComplexes with the same faces but different vertex sets are not equal.
     126
     127        EXAMPLES::
     128
     129            sage: S = SimplicialComplex(5,[[0,1],[3,4]])
     130            sage: H = Hom(S,S)
     131            sage: f = {0:0,1:1,2:2,3:3,4:4,5:5}
     132            sage: g = {0:0,1:1,3:3,4:4}
     133            sage: x = H(f)
     134            sage: y = H(g)
     135            sage: x==y
     136            False
     137            sage: x.image()
     138            Simplicial complex with vertex set (0, 1, 2, 3, 4, 5) and facets {(3, 4), (0, 1)}
     139            sage: y.image()
     140            Simplicial complex with vertex set (0, 1, 3, 4) and facets {(3, 4), (0, 1)}
     141            sage: x.image()==y.image()
     142            False
     143
     144        """
     145        if not isinstance(X,simplicial_complex.SimplicialComplex) or not isinstance(Y,simplicial_complex.SimplicialComplex):
     146            raise ValueError, "X and Y must be SimplicialComplexes."
     147        if not set(f.keys())==X._vertex_set.set() and not set(f.keys())==X.effective_vertices().set():
     148            raise ValueError, "f must be a dictionary from the vertex set of X to single values in the vertex set of Y."
     149        dim = X.dimension()
     150        Y_faces = Y.faces()
     151        for k in range(dim+1):
     152            for i in X.faces()[k]:
     153                tup = i.tuple()
     154                fi = []
     155                for j in tup:
     156                    fi.append(f[j])
     157                v = simplicial_complex.Simplex(set(fi))
     158            if not v in Y_faces[v.dimension()]:
     159                raise ValueError, "f must be a dictionary from the vertices of X to the vertices of Y."
     160        self._vertex_dictionary = f
     161        self._domain = X
     162        self._codomain = Y
     163   
     164    def __eq__(self,x):
     165        """
     166        Returns True if and only if self == x.
     167       
     168        EXAMPLES::
     169
     170            sage: S = simplicial_complexes.Sphere(2)
     171            sage: H = Hom(S,S)
     172            sage: i = H.identity()
     173            sage: i
     174            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)}
     175            sage: f = {0:0,1:1,2:2,3:2}
     176            sage: j = H(f)
     177            sage: i==j
     178            False
     179           
     180            sage: T = SimplicialComplex(3,[[1,2]])
     181            sage: T
     182            Simplicial complex with vertex set (0, 1, 2, 3) and facets {(1, 2)}
     183            sage: G = Hom(T,T)
     184            sage: k = G.identity()
     185            sage: g = {0:0,1:1,2:2,3:3}
     186            sage: l = G(g)
     187            sage: k==l
     188            True
     189
     190        """
     191        if not isinstance(x,SimplicialComplexMorphism) or self._codomain != x._codomain or self._domain != x._domain or self._vertex_dictionary != x._vertex_dictionary:
     192            return False
     193        else:
     194            return True
     195
     196    def __call__(self,x):
     197        """
     198        Input is a simplex of the domain. Output is the image simplex.
     199       
     200        EXAMPLES::
     201
     202            sage: S = simplicial_complexes.Sphere(2)
     203            sage: T = simplicial_complexes.Sphere(3)
     204            sage: S
     205            Simplicial complex with vertex set (0, 1, 2, 3) and facets {(0, 2, 3), (0, 1, 2), (1, 2, 3), (0, 1, 3)}
     206            sage: T
     207            Simplicial complex with vertex set (0, 1, 2, 3, 4) and 5 facets
     208            sage: f = {0:0,1:1,2:2,3:3}
     209            sage: H = Hom(S,T)
     210            sage: x = H(f)
     211            sage: from sage.homology.simplicial_complex import Simplex
     212            sage: x(Simplex([0,2,3]))
     213            (0, 2, 3)
     214
     215        """
     216        dim = self._domain.dimension()
     217        if not isinstance(x,simplicial_complex.Simplex) or x.dimension() > dim or not x in self._domain.faces()[x.dimension()]:
     218            raise ValueError, "x must be a simplex of the source of f"
     219        tup=x.tuple()
     220        fx=[]
     221        for j in tup:
     222            fx.append(self._vertex_dictionary[j])
     223        return simplicial_complex.Simplex(set(fx))
     224
     225    def _repr_(self):
     226        """
     227        Print representation
     228
     229        EXAMPLES::
     230
     231            sage: S = simplicial_complexes.Sphere(2)
     232            sage: H = Hom(S,S)
     233            sage: i = H.identity()
     234            sage: i
     235            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)}
     236            sage: i._repr_()
     237            '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)}'
     238 
     239
     240        """
     241        return "Simplicial complex morphism " + str(self._vertex_dictionary) + " from " + self._domain._repr_() + " to " + self._codomain._repr_()
     242
     243    def associated_chain_complex_morphism(self,base_ring=ZZ,augmented=False,cochain=False):
     244        """
     245        Returns the associated chain complex morphism of self.
     246
     247        EXAMPLES::
     248
     249            sage: S = simplicial_complexes.Sphere(1)
     250            sage: T = simplicial_complexes.Sphere(2)
     251            sage: H = Hom(S,T)
     252            sage: f = {0:0,1:1,2:2}
     253            sage: x = H(f)
     254            sage: x
     255            Simplicial complex morphism {0: 0, 1: 1, 2: 2} 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)}
     256            sage: a = x.associated_chain_complex_morphism()
     257            sage: a
     258            Chain complex morphism from Chain complex with at most 2 nonzero terms over Integer Ring. to Chain complex with at most 3 nonzero terms over Integer Ring.
     259            sage: a._matrix_dictionary
     260            {0: [0 0 0]
     261            [0 1 0]
     262            [0 0 1]
     263            [1 0 0],
     264             1: [0 0 0]
     265            [0 1 0]
     266            [0 0 0]
     267            [1 0 0]
     268            [0 0 0]
     269            [0 0 1],
     270             2: []}
     271            sage: x.associated_chain_complex_morphism(augmented=True)
     272            Chain complex morphism from Chain complex with at most 3 nonzero terms over Integer Ring. to Chain complex with at most 4 nonzero terms over Integer Ring.
     273            sage: x.associated_chain_complex_morphism(cochain=True)
     274            Chain complex morphism from Chain complex with at most 3 nonzero terms over Integer Ring. to Chain complex with at most 2 nonzero terms over Integer Ring.
     275            sage: x.associated_chain_complex_morphism(augmented=True,cochain=True)
     276            Chain complex morphism from Chain complex with at most 4 nonzero terms over Integer Ring. to Chain complex with at most 3 nonzero terms over Integer Ring.
     277            sage: x.associated_chain_complex_morphism(base_ring=GF(11))
     278            Chain complex morphism from Chain complex with at most 2 nonzero terms over Finite Field of size 11. to Chain complex with at most 3 nonzero terms over Finite Field of size 11.
     279
     280        """
     281        max_dim = max(self._domain.dimension(),self._codomain.dimension())
     282        min_dim = min(self._domain.dimension(),self._codomain.dimension())
     283        matrices = {}
     284        if augmented is True:
     285            m = matrix.Matrix(base_ring,1,1,1)
     286            if not cochain:
     287                matrices[-1] = m
     288            else:
     289                matrices[-1] = m.transpose()
     290        for dim in range(min_dim+1):
     291            X_faces = list(self._domain.faces()[dim])
     292            Y_faces = list(self._codomain.faces()[dim])
     293            num_faces_X = len(X_faces)
     294            num_faces_Y = len(Y_faces)
     295            mval = [0 for i in range(num_faces_X*num_faces_Y)]
     296            for i in X_faces:
     297                y = self(i)
     298                if y.dimension() < dim:
     299                    pass
     300                else:
     301                    mval[X_faces.index(i)+(Y_faces.index(y)*num_faces_X)] = 1
     302            m = matrix.Matrix(base_ring,num_faces_Y,num_faces_X,mval,sparse=True)
     303            if not cochain:
     304                matrices[dim] = m
     305            else:
     306                matrices[dim] = m.transpose()
     307        for dim in range(min_dim+1,max_dim+1):
     308            try:
     309                l1 = len(self._codomain.faces()[dim])
     310            except KeyError:
     311                l1 = 0
     312            try:
     313                l2 = len(self._domain.faces()[dim])
     314            except KeyError:
     315                l2 = 0
     316            m = matrix.zero_matrix(base_ring,l1,l2,sparse=True)
     317            if not cochain:
     318                matrices[dim] = m
     319            else:
     320                matrices[dim] = m.transpose()
     321        if not cochain:
     322            return ChainComplexMorphism(matrices,\
     323                    self._domain.chain_complex(base_ring=base_ring,augmented=augmented,cochain=cochain),\
     324                    self._codomain.chain_complex(base_ring=base_ring,augmented=augmented,cochain=cochain))
     325        else:
     326            return ChainComplexMorphism(matrices,\
     327                    self._codomain.chain_complex(base_ring=base_ring,augmented=augmented,cochain=cochain),\
     328                    self._domain.chain_complex(base_ring=base_ring,augmented=augmented,cochain=cochain))
     329       
     330    def image(self):
     331        """
     332        Computes the image simplicial complex of f.
     333       
     334        EXAMPLES::
     335
     336            sage: S = SimplicialComplex(3,[[0,1],[2,3]])
     337            sage: T = SimplicialComplex(1,[[0,1]])
     338            sage: f = {0:0,1:1,2:0,3:1}
     339            sage: H = Hom(S,T)
     340            sage: x = H(f)
     341            sage: x.image()
     342            Simplicial complex with vertex set (0, 1) and facets {(0, 1)}
     343
     344            sage: S = SimplicialComplex(2)
     345            sage: H = Hom(S,S)
     346            sage: i = H.identity()
     347            sage: i.image()
     348            Simplicial complex with vertex set (0, 1, 2) and facets {()}
     349            sage: i.is_surjective()
     350            True
     351            sage: S = SimplicialComplex(5,[[0,1]])
     352            sage: T = SimplicialComplex(3,[[0,1]])
     353            sage: f = {0:0,1:1}
     354            sage: g = {0:0,1:1,2:2,3:3,4:4,5:5}
     355            sage: H = Hom(S,T)
     356            sage: x = H(f)
     357            sage: y = H(g)
     358            sage: x == y
     359            False
     360            sage: x.image()
     361            Simplicial complex with vertex set (0, 1) and facets {(0, 1)}
     362            sage: y.image()
     363            Simplicial complex with vertex set (0, 1, 2, 3, 4, 5) and facets {(0, 1)}
     364
     365        """
     366        fa = [self(i) for i in self._domain.facets()]
     367        return simplicial_complex.SimplicialComplex(set(self._vertex_dictionary.values()),fa,maximality_check=True)
     368
     369    def domain(self):
     370        """
     371        Returns the domain of the morphism.
     372
     373        EXAMPLES::
     374
     375            sage: S = SimplicialComplex(3,[[0,1],[2,3]])
     376            sage: T = SimplicialComplex(1,[[0,1]])
     377            sage: f = {0:0,1:1,2:0,3:1}
     378            sage: H = Hom(S,T)
     379            sage: x = H(f)
     380            sage: x.domain()
     381            Simplicial complex with vertex set (0, 1, 2, 3) and facets {(2, 3), (0, 1)}
     382
     383        """
     384        return self._domain
     385
     386    def codomain(self):
     387        """
     388        Returns the codomain of the morphism.
     389
     390        EXAMPLES::
     391
     392            sage: S = SimplicialComplex(3,[[0,1],[2,3]])
     393            sage: T = SimplicialComplex(1,[[0,1]])
     394            sage: f = {0:0,1:1,2:0,3:1}
     395            sage: H = Hom(S,T)
     396            sage: x = H(f)
     397            sage: x.codomain()
     398            Simplicial complex with vertex set (0, 1) and facets {(0, 1)}
     399
     400        """
     401        return self._codomain
     402       
     403    def is_surjective(self):
     404        """
     405        Returns True if and only if self is surjective.
     406
     407        EXAMPLES::
     408
     409            sage: S = SimplicialComplex(3,[(0,1,2)])
     410            sage: S
     411            Simplicial complex with vertex set (0, 1, 2, 3) and facets {(0, 1, 2)}
     412            sage: T = SimplicialComplex(2,[(0,1)])
     413            sage: T
     414            Simplicial complex with vertex set (0, 1, 2) and facets {(0, 1)}
     415            sage: H = Hom(S,T)
     416            sage: x = H({0:0,1:1,2:1,3:2})
     417            sage: x.is_surjective()
     418            True
     419
     420            sage: S = SimplicialComplex(3,[[0,1],[2,3]])
     421            sage: T = SimplicialComplex(1,[[0,1]])
     422            sage: f = {0:0,1:1,2:0,3:1}
     423            sage: H = Hom(S,T)
     424            sage: x = H(f)
     425            sage: x.is_surjective()
     426            True
     427
     428        """   
     429        return self._codomain == self.image()
     430       
     431    def is_injective(self):
     432        """
     433        Returns True if and only if self is injective.
     434
     435        EXAMPLES::
     436
     437            sage: S = simplicial_complexes.Sphere(1)
     438            sage: T = simplicial_complexes.Sphere(2)
     439            sage: U = simplicial_complexes.Sphere(3)
     440            sage: H = Hom(T,S)
     441            sage: G = Hom(T,U)
     442            sage: f = {0:0,1:1,2:0,3:1}
     443            sage: x = H(f)
     444            sage: g = {0:0,1:1,2:2,3:3}
     445            sage: y = G(g)
     446            sage: x.is_injective()
     447            False
     448            sage: y.is_injective()
     449            True
     450
     451        """
     452        v = [self._vertex_dictionary[i[0]] for i in self._domain.faces()[0]]
     453        for i in v:
     454            if v.count(i) > 1:
     455                return False
     456        return True
     457
     458    def is_identity(self):
     459        """
     460        If x is an identity morphism, returns True. Otherwise, False.
     461
     462        EXAMPLES::
     463
     464            sage: T = simplicial_complexes.Sphere(1)
     465            sage: G = Hom(T,T)
     466            sage: T
     467            Simplicial complex with vertex set (0, 1, 2) and facets {(1, 2), (0, 2), (0, 1)}
     468            sage: j = G({0:0,1:1,2:2})
     469            sage: j.is_identity()
     470            True
     471
     472            sage: S = simplicial_complexes.Sphere(2)
     473            sage: T = simplicial_complexes.Sphere(3)
     474            sage: H = Hom(S,T)
     475            sage: f = {0:0,1:1,2:2,3:3}
     476            sage: x = H(f)
     477            sage: x
     478            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
     479            sage: x.is_identity()
     480            False
     481
     482        """
     483        if self._domain != self._codomain:
     484            return False
     485        else:
     486            f = dict()
     487            for i in self._domain.vertices().set():
     488                f[i] = i
     489            if self._vertex_dictionary != f:
     490                return False
     491            else:
     492                return True
     493
     494    def fiber_product(self,other,rename_vertices = True):
     495        """
     496        Fiber product of self and other. Both morphisms should have the same codomain. The method returns a morphism of simplicial complexes, which
     497        is the morphism from the space of the fiber product to the codomain.
     498
     499        EXAMPLES::
     500           
     501            sage: S = SimplicialComplex(2,[[0,1],[1,2]])
     502            sage: T = SimplicialComplex(2,[[0,2]])
     503            sage: U = SimplicialComplex(1,[[0,1]])
     504            sage: H = Hom(S,U)
     505            sage: G = Hom(T,U)
     506            sage: f = {0:0,1:1,2:0}
     507            sage: g = {0:0,1:1,2:1}
     508            sage: x = H(f)
     509            sage: y = G(g)
     510            sage: z = x.fiber_product(y)
     511            sage: z
     512            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)}
     513
     514        """
     515        if self._codomain != other._codomain:
     516            raise ValueError, "self and other must have the same codomain."
     517        X = self._domain.product(other._domain,rename_vertices = rename_vertices)
     518        v = []
     519        f = dict()
     520        eff1 = self._domain.effective_vertices()
     521        eff2 = other._domain.effective_vertices()
     522        for i in eff1:
     523            for j in eff2:
     524                if self(simplicial_complex.Simplex([i])) == other(simplicial_complex.Simplex([j])):
     525                    if rename_vertices:
     526                        v.append("L"+str(i)+"R"+str(j))
     527                        f["L"+str(i)+"R"+str(j)] = self._vertex_dictionary[i]
     528                    else:
     529                        v.append((i,j))
     530                        f[(i,j)] = self._vertex_dictionary[i]
     531        return SimplicialComplexMorphism(f,X.generated_subcomplex(v),self._codomain)