passagemath-graphs 10.5.43__cp312-cp312-macosx_14_0_arm64.whl → 10.6.1rc2__cp312-cp312-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-312-darwin.so +0 -0
  10. sage/combinat/designs/designs_pyx.pyx +2 -2
  11. sage/combinat/designs/evenly_distributed_sets.cpython-312-darwin.so +0 -0
  12. sage/combinat/designs/evenly_distributed_sets.pyx +4 -4
  13. sage/combinat/designs/gen_quadrangles_with_spread.cpython-312-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-312-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-312-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-312-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-312-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-312-darwin.so +0 -0
  39. sage/graphs/asteroidal_triples.pyx +24 -3
  40. sage/graphs/base/boost_graph.cpython-312-darwin.so +0 -0
  41. sage/graphs/base/boost_graph.pxd +3 -3
  42. sage/graphs/base/c_graph.cpython-312-darwin.so +0 -0
  43. sage/graphs/base/c_graph.pyx +1 -1
  44. sage/graphs/base/dense_graph.cpython-312-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-312-darwin.so +0 -0
  48. sage/graphs/base/sparse_graph.cpython-312-darwin.so +0 -0
  49. sage/graphs/base/static_dense_graph.cpython-312-darwin.so +0 -0
  50. sage/graphs/base/static_sparse_backend.cpython-312-darwin.so +0 -0
  51. sage/graphs/base/static_sparse_backend.pyx +8 -5
  52. sage/graphs/base/static_sparse_graph.cpython-312-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-312-darwin.so +0 -0
  56. sage/graphs/centrality.pyx +82 -9
  57. sage/graphs/cographs.py +1 -1
  58. sage/graphs/comparability.cpython-312-darwin.so +0 -0
  59. sage/graphs/comparability.pyx +64 -26
  60. sage/graphs/connectivity.cpython-312-darwin.so +0 -0
  61. sage/graphs/convexity_properties.cpython-312-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-312-darwin.so +0 -0
  66. sage/graphs/dot2tex_utils.py +1 -1
  67. sage/graphs/edge_connectivity.cpython-312-darwin.so +0 -0
  68. sage/graphs/generators/basic.py +1 -1
  69. sage/graphs/generators/distance_regular.cpython-312-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-312-darwin.so +0 -0
  76. sage/graphs/generic_graph_pyx.pyx +58 -11
  77. sage/graphs/genus.cpython-312-darwin.so +0 -0
  78. sage/graphs/genus.pyx +3 -4
  79. sage/graphs/graph.py +291 -8
  80. sage/graphs/graph_coloring.cpython-312-darwin.so +0 -0
  81. sage/graphs/graph_database.py +67 -12
  82. sage/graphs/graph_decompositions/bandwidth.cpython-312-darwin.so +0 -0
  83. sage/graphs/graph_decompositions/clique_separators.cpython-312-darwin.so +0 -0
  84. sage/graphs/graph_decompositions/clique_separators.pyx +24 -3
  85. sage/graphs/graph_decompositions/cutwidth.cpython-312-darwin.so +0 -0
  86. sage/graphs/graph_decompositions/fast_digraph.cpython-312-darwin.so +0 -0
  87. sage/graphs/graph_decompositions/fast_digraph.pyx +1 -1
  88. sage/graphs/graph_decompositions/graph_products.cpython-312-darwin.so +0 -0
  89. sage/graphs/graph_decompositions/graph_products.pyx +67 -21
  90. sage/graphs/graph_decompositions/modular_decomposition.cpython-312-darwin.so +0 -0
  91. sage/graphs/graph_decompositions/slice_decomposition.cpython-312-darwin.so +0 -0
  92. sage/graphs/graph_decompositions/slice_decomposition.pyx +34 -8
  93. sage/graphs/graph_decompositions/tree_decomposition.cpython-312-darwin.so +0 -0
  94. sage/graphs/graph_decompositions/vertex_separation.cpython-312-darwin.so +0 -0
  95. sage/graphs/graph_generators.py +45 -32
  96. sage/graphs/graph_generators_pyx.cpython-312-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-312-darwin.so +0 -0
  102. sage/graphs/hyperbolicity.pyx +2 -0
  103. sage/graphs/independent_sets.cpython-312-darwin.so +0 -0
  104. sage/graphs/isoperimetric_inequalities.cpython-312-darwin.so +0 -0
  105. sage/graphs/isoperimetric_inequalities.pyx +42 -6
  106. sage/graphs/line_graph.cpython-312-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-312-darwin.so +0 -0
  111. sage/graphs/path_enumeration.pyx +2 -2
  112. sage/graphs/spanning_tree.cpython-312-darwin.so +0 -0
  113. sage/graphs/strongly_regular_db.cpython-312-darwin.so +0 -0
  114. sage/graphs/strongly_regular_db.pyx +15 -15
  115. sage/graphs/traversals.cpython-312-darwin.so +0 -0
  116. sage/graphs/traversals.pyx +13 -12
  117. sage/graphs/trees.cpython-312-darwin.so +0 -0
  118. sage/graphs/tutte_polynomial.py +1 -1
  119. sage/graphs/views.cpython-312-darwin.so +0 -0
  120. sage/graphs/weakly_chordal.cpython-312-darwin.so +0 -0
  121. sage/graphs/weakly_chordal.pyx +50 -8
  122. sage/groups/perm_gps/partn_ref/refinement_graphs.cpython-312-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
@@ -38,6 +38,8 @@ Methods
38
38
 
39
39
  from memory_allocator cimport MemoryAllocator
40
40
  from sage.data_structures.bitset_base cimport *
41
+ from sage.graphs.base.static_sparse_backend cimport StaticSparseCGraph
42
+ from sage.graphs.base.static_sparse_backend cimport StaticSparseBackend
41
43
  from sage.graphs.base.static_sparse_graph cimport short_digraph
42
44
  from sage.graphs.base.static_sparse_graph cimport init_short_digraph
43
45
  from sage.graphs.base.static_sparse_graph cimport free_short_digraph
@@ -200,6 +202,17 @@ def is_long_hole_free(g, certificate=False):
200
202
 
201
203
  sage: graphs.EmptyGraph().is_long_hole_free()
202
204
  True
205
+
206
+ Immutable graphs::
207
+
208
+ sage: G = graphs.RandomGNP(10, .7)
209
+ sage: G._backend
210
+ <sage.graphs.base.sparse_graph.SparseGraphBackend ...>
211
+ sage: H = Graph(G, immutable=True)
212
+ sage: H._backend
213
+ <sage.graphs.base.static_sparse_backend.StaticSparseBackend ...>
214
+ sage: G.is_long_hole_free() == H.is_long_hole_free()
215
+ True
203
216
  """
204
217
  g._scream_if_not_simple()
205
218
 
@@ -212,9 +225,16 @@ def is_long_hole_free(g, certificate=False):
212
225
  # documented in the module sage.graphs.base.static_sparse_graph.
213
226
  # Vertices are relabeled in 0..n-1
214
227
  cdef int n = g.order()
215
- cdef list id_label = list(g)
228
+ cdef list id_label
229
+ cdef StaticSparseCGraph cg
216
230
  cdef short_digraph sd
217
- init_short_digraph(sd, g, edge_labelled=False, vertex_list=id_label)
231
+ if isinstance(g, StaticSparseBackend):
232
+ cg = <StaticSparseCGraph> g._cg
233
+ sd = <short_digraph> cg.g
234
+ id_label = cg._vertex_to_labels
235
+ else:
236
+ id_label = list(g)
237
+ init_short_digraph(sd, g, edge_labelled=False, vertex_list=id_label)
218
238
 
219
239
  # Make a dense copy of the graph for quick adjacency tests
220
240
  cdef bitset_t dense_graph
@@ -258,7 +278,8 @@ def is_long_hole_free(g, certificate=False):
258
278
 
259
279
  if not res:
260
280
  # We release memory before returning the result
261
- free_short_digraph(sd)
281
+ if not isinstance(g, StaticSparseBackend):
282
+ free_short_digraph(sd)
262
283
  bitset_free(dense_graph)
263
284
 
264
285
  if certificate:
@@ -269,7 +290,8 @@ def is_long_hole_free(g, certificate=False):
269
290
  InPath[u] = -1
270
291
 
271
292
  # Release memory
272
- free_short_digraph(sd)
293
+ if not isinstance(g, StaticSparseBackend):
294
+ free_short_digraph(sd)
273
295
  bitset_free(dense_graph)
274
296
 
275
297
  if certificate:
@@ -428,6 +450,17 @@ def is_long_antihole_free(g, certificate=False):
428
450
 
429
451
  sage: graphs.EmptyGraph().is_long_hole_free()
430
452
  True
453
+
454
+ Immutable graphs::
455
+
456
+ sage: G = graphs.RandomGNP(10, .7)
457
+ sage: G._backend
458
+ <sage.graphs.base.sparse_graph.SparseGraphBackend ...>
459
+ sage: H = Graph(G, immutable=True)
460
+ sage: H._backend
461
+ <sage.graphs.base.static_sparse_backend.StaticSparseBackend ...>
462
+ sage: G.is_long_antihole_free() == H.is_long_antihole_free()
463
+ True
431
464
  """
432
465
  g._scream_if_not_simple()
433
466
 
@@ -440,9 +473,16 @@ def is_long_antihole_free(g, certificate=False):
440
473
  # documented in the module sage.graphs.base.static_sparse_graph.
441
474
  # Vertices are relabeled in 0..n-1
442
475
  cdef int n = g.order()
443
- cdef list id_label = list(g)
476
+ cdef list id_label
477
+ cdef StaticSparseCGraph cg
444
478
  cdef short_digraph sd
445
- init_short_digraph(sd, g, edge_labelled=False, vertex_list=id_label)
479
+ if isinstance(g, StaticSparseBackend):
480
+ cg = <StaticSparseCGraph> g._cg
481
+ sd = <short_digraph> cg.g
482
+ id_label = cg._vertex_to_labels
483
+ else:
484
+ id_label = list(g)
485
+ init_short_digraph(sd, g, edge_labelled=False, vertex_list=id_label)
446
486
 
447
487
  # Make a dense copy of the graph for quick adjacency tests
448
488
  cdef bitset_t dense_graph
@@ -487,7 +527,8 @@ def is_long_antihole_free(g, certificate=False):
487
527
 
488
528
  if not res:
489
529
  # We release memory before returning the result
490
- free_short_digraph(sd)
530
+ if not isinstance(g, StaticSparseBackend):
531
+ free_short_digraph(sd)
491
532
  bitset_free(dense_graph)
492
533
 
493
534
  if certificate:
@@ -498,7 +539,8 @@ def is_long_antihole_free(g, certificate=False):
498
539
  InPath[u] = -1
499
540
 
500
541
  # Release memory
501
- free_short_digraph(sd)
542
+ if not isinstance(g, StaticSparseBackend):
543
+ free_short_digraph(sd)
502
544
  bitset_free(dense_graph)
503
545
 
504
546
  if certificate:
@@ -16,15 +16,15 @@ AUTHORS:
16
16
  - Sebastian Oehms June 2024: initial version
17
17
  """
18
18
 
19
- ##############################################################################
19
+ # ############################################################################
20
20
  # Copyright (C) 2024 Sebastian Oehms <seb.oehms@gmail.com>
21
21
  #
22
22
  # This program is free software: you can redistribute it and/or modify
23
23
  # it under the terms of the GNU General Public License as published by
24
24
  # the Free Software Foundation, either version 2 of the License, or
25
25
  # (at your option) any later version.
26
- # http://www.gnu.org/licenses/
27
- ##############################################################################
26
+ # https://www.gnu.org/licenses/
27
+ # ############################################################################
28
28
 
29
29
  from sage.knots.knotinfo import SymmetryMutant
30
30
  from sage.monoids.indexed_free_monoid import (IndexedFreeAbelianMonoid,
sage/knots/knotinfo.py CHANGED
@@ -16,7 +16,7 @@ package using
16
16
  - ``sage -f database_knotinfo`` (installs even if the current version is present)
17
17
 
18
18
  This will install a `Python wrapper <https://github.com/soehms/database_knotinfo#readme>`__
19
- for the original databases in Sage. This wrapper perfoms an automatic progress
19
+ for the original databases in Sage. This wrapper performs an automatic progress
20
20
  of version numbers. For more details and further install instructions please see
21
21
  the corresponding web-page.
22
22
 
@@ -449,7 +449,7 @@ class SymmetryMutant(Enum):
449
449
  res.append(self.rev().mir())
450
450
  return res
451
451
 
452
- def is_minimal(self, link):
452
+ def is_minimal(self, link) -> bool:
453
453
  r"""
454
454
  Return whether ``self`` is minimal among its matching mutants.
455
455
 
@@ -762,7 +762,7 @@ class KnotInfoBase(Enum):
762
762
 
763
763
  There has been a major change to braid representatives for
764
764
  proper links since version 2021.10.1. The former braid
765
- reresentatives can be obtained by the column
765
+ representatives can be obtained by the column
766
766
  ``braid_notation_old`` (see the final example below).
767
767
 
768
768
  EXAMPLES::
@@ -926,7 +926,7 @@ class KnotInfoBase(Enum):
926
926
  .. NOTE::
927
927
 
928
928
  KnotInfo's value for the unknot ``0_1`` is zero. This is not
929
- compatible whith Sage's result (the value of the Alexander
929
+ compatible with Sage's result (the value of the Alexander
930
930
  polynomial at -1). Since this method is needed to identify
931
931
  Sage links we take the according value in that case.
932
932
 
@@ -993,7 +993,7 @@ class KnotInfoBase(Enum):
993
993
  return knotinfo_int(self[self.items.signature])
994
994
 
995
995
  @cached_method
996
- def is_knot(self):
996
+ def is_knot(self) -> bool:
997
997
  r"""
998
998
  Return whether ``self`` is a knot or a proper link.
999
999
 
@@ -1064,7 +1064,7 @@ class KnotInfoBase(Enum):
1064
1064
  return symmetry_type
1065
1065
 
1066
1066
  @cached_method
1067
- def is_reversible(self):
1067
+ def is_reversible(self) -> bool:
1068
1068
  r"""
1069
1069
  Return whether ``self`` is reversible.
1070
1070
 
@@ -1097,7 +1097,7 @@ class KnotInfoBase(Enum):
1097
1097
  return None
1098
1098
 
1099
1099
  @cached_method
1100
- def is_amphicheiral(self, positive=False):
1100
+ def is_amphicheiral(self, positive=False) -> bool:
1101
1101
  r"""
1102
1102
  Return whether ``self`` is amphicheiral.
1103
1103
 
@@ -1185,7 +1185,7 @@ class KnotInfoBase(Enum):
1185
1185
  return None
1186
1186
 
1187
1187
  @cached_method
1188
- def is_hyperbolic(self):
1188
+ def is_hyperbolic(self) -> bool:
1189
1189
  r"""
1190
1190
  Return whether ``self`` is hyperbolic.
1191
1191
 
@@ -1202,7 +1202,7 @@ class KnotInfoBase(Enum):
1202
1202
  return False
1203
1203
 
1204
1204
  @cached_method
1205
- def is_alternating(self):
1205
+ def is_alternating(self) -> bool:
1206
1206
  r"""
1207
1207
  Return whether ``self`` is alternating.
1208
1208
 
@@ -1214,7 +1214,7 @@ class KnotInfoBase(Enum):
1214
1214
  return knotinfo_bool(self[self.items.alternating])
1215
1215
 
1216
1216
  @cached_method
1217
- def is_almost_alternating(self):
1217
+ def is_almost_alternating(self) -> bool:
1218
1218
  r"""
1219
1219
  Return whether ``self`` is almost alternating.
1220
1220
 
@@ -1227,7 +1227,7 @@ class KnotInfoBase(Enum):
1227
1227
  return knotinfo_bool(self[self.items.almost_alternating])
1228
1228
 
1229
1229
  @cached_method
1230
- def is_quasi_alternating(self):
1230
+ def is_quasi_alternating(self) -> bool:
1231
1231
  r"""
1232
1232
  Return whether ``self`` is quasi alternating.
1233
1233
 
@@ -1240,7 +1240,7 @@ class KnotInfoBase(Enum):
1240
1240
  return knotinfo_bool(self[self.items.quasi_alternating])
1241
1241
 
1242
1242
  @cached_method
1243
- def is_adequate(self):
1243
+ def is_adequate(self) -> bool:
1244
1244
  r"""
1245
1245
  Return whether ``self`` is adequate.
1246
1246
 
@@ -1253,7 +1253,7 @@ class KnotInfoBase(Enum):
1253
1253
  return knotinfo_bool(self[self.items.adequate])
1254
1254
 
1255
1255
  @cached_method
1256
- def is_positive(self):
1256
+ def is_positive(self) -> bool:
1257
1257
  r"""
1258
1258
  Return whether ``self`` is positive.
1259
1259
 
@@ -1265,7 +1265,7 @@ class KnotInfoBase(Enum):
1265
1265
  return knotinfo_bool(self[self.items.positive])
1266
1266
 
1267
1267
  @cached_method
1268
- def is_quasipositive(self):
1268
+ def is_quasipositive(self) -> bool:
1269
1269
  r"""
1270
1270
  Return whether ``self`` is quasi-positive.
1271
1271
 
@@ -1278,7 +1278,7 @@ class KnotInfoBase(Enum):
1278
1278
  return knotinfo_bool(self[self.items.quasipositive])
1279
1279
 
1280
1280
  @cached_method
1281
- def is_strongly_quasipositive(self):
1281
+ def is_strongly_quasipositive(self) -> bool:
1282
1282
  r"""
1283
1283
  Return whether ``self`` is strongly quasi-positive.
1284
1284
 
@@ -1291,7 +1291,7 @@ class KnotInfoBase(Enum):
1291
1291
  return knotinfo_bool(self[self.items.strongly_quasipositive])
1292
1292
 
1293
1293
  @cached_method
1294
- def is_positive_braid(self):
1294
+ def is_positive_braid(self) -> bool:
1295
1295
  r"""
1296
1296
  Return whether ``self`` is a positive braid.
1297
1297
 
@@ -1304,7 +1304,7 @@ class KnotInfoBase(Enum):
1304
1304
  return knotinfo_bool(self[self.items.positive_braid])
1305
1305
 
1306
1306
  @cached_method
1307
- def is_fibered(self):
1307
+ def is_fibered(self) -> bool:
1308
1308
  r"""
1309
1309
  Return whether ``self`` is fibered.
1310
1310
 
@@ -1316,7 +1316,7 @@ class KnotInfoBase(Enum):
1316
1316
  return knotinfo_bool(self[self.items.fibered])
1317
1317
 
1318
1318
  @cached_method
1319
- def is_oriented(self):
1319
+ def is_oriented(self) -> bool:
1320
1320
  r"""
1321
1321
  Return whether ``self`` is oriented.
1322
1322
 
@@ -1891,30 +1891,37 @@ class KnotInfoBase(Enum):
1891
1891
  return R(eval_knotinfo(conway_polynomial, locals=lc))
1892
1892
 
1893
1893
  @cached_method
1894
- def khovanov_polynomial(self, var1='q', var2='t', base_ring=ZZ, original=False, reduced=False, odd=False, KhoHo=False):
1894
+ def khovanov_polynomial(self, var1='q', var2='t', torsion='T', ring=None, original=False,
1895
+ reduced=False, odd=False, base_ring=None):
1895
1896
  r"""
1896
- Return the Khovanov polynomial according to the value of column
1897
- ``khovanov_polynomial`` for this knot or link as an instance of
1897
+ Return the Khovanov polynomial according to the value of columns
1898
+ ``khovanov_*`` for this knot or link as an instance of
1898
1899
  :class:`~sage.rings.polynomial.laurent_polynomial.LaurentPolynomial_mpair`.
1899
1900
 
1900
1901
  INPUT:
1901
1902
 
1902
- - ``var1`` -- (default: ``'q'``) the first variable
1903
- - ``var2`` -- (default: ``'t'``) the second variable
1904
- - ``base_ring`` -- (default: ``ZZ``) the ring of the polynomial's
1905
- coefficients
1903
+ - ``var1`` -- (default: ``'q'``) the first variable; its exponents
1904
+ correspond to the height of Khovanov homology
1905
+ - ``var2`` -- (default: ``'t'``) the second variable; its exponents
1906
+ correspond to the degree of Khovanov homology
1907
+ - ``torsion`` -- (default: ``'T'``) additional variable to indicate
1908
+ the torsion of the integral homology group corresponding to the
1909
+ monomial; monomials without it correspond to torsion free ``ring``
1910
+ modules; if it appears, its exponents stands for the modulus of
1911
+ the torsion
1912
+ - ``ring`` -- (default: ``ZZ`` for knots and ``QQ`` for proper links)
1913
+ the ring for the homology
1906
1914
  - ``original`` -- boolean (default: ``False``); if set to
1907
1915
  ``True`` the original table entry is returned as a string
1908
1916
  - ``reduced`` -- boolean (default: ``False``); if set to ``True``
1909
1917
  the reduced version of the homology is used
1910
1918
  - ``odd`` -- boolean (default: ``False``); if set to ``True``
1911
1919
  the odd version of the homology is used
1912
- - ``KhoHo`` -- boolean (deprecated). The corresponding values have
1913
- disappeared from the database since January 2024
1914
1920
 
1915
1921
  OUTPUT:
1916
1922
 
1917
- A Laurent polynomial over the integers, more precisely an instance of
1923
+ A two or three (for integral homology) variate Laurent polynomial over
1924
+ ``ZZ``, more precisely an instance of
1918
1925
  :class:`~sage.rings.polynomial.laurent_polynomial.LaurentPolynomial_mpair`.
1919
1926
  If ``original`` is set to ``True`` then a string is returned.
1920
1927
 
@@ -1931,11 +1938,9 @@ class KnotInfoBase(Enum):
1931
1938
 
1932
1939
  sage: K = KnotInfo.K6_3
1933
1940
  sage: Kk = K.khovanov_polynomial(); Kk
1934
- q^7*t^3 + q^5*t^2 + q^3*t^2 + q^3*t + q*t + 2*q + 2*q^-1 + q^-1*t^-1
1935
- + q^-3*t^-1 + q^-3*t^-2 + q^-5*t^-2 + q^-7*t^-3
1936
- sage: Kk2 = K.khovanov_polynomial(var1='p', base_ring=GF(2)); Kk2
1937
- p^7*t^3 + p^5*t^3 + p^5*t^2 + p^3*t + p^-1 + p^-1*t^-1 + p^-3*t^-2 + p^-7*t^-3
1938
-
1941
+ q^7*t^3 + q^5*t^3*T^2 + q^5*t^2 + q^3*t^2*T^2 + q^3*t^2 + q^3*t + q*t*T^2 + q*t
1942
+ + 2*q + q^-1*T^2 + 2*q^-1 + q^-1*t^-1 + q^-3*t^-1*T^2 + q^-3*t^-1 + q^-3*t^-2
1943
+ + q^-5*t^-2*T^2 + q^-5*t^-2 + q^-7*t^-3
1939
1944
  sage: L = KnotInfo.L5a1_0
1940
1945
  sage: Lk = L.khovanov_polynomial(); Lk
1941
1946
  q^4*t^2 + t + 2 + 2*q^-2 + q^-2*t^-1 + q^-4*t^-2 + q^-6*t^-2 + q^-8*t^-3
@@ -1946,10 +1951,10 @@ class KnotInfoBase(Enum):
1946
1951
 
1947
1952
  sage: Kkr = K.khovanov_polynomial(reduced=True); Kkr
1948
1953
  q^6*t^3 + 2*q^4*t^2 + 2*q^2*t + 3 + 2*q^-2*t^-1 + 2*q^-4*t^-2 + q^-6*t^-3
1949
- sage: K.khovanov_polynomial(base_ring=QQ, reduced=True) == Kkr
1954
+ sage: K.khovanov_polynomial(ring=QQ, reduced=True) == Kkr
1950
1955
  True
1951
- sage: Kkr2 = K.khovanov_polynomial(base_ring=GF(2), reduced=True); Kkr2
1952
- q^6*t^3 + 1 + q^-6*t^-3
1956
+ sage: Kkr2 = K.khovanov_polynomial(var1='p', ring=GF(2), reduced=True); Kkr2
1957
+ p^6*t^3 + 2*p^4*t^2 + 2*p^2*t + 3 + 2*p^-2*t^-1 + 2*p^-4*t^-2 + p^-6*t^-3
1953
1958
  sage: KnotInfo.K8_19.inject() # optional database_knotinfo
1954
1959
  Defining K8_19
1955
1960
  sage: K8kr = K8_19.khovanov_polynomial(reduced=True); K8kr # optional database_knotinfo
@@ -1959,23 +1964,27 @@ class KnotInfoBase(Enum):
1959
1964
 
1960
1965
  sage: K.khovanov_polynomial(odd=True) == Kkr
1961
1966
  True
1962
- sage: K.khovanov_polynomial(base_ring=QQ, odd=True) == Kkr
1967
+ sage: K.khovanov_polynomial(ring=QQ, odd=True) == Kkr
1963
1968
  True
1964
- sage: K.khovanov_polynomial(base_ring=GF(2), odd=True) == Kkr2
1969
+ sage: K.khovanov_polynomial(var1='p', ring=GF(2), odd=True) == Kkr2
1965
1970
  True
1966
1971
  sage: K8ko = K8_19.khovanov_polynomial(odd=True); K8ko # optional database_knotinfo
1967
- q^16*t^5 + q^10*t^2 + q^6
1972
+ q^14*t^5*T^3 + q^16*t^5 + q^12*t^4*T^2 + q^10*t^2 + q^6
1968
1973
  sage: K8kr == K8ko # optional database_knotinfo
1969
1974
  False
1970
1975
 
1976
+ Caution::
1977
+
1978
+ sage: Kk2 = K.khovanov_polynomial(ring=GF(2))
1979
+ Traceback (most recent call last):
1980
+ ...
1981
+ NotImplementedError: unreduced Khovanov polynomial available only for integral homology
1971
1982
 
1972
1983
  Comparison to Sage's results::
1973
1984
 
1974
1985
  sage: Kk == K.link().khovanov_polynomial()
1975
1986
  True
1976
- sage: Kk2 == K.link().khovanov_polynomial(var1='p', base_ring=GF(2))
1977
- True
1978
- sage: Lk == L.link().khovanov_polynomial()
1987
+ sage: Lk == L.link().khovanov_polynomial(ring=QQ)
1979
1988
  True
1980
1989
 
1981
1990
  TESTS::
@@ -1988,36 +1997,47 @@ class KnotInfoBase(Enum):
1988
1997
  1
1989
1998
  sage: K0_1.khovanov_polynomial(odd=True)
1990
1999
  1
1991
- sage: K0_1.khovanov_polynomial(base_ring=GF(3), reduced=True)
2000
+ sage: K0_1.khovanov_polynomial(ring=GF(3), reduced=True)
1992
2001
  Traceback (most recent call last):
1993
2002
  ...
1994
- ValueError: characteristic 3 of base ring is not valid
1995
- sage: K0_1.khovanov_polynomial(base_ring=GF(3), odd=True)
2003
+ ValueError: characteristic 3 of ring is not valid
2004
+ sage: K0_1.khovanov_polynomial(ring=GF(3), odd=True)
1996
2005
  Traceback (most recent call last):
1997
2006
  ...
1998
- ValueError: characteristic 3 of base ring is not valid
1999
- sage: L.khovanov_polynomial(base_ring=GF(2))
2007
+ ValueError: characteristic 3 of ring is not valid
2008
+ sage: L.khovanov_polynomial(ring=GF(2))
2000
2009
  Traceback (most recent call last):
2001
2010
  ...
2002
- NotImplementedError: Khovanov polynomial available only for knots in characteristic 2
2011
+ NotImplementedError: Khovanov polynomial not available for multi-component links for this ring
2003
2012
 
2004
2013
  REFERENCES:
2005
2014
 
2006
2015
  - :wikipedia:`Khovanov_homology`
2007
2016
  - :wikipedia:`Reduced_homology`
2008
2017
  - [ORS2013]_
2018
+ - `KnotInfo <https://knotinfo.math.indiana.edu/descriptions/khovanov_unreduced_integral_polynomial.html>`__
2009
2019
  """
2010
- ch = base_ring.characteristic()
2011
- integral = ch == 0 and base_ring.is_field()
2020
+ if not ring:
2021
+ if self.is_knot():
2022
+ ring = ZZ
2023
+ else:
2024
+ from sage.rings.rational_field import QQ
2025
+ ring = QQ
2026
+
2027
+ if base_ring:
2028
+ ring = base_ring
2029
+ from sage.misc.superseded import deprecation
2030
+ deprecation(40149, "base_ring is deprecated, use argument ring instead.")
2031
+
2032
+ ch = ring.characteristic()
2033
+ integral = (ch == 0) and (not ring.is_field())
2012
2034
  if not self.is_knot():
2013
2035
  # KnotJob calculated results only available for knots
2014
- khovanov_polynomial = self[self.items.khovanov_polynomial]
2015
- KhoHo = True
2036
+ if ch == 0 and ring.is_field():
2037
+ khovanov_polynomial = self[self.items.khovanov_polynomial]
2038
+ else:
2039
+ raise NotImplementedError('Khovanov polynomial not available for multi-component links for this ring')
2016
2040
  else:
2017
- if KhoHo:
2018
- KhoHo = False
2019
- from sage.misc.superseded import deprecation
2020
- deprecation(37014, "the KhoHo option is deprecated and ignored.")
2021
2041
  if reduced:
2022
2042
  if integral:
2023
2043
  khovanov_polynomial = self[self.items.khovanov_reduced_integral_polynomial]
@@ -2026,7 +2046,7 @@ class KnotInfoBase(Enum):
2026
2046
  elif ch == 2:
2027
2047
  khovanov_polynomial = self[self.items.khovanov_reduced_mod2_polynomial]
2028
2048
  else:
2029
- raise ValueError('characteristic %s of base ring is not valid' % ch)
2049
+ raise ValueError('characteristic %s of ring is not valid' % ch)
2030
2050
  elif odd:
2031
2051
  if integral:
2032
2052
  khovanov_polynomial = self[self.items.khovanov_odd_integral_polynomial]
@@ -2035,30 +2055,32 @@ class KnotInfoBase(Enum):
2035
2055
  elif ch == 2:
2036
2056
  khovanov_polynomial = self[self.items.khovanov_odd_mod2_polynomial]
2037
2057
  else:
2038
- raise ValueError('characteristic %s of base ring is not valid' % ch)
2058
+ raise ValueError('characteristic %s of ring is not valid' % ch)
2039
2059
  else:
2040
- khovanov_polynomial = self[self.items.khovanov_unreduced_integral_polynomial]
2060
+ if integral:
2061
+ khovanov_polynomial = self[self.items.khovanov_unreduced_integral_polynomial]
2062
+ else:
2063
+ raise NotImplementedError('unreduced Khovanov polynomial available only for integral homology')
2041
2064
 
2042
2065
  if original:
2043
2066
  return khovanov_polynomial
2044
2067
 
2045
2068
  from sage.rings.polynomial.laurent_polynomial_ring import LaurentPolynomialRing
2046
- var_names = [var1, var2]
2047
- R = LaurentPolynomialRing(base_ring, var_names)
2069
+ if integral:
2070
+ var_names = [var1, var2, torsion]
2071
+ else:
2072
+ var_names = [var1, var2]
2073
+
2074
+ R = LaurentPolynomialRing(ZZ, var_names)
2048
2075
 
2049
2076
  if not khovanov_polynomial and self.crossing_number() == 0:
2050
2077
  if reduced or odd:
2051
2078
  return R.one()
2052
2079
  else:
2053
- return R({(1, 0): 1, (-1, 0): 1})
2054
-
2055
- if ch == 2:
2056
- if not self.is_knot():
2057
- raise NotImplementedError('Khovanov polynomial available only for knots in characteristic 2')
2058
- if KhoHo:
2059
- khovanov_torsion_polynomial = self[self.items.khovanov_torsion_polynomial]
2060
- khovanov_torsion_polynomial = khovanov_torsion_polynomial.replace('Q', 'q')
2061
- khovanov_polynomial = '%s + %s' % (khovanov_polynomial, khovanov_torsion_polynomial)
2080
+ if integral:
2081
+ return R({(1, 0, 0): 1, (-1, 0, 0): 1})
2082
+ else:
2083
+ return R({(1, 0): 1, (-1, 0): 1})
2062
2084
 
2063
2085
  if not khovanov_polynomial:
2064
2086
  # given just for links with less than 12 crossings
@@ -2075,10 +2097,8 @@ class KnotInfoBase(Enum):
2075
2097
  lc = {}
2076
2098
  lc['q'] = gens[var1]
2077
2099
  lc['t'] = gens[var2]
2078
- if ch == 2:
2079
- lc['T'] = 1
2080
- else:
2081
- lc['T'] = 0
2100
+ if integral:
2101
+ lc['T'] = gens[torsion]
2082
2102
 
2083
2103
  return R(eval_knotinfo(khovanov_polynomial, locals=lc))
2084
2104
 
@@ -2230,7 +2250,7 @@ class KnotInfoBase(Enum):
2230
2250
  raise ValueError('link construction using %s not possible' % use_item)
2231
2251
 
2232
2252
  @cached_method
2233
- def is_unique(self):
2253
+ def is_unique(self) -> bool:
2234
2254
  r"""
2235
2255
  Return whether there is no other isotopic link in the database or not.
2236
2256
 
@@ -2276,7 +2296,7 @@ class KnotInfoBase(Enum):
2276
2296
  return None
2277
2297
 
2278
2298
  @cached_method
2279
- def is_recoverable(self, unique=True):
2299
+ def is_recoverable(self, unique=True) -> bool:
2280
2300
  r"""
2281
2301
  Return if ``self`` can be recovered from its conversion to Sage links
2282
2302
  using the ``pd_notation`` and the ``braid_notation`` and their
@@ -2555,17 +2575,17 @@ class KnotInfoSeries(UniqueRepresentation, SageObject):
2555
2575
  keyword has to be set to ``True``.
2556
2576
 
2557
2577
  - ``comp`` -- (default: ``None``) if given an integer for this
2558
- keyword the list is restriced to links having the according number
2578
+ keyword the list is restricted to links having the according number
2559
2579
  of components. This keyword implies ``oriented=True``.
2560
2580
 
2561
2581
  - ``det`` -- (default: ``None``) if given an integer for this
2562
- keyword the list is restriced to links having the according value
2582
+ keyword the list is restricted to links having the according value
2563
2583
  for its determinant. This keyword implies ``oriented=True``.
2564
2584
 
2565
2585
  - ``homfly`` -- (default: ``None``) if given a HOMFLY-PT polynomial
2566
- having ``normalization='vz'`` for this keyword the list is restriced to
2567
- links having the according value for its HOMFLY-PT polynomial. This
2568
- keyword implies ``oriented=True``.
2586
+ having ``normalization='vz'`` for this keyword the list is restricted
2587
+ to links having the according value for its HOMFLY-PT
2588
+ polynomial. This keyword implies ``oriented=True``.
2569
2589
 
2570
2590
  EXAMPLES::
2571
2591
 
@@ -2789,7 +2809,7 @@ class KnotInfoSeries(UniqueRepresentation, SageObject):
2789
2809
  res = 'L%s%s' % (cross_nr, alt)
2790
2810
  return res
2791
2811
 
2792
- def is_recoverable(self, unique=True, max_samples=8):
2812
+ def is_recoverable(self, unique=True, max_samples=8) -> bool:
2793
2813
  r"""
2794
2814
  Return if all items of ``self`` can be recovered from its conversion to
2795
2815
  Sage links using the ``pd_notation`` and the ``braid_notation`` and their