2222from sage .graphs .digraph import DiGraph
2323from sage .matrix .constructor import matrix
2424from sage .rings .integer_ring import ZZ
25+ from sage .rings .finite_rings .finite_field_constructor import GF
2526from sage .misc .lazy_attribute import lazy_attribute
2627from sage .misc .cachefunc import cached_method
2728from sage .misc .rest_index_of_methods import gen_rest_table_index
@@ -300,7 +301,7 @@ def is_lequal(self, i, j):
300301 .. note::
301302
302303 If the :meth:`lequal_matrix` has been computed, then this method is
303- redefined to use the cached matrix (see :meth:`_alternate_is_lequal`).
304+ redefined to use the cached data (see :meth:`_alternate_is_lequal`).
304305
305306 TESTS::
306307
@@ -974,7 +975,12 @@ def moebius_function_matrix(self, algorithm='recursive'):
974975
975976 .. TODO::
976977
977- Use an inversion algorithm for triangular matrices.
978+ Try to make a specific multimodular matrix inversion
979+ algorithm for this kind of sparse triangular matrices
980+ where the non-zero entries of the inverse are in known
981+ positions.
982+
983+ .. SEEALSO:: :meth:`lequal_matrix`, :meth:`coxeter_transformation`
978984
979985 EXAMPLES::
980986
@@ -1011,10 +1017,11 @@ def moebius_function_matrix(self, algorithm='recursive'):
10111017 if not hasattr (self , '_moebius_function_matrix' ):
10121018 if algorithm == 'recursive' :
10131019 n = self .cardinality ()
1014- L = self .lequal_matrix ()
1015- m = L . dict ( copy = True )
1016- greater_than = [ sorted ( L [ i ]. dict ()) for i in range ( n )]
1020+ gt = self ._leq_storage
1021+ greater_than = [ sorted ( gt [ i ]) for i in range ( n )]
1022+ m = {}
10171023 for i in range (n - 1 , - 1 , - 1 ):
1024+ m [(i , i )] = ZZ .one ()
10181025 for k in greater_than [i ]:
10191026 if k != i :
10201027 m [(i , k )] = - ZZ .sum (m [(j , k )]
@@ -1057,6 +1064,8 @@ def coxeter_transformation(self):
10571064 the Grothendieck group of the derived category of modules on the
10581065 poset, in the basis of simple modules.
10591066
1067+ .. SEEALSO:: :meth:`lequal_matrix`, :meth:`moebius_function_matrix`
1068+
10601069 EXAMPLES::
10611070
10621071 sage: M = posets.PentagonPoset()._hasse_diagram.coxeter_transformation(); M
@@ -1130,17 +1139,45 @@ def principal_order_ideal(self, i):
11301139 return self .order_ideal ([i ])
11311140
11321141 @lazy_attribute
1133- def _leq_matrix (self ):
1142+ def _leq_storage (self ):
1143+ """
1144+ Store the comparison relation as a list of Python sets.
1145+
1146+ The `i`-th item in the list is the set of elements greater than `i`.
1147+
1148+ EXAMPLES::
1149+
1150+ sage: H = posets.DiamondPoset(7)._hasse_diagram
1151+ sage: H._leq_storage
1152+ [{0, 1, 2, 3, 4, 5, 6}, {1, 6}, {2, 6}, {3, 6}, {4, 6}, {5, 6}, {6}]
1153+ """
1154+ n = self .order ()
1155+ greater_than = [set ([i ]) for i in range (n )]
1156+ for i in range (n - 1 , - 1 , - 1 ):
1157+ gt = greater_than [i ]
1158+ for j in self .neighbors_out (i ):
1159+ gt = gt .union (greater_than [j ])
1160+ greater_than [i ] = gt
1161+
1162+ # Redefine self.is_lequal
1163+ self .is_lequal = self ._alternate_is_lequal
1164+
1165+ return greater_than
1166+
1167+ @lazy_attribute
1168+ def _leq_matrix_boolean (self ):
11341169 r"""
1135- Computes a matrix whose ``(i,j)`` entry is 1 if ``i`` is less than
1136- ``j`` in the poset, and 0 otherwise; and redefines ``__lt__`` to
1137- use this matrix.
1170+ Compute a boolean matrix whose ``(i,j)`` entry is 1 if ``i``
1171+ is less than ``j`` in the poset, and 0 otherwise; and
1172+ redefines ``__lt__`` to use this matrix.
1173+
1174+ .. SEEALSO:: :meth:`_leq_matrix`
11381175
11391176 EXAMPLES::
11401177
11411178 sage: P = Poset([[1,3,2],[4],[4,5,6],[6],[7],[7],[7],[]])
11421179 sage: H = P._hasse_diagram
1143- sage: H._leq_matrix
1180+ sage: M = H._leq_matrix_boolean; M
11441181 [1 1 1 1 1 1 1 1]
11451182 [0 1 0 1 0 0 0 1]
11461183 [0 0 1 1 1 0 1 1]
@@ -1149,32 +1186,70 @@ def _leq_matrix(self):
11491186 [0 0 0 0 0 1 1 1]
11501187 [0 0 0 0 0 0 1 1]
11511188 [0 0 0 0 0 0 0 1]
1189+ sage: M.base_ring()
1190+ Finite Field of size 2
1191+ """
1192+ n = self .order ()
1193+ R = GF (2 )
1194+ one = R .one ()
1195+ greater_than = self ._leq_storage
1196+ D = {(i , j ): one for i in range (n ) for j in greater_than [i ]}
1197+ M = matrix (R , n , n , D , sparse = True )
1198+ M .set_immutable ()
1199+ return M
1200+
1201+ @lazy_attribute
1202+ def _leq_matrix (self ):
1203+ r"""
1204+ Compute an integer matrix whose ``(i,j)`` entry is 1 if ``i``
1205+ is less than ``j`` in the poset, and 0 otherwise.
11521206
1207+ .. SEEALSO:: :meth:`_leq_matrix_boolean`
1208+
1209+ EXAMPLES::
1210+
1211+ sage: P = Poset([[1,3,2],[4],[4,5,6],[6],[7],[7],[7],[]])
1212+ sage: H = P._hasse_diagram
1213+ sage: M = H._leq_matrix; M
1214+ [1 1 1 1 1 1 1 1]
1215+ [0 1 0 1 0 0 0 1]
1216+ [0 0 1 1 1 0 1 1]
1217+ [0 0 0 1 0 0 0 1]
1218+ [0 0 0 0 1 0 0 1]
1219+ [0 0 0 0 0 1 1 1]
1220+ [0 0 0 0 0 0 1 1]
1221+ [0 0 0 0 0 0 0 1]
1222+ sage: M.base_ring()
1223+ Integer Ring
11531224 """
1154- # Create the matrix
11551225 n = self .order ()
1156- D = {}
1157- for i in range (n ):
1158- for v in self .breadth_first_search (i ):
1159- D [(i , v )] = 1
1226+ one = ZZ .one ()
1227+ greater_than = self ._leq_storage
1228+ D = {(i , j ): one for i in range (n ) for j in greater_than [i ]}
11601229 M = matrix (ZZ , n , n , D , sparse = True )
11611230 M .set_immutable ()
1162- # Redefine self.is_lequal
1163- self .is_lequal = self ._alternate_is_lequal
1164- # Return the matrix
11651231 return M
11661232
1167- def lequal_matrix (self ):
1233+ def lequal_matrix (self , boolean = False ):
11681234 """
1169- Return the matrix whose ``(i,j)`` entry is 1 if ``i`` is less
1235+ Return a matrix whose ``(i,j)`` entry is 1 if ``i`` is less
11701236 than ``j`` in the poset, and 0 otherwise; and redefines
1171- ``__lt__`` to use this matrix.
1237+ ``__lt__`` to use the boolean version of this matrix.
1238+
1239+ INPUT:
1240+
1241+ - ``boolean`` -- optional flag (default ``False``) telling whether to
1242+ return a matrix with coefficients in `\GF(2)` or in `\ZZ`
1243+
1244+ .. SEEALSO::
1245+
1246+ :meth:`moebius_function_matrix`, :meth:`coxeter_transformation`
11721247
11731248 EXAMPLES::
11741249
11751250 sage: P = Poset([[1,3,2],[4],[4,5,6],[6],[7],[7],[7],[]])
11761251 sage: H = P._hasse_diagram
1177- sage: H.lequal_matrix()
1252+ sage: M = H.lequal_matrix(); M
11781253 [1 1 1 1 1 1 1 1]
11791254 [0 1 0 1 0 0 0 1]
11801255 [0 0 1 1 1 0 1 1]
@@ -1183,13 +1258,24 @@ def lequal_matrix(self):
11831258 [0 0 0 0 0 1 1 1]
11841259 [0 0 0 0 0 0 1 1]
11851260 [0 0 0 0 0 0 0 1]
1261+ sage: M.base_ring()
1262+ Integer Ring
1263+
1264+ sage: P = posets.DiamondPoset(6)
1265+ sage: H = P._hasse_diagram
1266+ sage: M = H.lequal_matrix(boolean=True)
1267+ sage: M.base_ring()
1268+ Finite Field of size 2
11861269
11871270 TESTS::
11881271
11891272 sage: H.lequal_matrix().is_immutable()
11901273 True
11911274 """
1192- return self ._leq_matrix
1275+ if boolean :
1276+ return self ._leq_matrix_boolean
1277+ else :
1278+ return self ._leq_matrix
11931279
11941280 def _alternate_is_lequal (self , i , j ):
11951281 r"""
@@ -1199,7 +1285,7 @@ def _alternate_is_lequal(self, i, j):
11991285 .. NOTE::
12001286
12011287 If the :meth:`lequal_matrix` has been computed, then
1202- :meth:`is_lequal` is redefined to use the cached matrix .
1288+ :meth:`is_lequal` is redefined to use the cached data .
12031289
12041290 EXAMPLES::
12051291
@@ -1223,7 +1309,7 @@ def _alternate_is_lequal(self, i, j):
12231309 sage: H._alternate_is_lequal(z,z)
12241310 True
12251311 """
1226- return bool ( self ._leq_matrix [ i , j ])
1312+ return j in self ._leq_storage [ i ]
12271313
12281314 def prime_elements (self ):
12291315 r"""
@@ -2026,7 +2112,7 @@ def are_incomparable(self, i, j):
20262112 sage: [ (i,j) for i in H.vertices() for j in H.vertices() if H.are_incomparable(i,j)]
20272113 [(1, 2), (1, 3), (2, 1), (3, 1)]
20282114 """
2029- mat = self ._leq_matrix
2115+ mat = self ._leq_matrix_boolean
20302116 return not mat [i , j ] and not mat [j , i ]
20312117
20322118 def are_comparable (self , i , j ):
@@ -2046,7 +2132,7 @@ def are_comparable(self, i, j):
20462132 sage: [ (i,j) for i in H.vertices() for j in H.vertices() if H.are_comparable(i,j)]
20472133 [(0, 0), (0, 1), (0, 2), (0, 3), (0, 4), (1, 0), (1, 1), (1, 4), (2, 0), (2, 2), (2, 3), (2, 4), (3, 0), (3, 2), (3, 3), (3, 4), (4, 0), (4, 1), (4, 2), (4, 3), (4, 4)]
20482134 """
2049- mat = self ._leq_matrix
2135+ mat = self ._leq_matrix_boolean
20502136 return bool (mat [i , j ]) or bool (mat [j , i ])
20512137
20522138 def antichains (self , element_class = list ):
0 commit comments