@@ -5232,7 +5232,7 @@ def factor(self):
5232
5232
"""
5233
5233
Factor the poset as a Cartesian product of smaller posets.
5234
5234
5235
- This only works for connected posets for the moment .
5235
+ This only works for connected posets.
5236
5236
5237
5237
The decomposition of a connected poset as a Cartesian product
5238
5238
of posets (prime in the sense that they cannot be written as
@@ -5270,19 +5270,24 @@ def factor(self):
5270
5270
sage: P.factor()
5271
5271
Traceback (most recent call last):
5272
5272
...
5273
- NotImplementedError: the poset is not connected
5273
+ NotImplementedError: the poset is empty or not connected
5274
5274
5275
5275
sage: P = posets.Crown(2)
5276
5276
sage: P.factor()
5277
5277
[Finite poset containing 4 elements]
5278
5278
5279
5279
sage: Poset().factor()
5280
- [Finite poset containing 0 elements]
5280
+ Traceback (most recent call last):
5281
+ ...
5282
+ NotImplementedError: the poset is empty or not connected
5281
5283
5282
5284
sage: factor(posets.BooleanLattice(2))
5283
5285
[Finite poset containing 2 elements,
5284
5286
Finite poset containing 2 elements]
5285
5287
5288
+ sage: factor(Poset(DiGraph([[0,1],[1,2],[0,3]])))
5289
+ [Finite poset containing 4 elements]
5290
+
5286
5291
REFERENCES:
5287
5292
5288
5293
.. [Feig1986] Joan Feigenbaum, *Directed Cartesian-Product Graphs
@@ -5293,49 +5298,57 @@ def factor(self):
5293
5298
from sage .graphs .graph import Graph
5294
5299
from sage .misc .flatten import flatten
5295
5300
dg = self ._hasse_diagram
5296
- if not dg .is_connected ():
5297
- raise NotImplementedError ('the poset is not connected' )
5301
+ if not dg .is_connected () or not dg . order () :
5302
+ raise NotImplementedError ('the poset is empty or not connected' )
5298
5303
if Integer (dg .num_verts ()).is_prime ():
5299
5304
return [self ]
5305
+ if sum (e for _ , e in self .degree_polynomial ().factor ()) == 1 :
5306
+ return [self ]
5307
+
5300
5308
G = dg .to_undirected ()
5301
5309
is_product , dic = G .is_cartesian_product (relabeling = True )
5302
5310
if not is_product :
5303
5311
return [self ]
5304
- dic = {key : tuple (flatten (dic [ key ] )) for key in dic }
5312
+ dic = {key : tuple (flatten (val )) for key , val in dic . items () }
5305
5313
5306
5314
prod_dg = dg .relabel (dic , inplace = False )
5307
5315
v0 = next (iter (dic .values ()))
5308
5316
n = len (v0 )
5309
5317
factors_range = range (n )
5310
- fusion = Graph (n )
5311
5318
5312
5319
def edge_color (va , vb ):
5313
- for i in range (n ):
5314
- if va [i ] != vb [i ]:
5315
- return i
5320
+ return next (i for i , (vai , vbi ) in enumerate (zip (va , vb ))
5321
+ if vai != vbi )
5322
+
5323
+ neighbors_table = {}
5324
+ for x in prod_dg :
5325
+ z = [[] for _ in range (n )]
5326
+ for y in prod_dg .neighbor_iterator (x ):
5327
+ z [edge_color (x , y )].append (y )
5328
+ neighbors_table [x ] = z
5316
5329
5330
+ fusion_edges = []
5317
5331
for i0 , i1 in Subsets (factors_range , 2 ):
5318
5332
for x in prod_dg :
5319
- neigh0 = [y for y in prod_dg .neighbor_iterator (x )
5320
- if edge_color (x , y ) == i0 ]
5321
- neigh1 = [z for z in prod_dg .neighbor_iterator (x )
5322
- if edge_color (x , z ) == i1 ]
5333
+ neigh0 = neighbors_table [x ][i0 ]
5334
+ neigh1 = neighbors_table [x ][i1 ]
5323
5335
for x0 , x1 in product (neigh0 , neigh1 ):
5324
5336
_x2 = list (x0 )
5325
5337
_x2 [i1 ] = x1 [i1 ]
5326
5338
x2 = tuple (_x2 )
5327
5339
A0 = prod_dg .has_edge (x , x0 )
5328
5340
B0 = prod_dg .has_edge (x1 , x2 )
5329
5341
if A0 != B0 :
5330
- fusion . add_edge ([i0 , i1 ])
5342
+ fusion_edges . append ([i0 , i1 ])
5331
5343
break
5332
5344
A1 = prod_dg .has_edge (x , x1 )
5333
5345
B1 = prod_dg .has_edge (x0 , x2 )
5334
5346
if A1 != B1 :
5335
- fusion . add_edge ([i0 , i1 ])
5347
+ fusion_edges . append ([i0 , i1 ])
5336
5348
break
5337
5349
5338
- fusion = fusion .transitive_closure ()
5350
+ fusion = Graph ([list (range (n )), fusion_edges ],
5351
+ format = "vertices_and_edges" )
5339
5352
resu = []
5340
5353
for s in fusion .connected_components (sort = False ):
5341
5354
subg = [x for x in prod_dg if all (x [i ] == v0 [i ] for i in factors_range
0 commit comments