passagemath-graphs 10.5.43__cp311-cp311-macosx_14_0_arm64.whl → 10.6.1rc2__cp311-cp311-macosx_14_0_arm64.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (132) hide show
  1. {passagemath_graphs-10.5.43.dist-info → passagemath_graphs-10.6.1rc2.dist-info}/METADATA +5 -6
  2. {passagemath_graphs-10.5.43.dist-info → passagemath_graphs-10.6.1rc2.dist-info}/RECORD +132 -130
  3. sage/combinat/abstract_tree.py +188 -17
  4. sage/combinat/cluster_algebra_quiver/interact.py +1 -2
  5. sage/combinat/cluster_algebra_quiver/mutation_type.py +518 -519
  6. sage/combinat/cluster_algebra_quiver/quiver.py +233 -205
  7. sage/combinat/designs/covering_design.py +2 -6
  8. sage/combinat/designs/database.py +11 -10
  9. sage/combinat/designs/designs_pyx.cpython-311-darwin.so +0 -0
  10. sage/combinat/designs/designs_pyx.pyx +2 -2
  11. sage/combinat/designs/evenly_distributed_sets.cpython-311-darwin.so +0 -0
  12. sage/combinat/designs/evenly_distributed_sets.pyx +4 -4
  13. sage/combinat/designs/gen_quadrangles_with_spread.cpython-311-darwin.so +0 -0
  14. sage/combinat/designs/latin_squares.py +53 -20
  15. sage/combinat/designs/orthogonal_arrays.py +2 -1
  16. sage/combinat/designs/orthogonal_arrays_find_recursive.cpython-311-darwin.so +0 -0
  17. sage/combinat/designs/orthogonal_arrays_find_recursive.pyx +22 -21
  18. sage/combinat/designs/resolvable_bibd.py +191 -157
  19. sage/combinat/designs/subhypergraph_search.cpython-311-darwin.so +0 -0
  20. sage/combinat/designs/subhypergraph_search.pyx +4 -4
  21. sage/combinat/designs/twographs.py +2 -2
  22. sage/combinat/finite_state_machine.py +6 -6
  23. sage/combinat/posets/bubble_shuffle.py +247 -0
  24. sage/combinat/posets/d_complete.py +3 -3
  25. sage/combinat/posets/elements.py +3 -3
  26. sage/combinat/posets/hasse_cython.cpython-311-darwin.so +0 -0
  27. sage/combinat/posets/hasse_cython.pyx +1 -1
  28. sage/combinat/posets/hasse_diagram.py +16 -22
  29. sage/combinat/posets/hochschild_lattice.py +158 -0
  30. sage/combinat/posets/incidence_algebras.py +14 -16
  31. sage/combinat/posets/lattices.py +51 -53
  32. sage/combinat/posets/linear_extension_iterator.cpython-311-darwin.so +0 -0
  33. sage/combinat/posets/linear_extensions.py +10 -12
  34. sage/combinat/posets/moebius_algebra.py +4 -4
  35. sage/combinat/posets/poset_examples.py +70 -23
  36. sage/combinat/posets/posets.py +294 -103
  37. sage/databases/knotinfo_db.py +2 -1
  38. sage/graphs/asteroidal_triples.cpython-311-darwin.so +0 -0
  39. sage/graphs/asteroidal_triples.pyx +24 -3
  40. sage/graphs/base/boost_graph.cpython-311-darwin.so +0 -0
  41. sage/graphs/base/boost_graph.pxd +3 -3
  42. sage/graphs/base/c_graph.cpython-311-darwin.so +0 -0
  43. sage/graphs/base/c_graph.pyx +1 -1
  44. sage/graphs/base/dense_graph.cpython-311-darwin.so +0 -0
  45. sage/graphs/base/dense_graph.pxd +5 -3
  46. sage/graphs/base/dense_graph.pyx +44 -0
  47. sage/graphs/base/graph_backends.cpython-311-darwin.so +0 -0
  48. sage/graphs/base/sparse_graph.cpython-311-darwin.so +0 -0
  49. sage/graphs/base/static_dense_graph.cpython-311-darwin.so +0 -0
  50. sage/graphs/base/static_sparse_backend.cpython-311-darwin.so +0 -0
  51. sage/graphs/base/static_sparse_backend.pyx +8 -5
  52. sage/graphs/base/static_sparse_graph.cpython-311-darwin.so +0 -0
  53. sage/graphs/base/static_sparse_graph.pyx +86 -15
  54. sage/graphs/bipartite_graph.py +59 -36
  55. sage/graphs/centrality.cpython-311-darwin.so +0 -0
  56. sage/graphs/centrality.pyx +82 -9
  57. sage/graphs/cographs.py +1 -1
  58. sage/graphs/comparability.cpython-311-darwin.so +0 -0
  59. sage/graphs/comparability.pyx +64 -26
  60. sage/graphs/connectivity.cpython-311-darwin.so +0 -0
  61. sage/graphs/convexity_properties.cpython-311-darwin.so +0 -0
  62. sage/graphs/convexity_properties.pyx +52 -9
  63. sage/graphs/digraph.py +439 -95
  64. sage/graphs/digraph_generators.py +174 -102
  65. sage/graphs/distances_all_pairs.cpython-311-darwin.so +0 -0
  66. sage/graphs/dot2tex_utils.py +1 -1
  67. sage/graphs/edge_connectivity.cpython-311-darwin.so +0 -0
  68. sage/graphs/generators/basic.py +1 -1
  69. sage/graphs/generators/distance_regular.cpython-311-darwin.so +0 -0
  70. sage/graphs/generators/distance_regular.pyx +1 -1
  71. sage/graphs/generators/families.py +37 -27
  72. sage/graphs/generators/random.py +2 -2
  73. sage/graphs/generators/smallgraphs.py +3 -3
  74. sage/graphs/generic_graph.py +558 -86
  75. sage/graphs/generic_graph_pyx.cpython-311-darwin.so +0 -0
  76. sage/graphs/generic_graph_pyx.pyx +58 -11
  77. sage/graphs/genus.cpython-311-darwin.so +0 -0
  78. sage/graphs/genus.pyx +3 -4
  79. sage/graphs/graph.py +291 -8
  80. sage/graphs/graph_coloring.cpython-311-darwin.so +0 -0
  81. sage/graphs/graph_database.py +67 -12
  82. sage/graphs/graph_decompositions/bandwidth.cpython-311-darwin.so +0 -0
  83. sage/graphs/graph_decompositions/clique_separators.cpython-311-darwin.so +0 -0
  84. sage/graphs/graph_decompositions/clique_separators.pyx +24 -3
  85. sage/graphs/graph_decompositions/cutwidth.cpython-311-darwin.so +0 -0
  86. sage/graphs/graph_decompositions/fast_digraph.cpython-311-darwin.so +0 -0
  87. sage/graphs/graph_decompositions/fast_digraph.pyx +1 -1
  88. sage/graphs/graph_decompositions/graph_products.cpython-311-darwin.so +0 -0
  89. sage/graphs/graph_decompositions/graph_products.pyx +67 -21
  90. sage/graphs/graph_decompositions/modular_decomposition.cpython-311-darwin.so +0 -0
  91. sage/graphs/graph_decompositions/slice_decomposition.cpython-311-darwin.so +0 -0
  92. sage/graphs/graph_decompositions/slice_decomposition.pyx +34 -8
  93. sage/graphs/graph_decompositions/tree_decomposition.cpython-311-darwin.so +0 -0
  94. sage/graphs/graph_decompositions/vertex_separation.cpython-311-darwin.so +0 -0
  95. sage/graphs/graph_generators.py +45 -32
  96. sage/graphs/graph_generators_pyx.cpython-311-darwin.so +0 -0
  97. sage/graphs/graph_generators_pyx.pyx +15 -15
  98. sage/graphs/graph_latex.py +1 -1
  99. sage/graphs/graph_list.py +52 -9
  100. sage/graphs/graph_plot.py +7 -0
  101. sage/graphs/hyperbolicity.cpython-311-darwin.so +0 -0
  102. sage/graphs/hyperbolicity.pyx +2 -0
  103. sage/graphs/independent_sets.cpython-311-darwin.so +0 -0
  104. sage/graphs/isoperimetric_inequalities.cpython-311-darwin.so +0 -0
  105. sage/graphs/isoperimetric_inequalities.pyx +42 -6
  106. sage/graphs/line_graph.cpython-311-darwin.so +0 -0
  107. sage/graphs/line_graph.pyx +153 -37
  108. sage/graphs/matching_covered_graph.py +84 -60
  109. sage/graphs/orientations.py +3 -18
  110. sage/graphs/path_enumeration.cpython-311-darwin.so +0 -0
  111. sage/graphs/path_enumeration.pyx +2 -2
  112. sage/graphs/spanning_tree.cpython-311-darwin.so +0 -0
  113. sage/graphs/strongly_regular_db.cpython-311-darwin.so +0 -0
  114. sage/graphs/strongly_regular_db.pyx +15 -15
  115. sage/graphs/traversals.cpython-311-darwin.so +0 -0
  116. sage/graphs/traversals.pyx +13 -12
  117. sage/graphs/trees.cpython-311-darwin.so +0 -0
  118. sage/graphs/tutte_polynomial.py +1 -1
  119. sage/graphs/views.cpython-311-darwin.so +0 -0
  120. sage/graphs/weakly_chordal.cpython-311-darwin.so +0 -0
  121. sage/graphs/weakly_chordal.pyx +50 -8
  122. sage/groups/perm_gps/partn_ref/refinement_graphs.cpython-311-darwin.so +0 -0
  123. sage/knots/free_knotinfo_monoid.py +3 -3
  124. sage/knots/knotinfo.py +102 -82
  125. sage/knots/link.py +72 -39
  126. sage/topology/cubical_complex.py +4 -5
  127. sage/topology/delta_complex.py +4 -4
  128. sage/topology/simplicial_complex.py +0 -1
  129. sage/topology/simplicial_complex_catalog.py +6 -0
  130. sage/topology/simplicial_complex_examples.py +4 -16
  131. {passagemath_graphs-10.5.43.dist-info → passagemath_graphs-10.6.1rc2.dist-info}/WHEEL +0 -0
  132. {passagemath_graphs-10.5.43.dist-info → passagemath_graphs-10.6.1rc2.dist-info}/top_level.txt +0 -0
@@ -185,6 +185,7 @@ List of Poset methods
185
185
  :meth:`~FinitePoset.flag_h_polynomial` | Return the flag h-polynomial of the poset.
186
186
  :meth:`~FinitePoset.order_polynomial` | Return the order polynomial of the poset.
187
187
  :meth:`~FinitePoset.zeta_polynomial` | Return the zeta polynomial of the poset.
188
+ :meth:`~FinitePoset.apozeta_polynomial` | Return the apozeta polynomial of the poset.
188
189
  :meth:`~FinitePoset.M_triangle` | Return the M-triangle of the poset.
189
190
  :meth:`~FinitePoset.kazhdan_lusztig_polynomial` | Return the Kazhdan-Lusztig polynomial of the poset.
190
191
  :meth:`~FinitePoset.coxeter_polynomial` | Return the characteristic polynomial of the Coxeter transformation.
@@ -749,9 +750,9 @@ def Poset(data=None, element_labels=None, cover_relations=False, linear_extensio
749
750
  # and is transitively reduced.
750
751
  if D.has_loops():
751
752
  raise ValueError("Hasse diagram contains loops")
752
- elif D.has_multiple_edges():
753
+ if D.has_multiple_edges():
753
754
  raise ValueError("Hasse diagram contains multiple edges")
754
- elif cover_relations and not D.is_transitively_reduced():
755
+ if cover_relations and not D.is_transitively_reduced():
755
756
  raise ValueError("Hasse diagram is not transitively reduced")
756
757
 
757
758
  if element_labels is not None:
@@ -1108,9 +1109,9 @@ class FinitePoset(UniqueRepresentation, Parent):
1108
1109
  """
1109
1110
  if self._is_facade:
1110
1111
  return self._elements
1111
- else:
1112
- return tuple(self.element_class(self, element, vertex)
1113
- for vertex, element in enumerate(self._elements))
1112
+
1113
+ return tuple(self.element_class(self, element, vertex)
1114
+ for vertex, element in enumerate(self._elements))
1114
1115
 
1115
1116
  # This defines the type (class) of elements of poset.
1116
1117
  Element = PosetElement
@@ -1156,11 +1157,11 @@ class FinitePoset(UniqueRepresentation, Parent):
1156
1157
  """
1157
1158
  if isinstance(element, self.element_class) and element.parent() is self:
1158
1159
  return element.vertex
1159
- else:
1160
- try:
1161
- return self._element_to_vertex_dict[element]
1162
- except KeyError:
1163
- raise ValueError("element (=%s) not in poset" % element)
1160
+
1161
+ try:
1162
+ return self._element_to_vertex_dict[element]
1163
+ except KeyError:
1164
+ raise ValueError(f"element (={element}) not in poset")
1164
1165
 
1165
1166
  def _vertex_to_element(self, vertex):
1166
1167
  """
@@ -1226,8 +1227,7 @@ class FinitePoset(UniqueRepresentation, Parent):
1226
1227
  """
1227
1228
  if self._is_facade:
1228
1229
  return element
1229
- else:
1230
- return element.element
1230
+ return element.element
1231
1231
 
1232
1232
  def __bool__(self) -> bool:
1233
1233
  r"""
@@ -1337,7 +1337,7 @@ class FinitePoset(UniqueRepresentation, Parent):
1337
1337
  return element
1338
1338
  return super().__call__(element)
1339
1339
 
1340
- def hasse_diagram(self):
1340
+ def hasse_diagram(self) -> DiGraph:
1341
1341
  r"""
1342
1342
  Return the Hasse diagram of the poset as a Sage :class:`DiGraph`.
1343
1343
 
@@ -1380,7 +1380,7 @@ class FinitePoset(UniqueRepresentation, Parent):
1380
1380
  rankdir='up',)
1381
1381
  return G
1382
1382
 
1383
- def _latex_(self):
1383
+ def _latex_(self) -> str:
1384
1384
  r"""
1385
1385
  Return a latex method for the poset.
1386
1386
 
@@ -1398,7 +1398,77 @@ class FinitePoset(UniqueRepresentation, Parent):
1398
1398
  """
1399
1399
  return self.hasse_diagram()._latex_()
1400
1400
 
1401
- def _repr_(self):
1401
+ def tikz(self, format=None, edge_labels=False, color_by_label=False,
1402
+ prog='dot', rankdir='up', standalone_config=None,
1403
+ usepackage=None, usetikzlibrary=None, macros=None,
1404
+ use_sage_preamble=None, **kwds):
1405
+ r"""
1406
+ Return a TikzPicture illustrating the poset.
1407
+
1408
+ If ``graphviz`` and ``dot2tex`` are available, it uses these packages for
1409
+ placements of vertices and edges.
1410
+
1411
+ INPUT:
1412
+
1413
+ - ``format`` -- string (default: ``None``), ``'dot2tex'`` or
1414
+ ``'tkz_graph'``. If ``None``, it is set to ``'dot2tex'`` if
1415
+ dot2tex is present, otherwise it is set to ``'tkz_graph'``.
1416
+ - ``edge_labels`` -- bool (default: ``False``)
1417
+ - ``color_by_label`` -- boolean or dictionary or function (default:
1418
+ ``False``); whether to color each edge with a different color
1419
+ according to its label; the colors are chosen along a rainbow, unless
1420
+ they are specified by a function or dictionary mapping labels to
1421
+ colors;
1422
+
1423
+ When using format ``'dot2tex'``, the following inputs are considered:
1424
+
1425
+ - ``prog`` -- string (default: ``'dot'``) the program used for the
1426
+ layout corresponding to one of the software of the graphviz
1427
+ suite: 'dot', 'neato', 'twopi', 'circo' or 'fdp'.
1428
+ - ``rankdir`` -- string (default: ``'up'``), direction of graph layout
1429
+ when prog is ``'dot'``, possible values are ``'down'``,
1430
+ ``'up'``, ``'right'`` and ``'left'``.
1431
+
1432
+ Additional keywords arguments are forwarded to
1433
+ :meth:`sage.graphs.graph_latex.GraphLatex.set_option`.
1434
+
1435
+ The following inputs define the preamble of the latex standalone
1436
+ document class file containing the tikzpicture:
1437
+
1438
+ - ``standalone_config`` -- list of strings (default: ``["border=4mm"]``);
1439
+ latex document class standalone configuration options
1440
+ - ``usepackage`` -- list of strings (default: ``[]``); latex
1441
+ packages
1442
+ - ``usetikzlibrary`` -- list of strings (default: ``[]``); tikz
1443
+ libraries to use
1444
+ - ``macros`` -- list of strings (default: ``[]``); list of
1445
+ newcommands needed for the picture
1446
+ - ``use_sage_preamble`` -- bool (default: ``None``), if ``None``
1447
+ it is set to ``True`` if and only if format is ``'tkz_graph'``
1448
+
1449
+ OUTPUT:
1450
+
1451
+ An instance of :mod:`sage.misc.latex_standalone.TikzPicture`.
1452
+
1453
+ .. NOTE::
1454
+
1455
+ Prerequisite: dot2tex optional Sage package and graphviz must be
1456
+ installed when using format ``'dot2tex'``.
1457
+
1458
+ EXAMPLES::
1459
+
1460
+ sage: P = Poset(([1,2], [[1,2]]), cover_relations=True)
1461
+ sage: tikz = P.tikz() # optional - dot2tex graphviz # long time
1462
+ sage: _ = tikz.pdf(view=False) # optional - dot2tex graphviz latex # long time
1463
+ """
1464
+ G = self.hasse_diagram()
1465
+ return G.tikz(format=format, edge_labels=edge_labels,
1466
+ color_by_label=color_by_label, prog=prog, rankdir=rankdir,
1467
+ standalone_config=standalone_config, usepackage=usepackage,
1468
+ usetikzlibrary=usetikzlibrary, macros=macros,
1469
+ use_sage_preamble=use_sage_preamble, **kwds)
1470
+
1471
+ def _repr_(self) -> str:
1402
1472
  r"""
1403
1473
  Return a string representation of the poset.
1404
1474
 
@@ -2704,6 +2774,10 @@ class FinitePoset(UniqueRepresentation, Parent):
2704
2774
  """
2705
2775
  if not self.cardinality():
2706
2776
  return []
2777
+ # precomputation helps for speed:
2778
+ if self.cardinality() > 60:
2779
+ self.lequal_matrix()
2780
+
2707
2781
  H = self._hasse_diagram
2708
2782
  stock = [(x, x, x) for x in H]
2709
2783
  poly = [len(stock)]
@@ -3055,7 +3129,7 @@ class FinitePoset(UniqueRepresentation, Parent):
3055
3129
  return None
3056
3130
  return self._vertex_to_element(hasse_bot)
3057
3131
 
3058
- def has_bottom(self):
3132
+ def has_bottom(self) -> bool:
3059
3133
  """
3060
3134
  Return ``True`` if the poset has a unique minimal element, and
3061
3135
  ``False`` otherwise.
@@ -3110,7 +3184,7 @@ class FinitePoset(UniqueRepresentation, Parent):
3110
3184
  return None
3111
3185
  return self._vertex_to_element(hasse_top)
3112
3186
 
3113
- def has_top(self):
3187
+ def has_top(self) -> bool:
3114
3188
  """
3115
3189
  Return ``True`` if the poset has a unique maximal element, and
3116
3190
  ``False`` otherwise.
@@ -3336,7 +3410,7 @@ class FinitePoset(UniqueRepresentation, Parent):
3336
3410
  sorted_o = sorted(elms, key=self._element_to_vertex)
3337
3411
  return all(self.le(a, b) for a, b in zip(sorted_o, sorted_o[1:]))
3338
3412
 
3339
- def is_antichain_of_poset(self, elms):
3413
+ def is_antichain_of_poset(self, elms) -> bool:
3340
3414
  """
3341
3415
  Return ``True`` if ``elms`` is an antichain of the poset
3342
3416
  and ``False`` otherwise.
@@ -3444,7 +3518,7 @@ class FinitePoset(UniqueRepresentation, Parent):
3444
3518
  return False
3445
3519
  return all(part.is_series_parallel() for part in parts)
3446
3520
 
3447
- def is_EL_labelling(self, f, return_raising_chains=False):
3521
+ def is_EL_labelling(self, f, return_raising_chains=False) -> bool | dict:
3448
3522
  r"""
3449
3523
  Return ``True`` if ``f`` is an EL labelling of ``self``.
3450
3524
 
@@ -3464,7 +3538,7 @@ class FinitePoset(UniqueRepresentation, Parent):
3464
3538
  ``self`` such that ``b`` covers ``a`` and returning elements
3465
3539
  in a totally ordered set.
3466
3540
 
3467
- - ``return_raising_chains`` (optional; default:``False``) if
3541
+ - ``return_raising_chains`` (optional; default: ``False``) if
3468
3542
  ``True``, returns the set of all raising chains in ``self``,
3469
3543
  if possible.
3470
3544
 
@@ -3853,7 +3927,7 @@ class FinitePoset(UniqueRepresentation, Parent):
3853
3927
  return (nonlocals[0], nonlocals[1])
3854
3928
  return nonlocals[0]
3855
3929
 
3856
- def is_jump_critical(self, certificate=False):
3930
+ def is_jump_critical(self, certificate=False) -> bool | tuple:
3857
3931
  """
3858
3932
  Return ``True`` if the poset is jump-critical, and ``False`` otherwise.
3859
3933
 
@@ -3960,8 +4034,7 @@ class FinitePoset(UniqueRepresentation, Parent):
3960
4034
  hasse_rf = self._hasse_diagram.rank_function()
3961
4035
  if hasse_rf is None:
3962
4036
  return None
3963
- else:
3964
- return lambda z: hasse_rf(self._element_to_vertex(z))
4037
+ return lambda z: hasse_rf(self._element_to_vertex(z))
3965
4038
 
3966
4039
  def rank(self, element=None):
3967
4040
  r"""
@@ -3990,10 +4063,9 @@ class FinitePoset(UniqueRepresentation, Parent):
3990
4063
  """
3991
4064
  if element is None:
3992
4065
  return len(self.level_sets()) - 1
3993
- elif self.is_ranked():
4066
+ if self.is_ranked():
3994
4067
  return self.rank_function()(element)
3995
- else:
3996
- raise ValueError("the poset is not ranked")
4068
+ raise ValueError("the poset is not ranked")
3997
4069
 
3998
4070
  def is_ranked(self) -> bool:
3999
4071
  r"""
@@ -4077,7 +4149,7 @@ class FinitePoset(UniqueRepresentation, Parent):
4077
4149
  rank = rf(maxes[0])
4078
4150
  return all(rf(i) == rank for i in maxes)
4079
4151
 
4080
- def covers(self, x, y):
4152
+ def covers(self, x, y) -> bool:
4081
4153
  """
4082
4154
  Return ``True`` if ``y`` covers ``x`` and ``False`` otherwise.
4083
4155
 
@@ -4109,7 +4181,7 @@ class FinitePoset(UniqueRepresentation, Parent):
4109
4181
  for e in self._hasse_diagram.neighbor_out_iterator(self._element_to_vertex(x)):
4110
4182
  yield self._vertex_to_element(e)
4111
4183
 
4112
- def upper_covers(self, x):
4184
+ def upper_covers(self, x) -> list:
4113
4185
  """
4114
4186
  Return the list of upper covers of the element ``x``.
4115
4187
 
@@ -4142,7 +4214,7 @@ class FinitePoset(UniqueRepresentation, Parent):
4142
4214
  for e in self._hasse_diagram.neighbor_in_iterator(self._element_to_vertex(x)):
4143
4215
  yield self._vertex_to_element(e)
4144
4216
 
4145
- def lower_covers(self, x):
4217
+ def lower_covers(self, x) -> list:
4146
4218
  """
4147
4219
  Return the list of lower covers of the element ``x``.
4148
4220
 
@@ -4161,7 +4233,7 @@ class FinitePoset(UniqueRepresentation, Parent):
4161
4233
  """
4162
4234
  return list(self.lower_covers_iterator(x))
4163
4235
 
4164
- def cardinality(self):
4236
+ def cardinality(self) -> Integer:
4165
4237
  """
4166
4238
  Return the number of elements in the poset.
4167
4239
 
@@ -4331,10 +4403,15 @@ class FinitePoset(UniqueRepresentation, Parent):
4331
4403
  """
4332
4404
  return self._hasse_diagram.coxeter_transformation()
4333
4405
 
4334
- def coxeter_polynomial(self):
4406
+ def coxeter_polynomial(self, algorithm="sage"):
4335
4407
  """
4336
4408
  Return the Coxeter polynomial of the poset.
4337
4409
 
4410
+ INPUT:
4411
+
4412
+ - ``algorithm`` -- optional (default: ``"sage"``) ;
4413
+ the unique other option is ``"magma"``
4414
+
4338
4415
  OUTPUT: a polynomial in one variable
4339
4416
 
4340
4417
  The output is the characteristic polynomial of the Coxeter
@@ -4351,13 +4428,24 @@ class FinitePoset(UniqueRepresentation, Parent):
4351
4428
  sage: p.coxeter_polynomial() # needs sage.groups sage.libs.flint
4352
4429
  x^6 + x^5 - x^3 + x + 1
4353
4430
 
4431
+ TESTS::
4432
+
4433
+ sage: P = posets.PentagonPoset()
4434
+ sage: P.coxeter_polynomial("magma") # optional - magma
4435
+ x^5 + x^4 + x + 1
4436
+
4354
4437
  .. SEEALSO::
4355
4438
 
4356
4439
  :meth:`coxeter_transformation`, :meth:`coxeter_smith_form`
4357
4440
  """
4358
- return self._hasse_diagram.coxeter_transformation().charpoly()
4441
+ cox_matrix = self._hasse_diagram.coxeter_transformation()
4442
+ if algorithm == "magma":
4443
+ from sage.interfaces.magma import magma
4444
+ dense_matrix = magma(cox_matrix).Matrix()
4445
+ return dense_matrix.CharacteristicPolynomial().sage()
4446
+ return cox_matrix.charpoly()
4359
4447
 
4360
- def coxeter_smith_form(self, algorithm='singular'):
4448
+ def coxeter_smith_form(self, algorithm='singular') -> list:
4361
4449
  """
4362
4450
  Return the Smith normal form of `x` minus the Coxeter transformation
4363
4451
  matrix.
@@ -4381,29 +4469,33 @@ class FinitePoset(UniqueRepresentation, Parent):
4381
4469
 
4382
4470
  EXAMPLES::
4383
4471
 
4384
- sage: P = posets.PentagonPoset()
4385
- sage: P.coxeter_smith_form() # needs sage.libs.singular
4386
- [1, 1, 1, 1, x^5 + x^4 + x + 1]
4472
+ sage: P = posets.PentagonPoset()
4473
+ sage: P.coxeter_smith_form() # needs sage.libs.singular
4474
+ [1, 1, 1, 1, x^5 + x^4 + x + 1]
4387
4475
 
4388
- sage: P = posets.DiamondPoset(7)
4389
- sage: prod(P.coxeter_smith_form()) == P.coxeter_polynomial() # needs sage.libs.singular
4390
- True
4476
+ sage: P = posets.DiamondPoset(7)
4477
+ sage: prod(P.coxeter_smith_form()) == P.coxeter_polynomial() # needs sage.libs.singular
4478
+ True
4391
4479
 
4392
4480
  TESTS::
4393
4481
 
4394
- sage: P = posets.PentagonPoset()
4395
- sage: P.coxeter_smith_form(algorithm='sage') # needs sage.libs.flint
4396
- [1, 1, 1, 1, x^5 + x^4 + x + 1]
4397
- sage: P.coxeter_smith_form(algorithm='gap') # needs sage.libs.gap
4398
- [1, 1, 1, 1, x^5 + x^4 + x + 1]
4399
- sage: P.coxeter_smith_form(algorithm='pari') # needs sage.libs.flint sage.libs.pari
4400
- [1, 1, 1, 1, x^5 + x^4 + x + 1]
4401
- sage: P.coxeter_smith_form(algorithm='fricas') # optional - fricas
4402
- [1, 1, 1, 1, x^5 + x^4 + x + 1]
4403
- sage: P.coxeter_smith_form(algorithm='maple') # optional - maple
4404
- [1, 1, 1, 1, x^5 + x^4 + x + 1]
4405
- sage: P.coxeter_smith_form(algorithm='magma') # optional - magma
4406
- [1, 1, 1, 1, x^5 + x^4 + x + 1]
4482
+ sage: P = posets.PentagonPoset()
4483
+ sage: P.coxeter_smith_form(algorithm='sage') # needs sage.libs.flint
4484
+ [1, 1, 1, 1, x^5 + x^4 + x + 1]
4485
+ sage: P.coxeter_smith_form(algorithm='gap') # needs sage.libs.gap
4486
+ [1, 1, 1, 1, x^5 + x^4 + x + 1]
4487
+ sage: P.coxeter_smith_form(algorithm='pari') # needs sage.libs.flint sage.libs.pari
4488
+ [1, 1, 1, 1, x^5 + x^4 + x + 1]
4489
+ sage: P.coxeter_smith_form(algorithm='fricas') # optional - fricas
4490
+ [1, 1, 1, 1, x^5 + x^4 + x + 1]
4491
+ sage: P.coxeter_smith_form(algorithm='maple') # optional - maple
4492
+ [1, 1, 1, 1, x^5 + x^4 + x + 1]
4493
+ sage: P.coxeter_smith_form(algorithm='magma') # optional - magma
4494
+ [1, 1, 1, 1, x^5 + x^4 + x + 1]
4495
+ sage: P.coxeter_smith_form(algorithm='nasa')
4496
+ Traceback (most recent call last):
4497
+ ...
4498
+ ValueError: unknown algorithm
4407
4499
 
4408
4500
  .. SEEALSO::
4409
4501
 
@@ -4456,7 +4548,9 @@ class FinitePoset(UniqueRepresentation, Parent):
4456
4548
  fm = fricas(x - c0)
4457
4549
  return list(fricas(fm.name() + "::Matrix(UP(x, FRAC INT))").smith().diagonal().sage())
4458
4550
 
4459
- def is_meet_semilattice(self, certificate=False):
4551
+ raise ValueError("unknown algorithm")
4552
+
4553
+ def is_meet_semilattice(self, certificate=False) -> bool | tuple:
4460
4554
  r"""
4461
4555
  Return ``True`` if the poset has a meet operation, and
4462
4556
  ``False`` otherwise.
@@ -4529,7 +4623,7 @@ class FinitePoset(UniqueRepresentation, Parent):
4529
4623
  return (True, None)
4530
4624
  return True
4531
4625
 
4532
- def is_join_semilattice(self, certificate=False):
4626
+ def is_join_semilattice(self, certificate=False) -> bool | tuple:
4533
4627
  """
4534
4628
  Return ``True`` if the poset has a join operation, and ``False``
4535
4629
  otherwise.
@@ -4601,7 +4695,7 @@ class FinitePoset(UniqueRepresentation, Parent):
4601
4695
  return (True, None)
4602
4696
  return True
4603
4697
 
4604
- def is_isomorphic(self, other, **kwds):
4698
+ def is_isomorphic(self, other, **kwds) -> bool | tuple:
4605
4699
  """
4606
4700
  Return ``True`` if both posets are isomorphic.
4607
4701
 
@@ -4665,7 +4759,7 @@ class FinitePoset(UniqueRepresentation, Parent):
4665
4759
  raise TypeError("'other' is not a finite poset")
4666
4760
  return (self.subposet([self._list[i] for i in x]) for x in self._hasse_diagram.transitive_closure().subgraph_search_iterator(other.hasse_diagram().transitive_closure(), induced=True, return_graphs=False))
4667
4761
 
4668
- def isomorphic_subposets(self, other):
4762
+ def isomorphic_subposets(self, other) -> list:
4669
4763
  """
4670
4764
  Return a list of subposets of ``self`` isomorphic to ``other``.
4671
4765
 
@@ -4701,7 +4795,8 @@ class FinitePoset(UniqueRepresentation, Parent):
4701
4795
  L = self._hasse_diagram.transitive_closure().subgraph_search_iterator(other._hasse_diagram.transitive_closure(), induced=True, return_graphs=False)
4702
4796
  # Since subgraph_search_iterator returns labelled copies, we
4703
4797
  # remove duplicates.
4704
- return [self.subposet([self._list[i] for i in x]) for x in sorted({frozenset(y) for y in L})]
4798
+ return [self.subposet([self._list[i] for i in x])
4799
+ for x in sorted({frozenset(y) for y in L})]
4705
4800
 
4706
4801
  # Caveat: list is overridden by the method list above!!!
4707
4802
  def antichains(self, element_constructor=None):
@@ -4794,7 +4889,7 @@ class FinitePoset(UniqueRepresentation, Parent):
4794
4889
  for antichain in self._hasse_diagram.antichains_iterator():
4795
4890
  yield [vertex_to_element(_) for _ in antichain]
4796
4891
 
4797
- def width(self, certificate=False):
4892
+ def width(self, certificate=False) -> Integer | tuple:
4798
4893
  r"""
4799
4894
  Return the width of the poset (the size of its longest antichain).
4800
4895
 
@@ -4972,7 +5067,7 @@ class FinitePoset(UniqueRepresentation, Parent):
4972
5067
  result.rename("Set of chains of %s" % self)
4973
5068
  return result
4974
5069
 
4975
- def connected_components(self):
5070
+ def connected_components(self) -> list:
4976
5071
  """
4977
5072
  Return the connected components of the poset as subposets.
4978
5073
 
@@ -5019,7 +5114,7 @@ class FinitePoset(UniqueRepresentation, Parent):
5019
5114
  facade=False))
5020
5115
  return result
5021
5116
 
5022
- def ordinal_summands(self):
5117
+ def ordinal_summands(self) -> list:
5023
5118
  r"""
5024
5119
  Return the ordinal summands of the poset as subposets.
5025
5120
 
@@ -5230,11 +5325,11 @@ class FinitePoset(UniqueRepresentation, Parent):
5230
5325
 
5231
5326
  return Poset((rees_set, covers), cover_relations=True)
5232
5327
 
5233
- def factor(self):
5328
+ def factor(self) -> list:
5234
5329
  """
5235
5330
  Factor the poset as a Cartesian product of smaller posets.
5236
5331
 
5237
- This only works for connected posets for the moment.
5332
+ This only works for connected posets.
5238
5333
 
5239
5334
  The decomposition of a connected poset as a Cartesian product
5240
5335
  of posets (prime in the sense that they cannot be written as
@@ -5272,19 +5367,24 @@ class FinitePoset(UniqueRepresentation, Parent):
5272
5367
  sage: P.factor()
5273
5368
  Traceback (most recent call last):
5274
5369
  ...
5275
- NotImplementedError: the poset is not connected
5370
+ NotImplementedError: the poset is empty or not connected
5276
5371
 
5277
5372
  sage: P = posets.Crown(2)
5278
5373
  sage: P.factor()
5279
5374
  [Finite poset containing 4 elements]
5280
5375
 
5281
5376
  sage: Poset().factor()
5282
- [Finite poset containing 0 elements]
5377
+ Traceback (most recent call last):
5378
+ ...
5379
+ NotImplementedError: the poset is empty or not connected
5283
5380
 
5284
5381
  sage: factor(posets.BooleanLattice(2))
5285
5382
  [Finite poset containing 2 elements,
5286
5383
  Finite poset containing 2 elements]
5287
5384
 
5385
+ sage: factor(Poset(DiGraph([[0,1],[1,2],[0,3]])))
5386
+ [Finite poset containing 4 elements]
5387
+
5288
5388
  REFERENCES:
5289
5389
 
5290
5390
  .. [Feig1986] Joan Feigenbaum, *Directed Cartesian-Product Graphs
@@ -5295,33 +5395,40 @@ class FinitePoset(UniqueRepresentation, Parent):
5295
5395
  from sage.graphs.graph import Graph
5296
5396
  from sage.misc.flatten import flatten
5297
5397
  dg = self._hasse_diagram
5298
- if not dg.is_connected():
5299
- raise NotImplementedError('the poset is not connected')
5398
+ if not dg.is_connected() or not dg.order():
5399
+ raise NotImplementedError('the poset is empty or not connected')
5300
5400
  if Integer(dg.num_verts()).is_prime():
5301
5401
  return [self]
5402
+ if sum(e for _, e in self.degree_polynomial().factor()) == 1:
5403
+ return [self]
5404
+
5302
5405
  G = dg.to_undirected()
5303
5406
  is_product, dic = G.is_cartesian_product(relabeling=True)
5304
5407
  if not is_product:
5305
5408
  return [self]
5306
- dic = {key: tuple(flatten(dic[key])) for key in dic}
5409
+ dic = {key: tuple(flatten(val)) for key, val in dic.items()}
5307
5410
 
5308
5411
  prod_dg = dg.relabel(dic, inplace=False)
5309
5412
  v0 = next(iter(dic.values()))
5310
5413
  n = len(v0)
5311
5414
  factors_range = range(n)
5312
- fusion = Graph(n)
5313
5415
 
5314
5416
  def edge_color(va, vb):
5315
- for i in range(n):
5316
- if va[i] != vb[i]:
5317
- return i
5417
+ return next(i for i, (vai, vbi) in enumerate(zip(va, vb))
5418
+ if vai != vbi)
5419
+
5420
+ neighbors_table = {}
5421
+ for x in prod_dg:
5422
+ z = [[] for _ in range(n)]
5423
+ for y in prod_dg.neighbor_iterator(x):
5424
+ z[edge_color(x, y)].append(y)
5425
+ neighbors_table[x] = z
5318
5426
 
5427
+ fusion_edges = []
5319
5428
  for i0, i1 in Subsets(factors_range, 2):
5320
5429
  for x in prod_dg:
5321
- neigh0 = [y for y in prod_dg.neighbor_iterator(x)
5322
- if edge_color(x, y) == i0]
5323
- neigh1 = [z for z in prod_dg.neighbor_iterator(x)
5324
- if edge_color(x, z) == i1]
5430
+ neigh0 = neighbors_table[x][i0]
5431
+ neigh1 = neighbors_table[x][i1]
5325
5432
  for x0, x1 in product(neigh0, neigh1):
5326
5433
  _x2 = list(x0)
5327
5434
  _x2[i1] = x1[i1]
@@ -5329,15 +5436,16 @@ class FinitePoset(UniqueRepresentation, Parent):
5329
5436
  A0 = prod_dg.has_edge(x, x0)
5330
5437
  B0 = prod_dg.has_edge(x1, x2)
5331
5438
  if A0 != B0:
5332
- fusion.add_edge([i0, i1])
5439
+ fusion_edges.append([i0, i1])
5333
5440
  break
5334
5441
  A1 = prod_dg.has_edge(x, x1)
5335
5442
  B1 = prod_dg.has_edge(x0, x2)
5336
5443
  if A1 != B1:
5337
- fusion.add_edge([i0, i1])
5444
+ fusion_edges.append([i0, i1])
5338
5445
  break
5339
5446
 
5340
- fusion = fusion.transitive_closure()
5447
+ fusion = Graph([list(range(n)), fusion_edges],
5448
+ format="vertices_and_edges")
5341
5449
  resu = []
5342
5450
  for s in fusion.connected_components(sort=False):
5343
5451
  subg = [x for x in prod_dg if all(x[i] == v0[i] for i in factors_range
@@ -7239,6 +7347,8 @@ class FinitePoset(UniqueRepresentation, Parent):
7239
7347
  In particular, `Z(2)` is the number of vertices and `Z(3)` is
7240
7348
  the number of intervals.
7241
7349
 
7350
+ .. SEEALSO:: :meth:`apozeta_polynomial`
7351
+
7242
7352
  EXAMPLES::
7243
7353
 
7244
7354
  sage: # needs sage.libs.flint
@@ -7279,6 +7389,54 @@ class FinitePoset(UniqueRepresentation, Parent):
7279
7389
  f = g[n] + f / n
7280
7390
  return f
7281
7391
 
7392
+ def apozeta_polynomial(self):
7393
+ r"""
7394
+ Return the apozeta polynomial of the poset ``self``.
7395
+
7396
+ The poset is assumed to be graded.
7397
+
7398
+ The apozeta polynomial of a poset is the unique polynomial
7399
+ `Z^{a}(q)` such that for every integer `m > 1`, `Z^{a}(m)` is
7400
+ the number of weakly increasing sequences `x_1 \leq x_2 \leq
7401
+ \dots \leq x_{m-1}` of elements of the poset whose largest
7402
+ element belongs to the top level of the poset.
7403
+
7404
+ When the poset `P` has a unique maximal element, this is
7405
+ equal to `Z(q-1)` where `Z` is the zeta polynomial of `P`.
7406
+
7407
+ The name comes from the greek radical ``apo``.
7408
+
7409
+ .. SEEALSO:: :meth:`zeta_polynomial`
7410
+
7411
+ EXAMPLES::
7412
+
7413
+ sage: P = posets.NoncrossingPartitions(SymmetricGroup(4))
7414
+ sage: P.apozeta_polynomial()
7415
+ 8/3*q^3 - 10*q^2 + 37/3*q - 5
7416
+
7417
+ sage: P = Poset({"a": "bc", "b": "d", "c": "de"})
7418
+ sage: P.apozeta_polynomial()
7419
+ 3/2*q^2 - 5/2*q + 1
7420
+ sage: P.zeta_polynomial()
7421
+ 3/2*q^2 - 1/2*q
7422
+
7423
+ TESTS:
7424
+
7425
+ Checking the simplest case::
7426
+
7427
+ sage: Poset({1: []}).apozeta_polynomial()
7428
+ 1
7429
+ sage: parent(_)
7430
+ Univariate Polynomial Ring in q over Rational Field
7431
+ """
7432
+ from sage.functions.other import binomial
7433
+ R = PolynomialRing(QQ, 'q')
7434
+ q = R.gen()
7435
+
7436
+ top_level = self.level_sets()[-1]
7437
+ return sum(binomial(q - 2, len(c) - 1)
7438
+ for c in self.chains() if c and c[-1] in top_level)
7439
+
7282
7440
  def M_triangle(self):
7283
7441
  r"""
7284
7442
  Return the M-triangle of the poset.
@@ -7930,7 +8088,7 @@ class FinitePoset(UniqueRepresentation, Parent):
7930
8088
  return False
7931
8089
  return True
7932
8090
 
7933
- def is_slender(self, certificate=False):
8091
+ def is_slender(self, certificate=False) -> bool | tuple:
7934
8092
  r"""
7935
8093
  Return ``True`` if the poset is slender, and ``False`` otherwise.
7936
8094
 
@@ -8007,7 +8165,7 @@ class FinitePoset(UniqueRepresentation, Parent):
8007
8165
  return (True, None)
8008
8166
  return True
8009
8167
 
8010
- def is_sperner(self):
8168
+ def is_sperner(self) -> bool:
8011
8169
  """
8012
8170
  Return ``True`` if the poset is Sperner, and ``False`` otherwise.
8013
8171
 
@@ -8049,7 +8207,7 @@ class FinitePoset(UniqueRepresentation, Parent):
8049
8207
  N = max(len(level) for level in self._hasse_diagram.level_sets())
8050
8208
  return W <= N
8051
8209
 
8052
- def is_eulerian(self, k=None, certificate=False):
8210
+ def is_eulerian(self, k=None, certificate=False) -> bool | tuple:
8053
8211
  """
8054
8212
  Return ``True`` if the poset is Eulerian, and ``False`` otherwise.
8055
8213
 
@@ -8167,7 +8325,7 @@ class FinitePoset(UniqueRepresentation, Parent):
8167
8325
  return False
8168
8326
  return (True, None) if certificate else True
8169
8327
 
8170
- def is_greedy(self, certificate=False):
8328
+ def is_greedy(self, certificate=False) -> bool | tuple:
8171
8329
  """
8172
8330
  Return ``True`` if the poset is greedy, and ``False`` otherwise.
8173
8331
 
@@ -8543,35 +8701,69 @@ class FinitePoset(UniqueRepresentation, Parent):
8543
8701
  A cut is a subset `A` of ``self`` such that the set of lower
8544
8702
  bounds of the set of upper bounds of `A` is exactly `A`.
8545
8703
 
8546
- The cuts are computed here using the maximal independent sets in the
8547
- auxiliary graph defined as `P \times [0,1]` with an edge
8548
- from `(x, 0)` to `(y, 1)` if
8549
- and only if `x \not\geq_P y`. See the end of section 4 in [JRJ94]_.
8704
+ The cuts are computed as the smallest family of subsets of P containing its
8705
+ principal order filters, the whole set P and which is closed by intersection.
8550
8706
 
8551
8707
  EXAMPLES::
8552
8708
 
8553
8709
  sage: P = posets.AntichainPoset(3)
8554
8710
  sage: Pc = P.cuts()
8555
8711
  sage: Pc # random
8556
- [frozenset({0}),
8712
+ [frozenset({2}),
8713
+ frozenset({1}),
8714
+ frozenset({0}),
8557
8715
  frozenset(),
8558
- frozenset({0, 1, 2}),
8559
- frozenset({2}),
8560
- frozenset({1})]
8716
+ frozenset({0, 1, 2})]
8561
8717
  sage: sorted(list(c) for c in Pc)
8562
8718
  [[], [0], [0, 1, 2], [1], [2]]
8563
8719
 
8720
+ TESTS::
8721
+
8722
+ sage: P = Poset()
8723
+ sage: P.cuts()
8724
+ [frozenset()]
8725
+ sage: P = Poset({3: [4, 5, 7], 1: [2, 4, 6], 4: [], 0: [2, 5], 2: [7], 7: [], 5: [6], 6: []})
8726
+ sage: P.cuts()
8727
+ [frozenset({3, 4, 5, 6, 7}),
8728
+ frozenset({1, 2, 4, 6, 7}),
8729
+ frozenset({4}),
8730
+ frozenset({0, 2, 5, 6, 7}),
8731
+ frozenset({2, 7}),
8732
+ frozenset({7}),
8733
+ frozenset({5, 6}),
8734
+ frozenset({6}),
8735
+ frozenset({4, 6, 7}),
8736
+ frozenset({5, 6, 7}),
8737
+ frozenset({2, 6, 7}),
8738
+ frozenset(),
8739
+ frozenset({6, 7}),
8740
+ frozenset({0, 1, 2, 3, 4, 5, 6, 7})]
8741
+
8564
8742
  .. SEEALSO::
8565
8743
 
8566
8744
  :meth:`completion_by_cuts`
8567
8745
  """
8568
- from sage.graphs.graph import Graph
8569
- from sage.graphs.independent_sets import IndependentSets
8570
- auxg = Graph({(u, 0): [(v, 1) for v in self if not self.ge(u, v)]
8571
- for u in self}, format='dict_of_lists')
8572
- auxg.add_vertices([(v, 1) for v in self])
8573
- return [frozenset([xa for xa, xb in c if xb == 0])
8574
- for c in IndependentSets(auxg, maximal=True)]
8746
+ C, C2 = [], []
8747
+ for x in self:
8748
+ C.append(set(self.order_filter([x])))
8749
+ for i, c in enumerate(C):
8750
+ for j in range(i + 1, len(C)):
8751
+ I = c.intersection(C[j])
8752
+ if I not in C + C2:
8753
+ C2.append(I)
8754
+ while C2:
8755
+ D = []
8756
+ for x in C:
8757
+ for y in C2:
8758
+ I = x.intersection(y)
8759
+ if all(I not in X for X in [C, C2, D]):
8760
+ D.append(I)
8761
+ C.extend(C2)
8762
+ C2 = D
8763
+ S = set(self)
8764
+ if S not in C:
8765
+ C.append(S)
8766
+ return [frozenset(x) for x in C]
8575
8767
 
8576
8768
  def completion_by_cuts(self):
8577
8769
  """
@@ -8760,7 +8952,7 @@ class FinitePoset(UniqueRepresentation, Parent):
8760
8952
  poly = self._kl_poly(x, y, canonical_labels)
8761
8953
  return poly(q=q)
8762
8954
 
8763
- def is_induced_subposet(self, other):
8955
+ def is_induced_subposet(self, other) -> bool:
8764
8956
  r"""
8765
8957
  Return ``True`` if the poset is an induced subposet of ``other``, and
8766
8958
  ``False`` otherwise.
@@ -8837,8 +9029,7 @@ class FinitePoset(UniqueRepresentation, Parent):
8837
9029
  from sage.libs.gap.libgap import libgap
8838
9030
  libgap.LoadPackage("QPA")
8839
9031
  L = list(self)
8840
- g = libgap.Poset(L, [self.principal_order_filter(x) for x in L])
8841
- return g
9032
+ return libgap.Poset(L, [self.principal_order_filter(x) for x in L])
8842
9033
 
8843
9034
  def _macaulay2_init_(self, macaulay2=None):
8844
9035
  """
@@ -8905,7 +9096,7 @@ class FinitePosets_n(UniqueRepresentation, Parent):
8905
9096
  Parent.__init__(self, category=FiniteEnumeratedSets())
8906
9097
  self._n = n
8907
9098
 
8908
- def _repr_(self):
9099
+ def _repr_(self) -> str:
8909
9100
  r"""
8910
9101
  EXAMPLES::
8911
9102
 
@@ -8913,7 +9104,7 @@ class FinitePosets_n(UniqueRepresentation, Parent):
8913
9104
  sage: P._repr_()
8914
9105
  'Posets containing 3 elements'
8915
9106
  """
8916
- return "Posets containing %s elements" % self._n
9107
+ return f"Posets containing {self._n} elements"
8917
9108
 
8918
9109
  def __contains__(self, P) -> bool:
8919
9110
  """
@@ -8998,7 +9189,7 @@ Posets_all = Posets
8998
9189
  # ------- Miscellaneous functions -------
8999
9190
 
9000
9191
 
9001
- def is_poset(dig):
9192
+ def is_poset(dig) -> bool:
9002
9193
  r"""
9003
9194
  Return ``True`` if a directed graph is acyclic and transitively
9004
9195
  reduced, and ``False`` otherwise.