152152from __future__ import print_function , absolute_import
153153from six .moves import range
154154from six import integer_types
155+ from operator import index as PyNumber_Index
155156
156157# possible future directions for SimplicialComplex:
157158#
@@ -828,7 +829,7 @@ class SimplicialComplex(Parent, GenericCellComplex):
828829 :param maximality_check: see below
829830 :type maximality_check: boolean; optional, default ``True``
830831 :param sort_facets: see below
831- :type sort_facets: boolean; optional, default ``True``
832+ :type sort_facets: boolean or sorting key ; optional, default ``True``
832833 :param name_check: see below
833834 :type name_check: boolean; optional, default ``False``
834835 :param is_mutable: Set to ``False`` to make this immutable
@@ -857,8 +858,9 @@ class SimplicialComplex(Parent, GenericCellComplex):
857858 this class may fail if faces which are claimed to be maximal are
858859 in fact not.
859860
860- If ``sort_facets`` is ``True``, sort the vertices in each facet. If
861- the vertices in different facets are not ordered compatibly (e.g.,
861+ If ``sort_facets`` is ``True``, sort the vertices. You can also
862+ specify a sorting key as ``sort_facets``, which is then used to sort.
863+ If the vertices in different facets are not ordered compatibly (e.g.,
862864 if you have facets ``(1, 3, 5)`` and ``(5, 3, 8)``), then homology
863865 calculations may have unpredictable results.
864866
@@ -908,6 +910,11 @@ class SimplicialComplex(Parent, GenericCellComplex):
908910 sage: SimplicialComplex(from_characteristic_function=(f, l.ground_set()))
909911 Simplicial complex with 21 vertices and 168 facets
910912
913+ The vertices can be sorted with a custom key::
914+
915+ sage: SimplicialComplex([10], sort_facets=str)
916+ Simplicial complex with 11 vertices and facets {(0, 1, 10, 2, 3, 4, 5, 6, 7, 8, 9)}
917+
911918 TESTS:
912919
913920 Check that we can make mutable copies (see :trac:`14142`)::
@@ -974,6 +981,13 @@ def __init__(self,
974981
975982 sage: TestSuite(S).run()
976983 sage: TestSuite(S3).run()
984+
985+ ::
986+
987+ sage: SimplicialComplex([2], sort_facets="bogus")
988+ Traceback (most recent call last):
989+ ...
990+ TypeError: sort_facets should be a boolean or callable, not 'bogus'
977991 """
978992 if (maximal_faces is not None and
979993 from_characteristic_function is not None ):
@@ -1014,15 +1028,26 @@ def __init__(self,
10141028 self ._sorted = False
10151029 return
10161030
1017- if isinstance (vertex_set , (int , Integer )):
1018- vertices = tuple (range (vertex_set + 1 ))
1019- elif sort_facets :
1020- try :
1021- vertices = tuple (sorted (vertex_set ))
1022- except TypeError :
1023- vertices = tuple (sorted (vertex_set , key = str ))
1031+ try :
1032+ # Check whether vertex_set is an integer
1033+ n = PyNumber_Index (vertex_set )
1034+ except TypeError :
1035+ pass
10241036 else :
1025- vertices = tuple (vertex_set )
1037+ vertex_set = range (n + 1 )
1038+
1039+ if sort_facets is True :
1040+ vertex_set = sorted (vertex_set )
1041+ elif callable (sort_facets ):
1042+ vertex_set = sorted (vertex_set , key = sort_facets )
1043+ elif not sort_facets :
1044+ # Ensure that sort_facets is either a callable or boolean
1045+ sort_facets = False
1046+ else :
1047+ raise TypeError ("sort_facets should be a boolean or callable, not {!r}"
1048+ .format (sort_facets ))
1049+ vertices = tuple (vertex_set )
1050+
10261051 gen_dict = {}
10271052 for v in vertices :
10281053 if name_check :
@@ -1050,11 +1075,10 @@ def __init__(self,
10501075 if (maximality_check and
10511076 any (face .is_face (other ) for other in good_faces )):
10521077 continue
1053- if sort_facets :
1054- try :
1055- face = Simplex (sorted (face .tuple ()))
1056- except TypeError :
1057- face = Simplex (sorted (face .tuple (), key = str ))
1078+ if sort_facets is True :
1079+ face = Simplex (sorted (face .tuple ()))
1080+ elif sort_facets is not False :
1081+ face = Simplex (sorted (face .tuple (), key = sort_facets ))
10581082 good_faces .append (face )
10591083
10601084 # if no maximal faces, add the empty face as a facet
@@ -1065,8 +1089,8 @@ def __init__(self,
10651089 self ._vertex_set = vertices
10661090 # self._facets: unsorted list of facets
10671091 self ._facets = good_faces
1068- # self._sorted: True if the vertex set should be sorted. This
1069- # gets used by the add_face method.
1092+ # self._sorted: True if the vertex set should be sorted or
1093+ # sorting key. This gets used by the add_face method.
10701094 self ._sorted = sort_facets
10711095 # self._faces: dictionary of dictionaries of faces. The main
10721096 # dictionary is keyed by subcomplexes, and each value is a
@@ -2477,10 +2501,12 @@ def add_face(self, face):
24772501 if not self ._is_mutable :
24782502 raise ValueError ("This simplicial complex is not mutable" )
24792503
2480- if self ._sorted :
2504+ if self ._sorted is True :
24812505 new_face = Simplex (sorted (face ))
2482- else :
2506+ elif self . _sorted is False :
24832507 new_face = Simplex (face )
2508+ else :
2509+ new_face = Simplex (sorted (face , key = self ._sorted ))
24842510
24852511 face_is_maximal = True
24862512 for other in self ._facets :
@@ -4187,7 +4213,7 @@ def _is_numeric(self):
41874213
41884214 EXAMPLES::
41894215
4190- sage: s = SimplicialComplex()
4216+ sage: s = SimplicialComplex(sort_facets=str )
41914217 sage: s._is_numeric()
41924218 True
41934219 sage: s.add_face(['a', 'b', 123])
@@ -4212,7 +4238,7 @@ def _translation_to_numeric(self):
42124238
42134239 EXAMPLES::
42144240
4215- sage: s = SimplicialComplex()
4241+ sage: s = SimplicialComplex(sort_facets=str )
42164242 sage: s._translation_to_numeric()
42174243 {}
42184244 sage: s.add_face(['a', 'b', 123])
@@ -4240,7 +4266,7 @@ def _translation_from_numeric(self):
42404266
42414267 EXAMPLES::
42424268
4243- sage: s = SimplicialComplex()
4269+ sage: s = SimplicialComplex(sort_facets=str )
42444270 sage: s._translation_from_numeric()
42454271 {}
42464272 sage: s.add_face(['a', 'b', 123])
0 commit comments