passagemath-graphs 10.6.1rc1__cp310-cp310-musllinux_1_2_aarch64.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.
- passagemath_graphs-10.6.1rc1.dist-info/METADATA +292 -0
- passagemath_graphs-10.6.1rc1.dist-info/RECORD +260 -0
- passagemath_graphs-10.6.1rc1.dist-info/WHEEL +5 -0
- passagemath_graphs-10.6.1rc1.dist-info/top_level.txt +2 -0
- passagemath_graphs.libs/libgcc_s-69c45f16.so.1 +0 -0
- passagemath_graphs.libs/libgmp-8e78bd9b.so.10.5.0 +0 -0
- passagemath_graphs.libs/libstdc++-1f1a71be.so.6.0.33 +0 -0
- sage/all__sagemath_graphs.py +39 -0
- sage/combinat/abstract_tree.py +2723 -0
- sage/combinat/all__sagemath_graphs.py +34 -0
- sage/combinat/binary_tree.py +5306 -0
- sage/combinat/cluster_algebra_quiver/all.py +22 -0
- sage/combinat/cluster_algebra_quiver/cluster_seed.py +5208 -0
- sage/combinat/cluster_algebra_quiver/interact.py +124 -0
- sage/combinat/cluster_algebra_quiver/mutation_class.py +625 -0
- sage/combinat/cluster_algebra_quiver/mutation_type.py +1555 -0
- sage/combinat/cluster_algebra_quiver/quiver.py +2290 -0
- sage/combinat/cluster_algebra_quiver/quiver_mutation_type.py +2468 -0
- sage/combinat/designs/MOLS_handbook_data.py +570 -0
- sage/combinat/designs/all.py +58 -0
- sage/combinat/designs/bibd.py +1655 -0
- sage/combinat/designs/block_design.py +1071 -0
- sage/combinat/designs/covering_array.py +269 -0
- sage/combinat/designs/covering_design.py +530 -0
- sage/combinat/designs/database.py +5615 -0
- sage/combinat/designs/design_catalog.py +122 -0
- sage/combinat/designs/designs_pyx.cpython-310-aarch64-linux-gnu.so +0 -0
- sage/combinat/designs/designs_pyx.pxd +21 -0
- sage/combinat/designs/designs_pyx.pyx +993 -0
- sage/combinat/designs/difference_family.py +3951 -0
- sage/combinat/designs/difference_matrices.py +279 -0
- sage/combinat/designs/evenly_distributed_sets.cpython-310-aarch64-linux-gnu.so +0 -0
- sage/combinat/designs/evenly_distributed_sets.pyx +661 -0
- sage/combinat/designs/ext_rep.py +1064 -0
- sage/combinat/designs/gen_quadrangles_with_spread.cpython-310-aarch64-linux-gnu.so +0 -0
- sage/combinat/designs/gen_quadrangles_with_spread.pyx +339 -0
- sage/combinat/designs/group_divisible_designs.py +361 -0
- sage/combinat/designs/incidence_structures.py +2357 -0
- sage/combinat/designs/latin_squares.py +581 -0
- sage/combinat/designs/orthogonal_arrays.py +2244 -0
- sage/combinat/designs/orthogonal_arrays_build_recursive.py +1780 -0
- sage/combinat/designs/orthogonal_arrays_find_recursive.cpython-310-aarch64-linux-gnu.so +0 -0
- sage/combinat/designs/orthogonal_arrays_find_recursive.pyx +967 -0
- sage/combinat/designs/resolvable_bibd.py +815 -0
- sage/combinat/designs/steiner_quadruple_systems.py +1306 -0
- sage/combinat/designs/subhypergraph_search.cpython-310-aarch64-linux-gnu.so +0 -0
- sage/combinat/designs/subhypergraph_search.pyx +530 -0
- sage/combinat/designs/twographs.py +306 -0
- sage/combinat/finite_state_machine.py +14874 -0
- sage/combinat/finite_state_machine_generators.py +2006 -0
- sage/combinat/graph_path.py +448 -0
- sage/combinat/interval_posets.py +3908 -0
- sage/combinat/nu_tamari_lattice.py +269 -0
- sage/combinat/ordered_tree.py +1446 -0
- sage/combinat/posets/all.py +46 -0
- sage/combinat/posets/bubble_shuffle.py +247 -0
- sage/combinat/posets/cartesian_product.py +493 -0
- sage/combinat/posets/d_complete.py +182 -0
- sage/combinat/posets/elements.py +273 -0
- sage/combinat/posets/forest.py +30 -0
- sage/combinat/posets/hasse_cython.cpython-310-aarch64-linux-gnu.so +0 -0
- sage/combinat/posets/hasse_cython.pyx +174 -0
- sage/combinat/posets/hasse_diagram.py +3672 -0
- sage/combinat/posets/hochschild_lattice.py +158 -0
- sage/combinat/posets/incidence_algebras.py +794 -0
- sage/combinat/posets/lattices.py +5117 -0
- sage/combinat/posets/linear_extension_iterator.cpython-310-aarch64-linux-gnu.so +0 -0
- sage/combinat/posets/linear_extension_iterator.pyx +292 -0
- sage/combinat/posets/linear_extensions.py +1037 -0
- sage/combinat/posets/mobile.py +275 -0
- sage/combinat/posets/moebius_algebra.py +776 -0
- sage/combinat/posets/poset_examples.py +2178 -0
- sage/combinat/posets/posets.py +9360 -0
- sage/combinat/rooted_tree.py +1070 -0
- sage/combinat/shard_order.py +239 -0
- sage/combinat/tamari_lattices.py +384 -0
- sage/combinat/yang_baxter_graph.py +923 -0
- sage/databases/all__sagemath_graphs.py +1 -0
- sage/databases/knotinfo_db.py +1231 -0
- sage/ext_data/all__sagemath_graphs.py +1 -0
- sage/ext_data/graphs/graph_plot_js.html +330 -0
- sage/ext_data/kenzo/CP2.txt +45 -0
- sage/ext_data/kenzo/CP3.txt +349 -0
- sage/ext_data/kenzo/CP4.txt +4774 -0
- sage/ext_data/kenzo/README.txt +49 -0
- sage/ext_data/kenzo/S4.txt +20 -0
- sage/graphs/all.py +42 -0
- sage/graphs/asteroidal_triples.cpython-310-aarch64-linux-gnu.so +0 -0
- sage/graphs/asteroidal_triples.pyx +320 -0
- sage/graphs/base/all.py +1 -0
- sage/graphs/base/boost_graph.cpython-310-aarch64-linux-gnu.so +0 -0
- sage/graphs/base/boost_graph.pxd +106 -0
- sage/graphs/base/boost_graph.pyx +3045 -0
- sage/graphs/base/c_graph.cpython-310-aarch64-linux-gnu.so +0 -0
- sage/graphs/base/c_graph.pxd +106 -0
- sage/graphs/base/c_graph.pyx +5096 -0
- sage/graphs/base/dense_graph.cpython-310-aarch64-linux-gnu.so +0 -0
- sage/graphs/base/dense_graph.pxd +28 -0
- sage/graphs/base/dense_graph.pyx +801 -0
- sage/graphs/base/graph_backends.cpython-310-aarch64-linux-gnu.so +0 -0
- sage/graphs/base/graph_backends.pxd +5 -0
- sage/graphs/base/graph_backends.pyx +797 -0
- sage/graphs/base/overview.py +85 -0
- sage/graphs/base/sparse_graph.cpython-310-aarch64-linux-gnu.so +0 -0
- sage/graphs/base/sparse_graph.pxd +90 -0
- sage/graphs/base/sparse_graph.pyx +1653 -0
- sage/graphs/base/static_dense_graph.cpython-310-aarch64-linux-gnu.so +0 -0
- sage/graphs/base/static_dense_graph.pxd +5 -0
- sage/graphs/base/static_dense_graph.pyx +1032 -0
- sage/graphs/base/static_sparse_backend.cpython-310-aarch64-linux-gnu.so +0 -0
- sage/graphs/base/static_sparse_backend.pxd +27 -0
- sage/graphs/base/static_sparse_backend.pyx +1583 -0
- sage/graphs/base/static_sparse_graph.cpython-310-aarch64-linux-gnu.so +0 -0
- sage/graphs/base/static_sparse_graph.pxd +37 -0
- sage/graphs/base/static_sparse_graph.pyx +1375 -0
- sage/graphs/bipartite_graph.py +2732 -0
- sage/graphs/centrality.cpython-310-aarch64-linux-gnu.so +0 -0
- sage/graphs/centrality.pyx +1038 -0
- sage/graphs/cographs.py +519 -0
- sage/graphs/comparability.cpython-310-aarch64-linux-gnu.so +0 -0
- sage/graphs/comparability.pyx +851 -0
- sage/graphs/connectivity.cpython-310-aarch64-linux-gnu.so +0 -0
- sage/graphs/connectivity.pxd +157 -0
- sage/graphs/connectivity.pyx +4813 -0
- sage/graphs/convexity_properties.cpython-310-aarch64-linux-gnu.so +0 -0
- sage/graphs/convexity_properties.pxd +16 -0
- sage/graphs/convexity_properties.pyx +870 -0
- sage/graphs/digraph.py +4754 -0
- sage/graphs/digraph_generators.py +1993 -0
- sage/graphs/distances_all_pairs.cpython-310-aarch64-linux-gnu.so +0 -0
- sage/graphs/distances_all_pairs.pxd +12 -0
- sage/graphs/distances_all_pairs.pyx +2938 -0
- sage/graphs/domination.py +1363 -0
- sage/graphs/dot2tex_utils.py +100 -0
- sage/graphs/edge_connectivity.cpython-310-aarch64-linux-gnu.so +0 -0
- sage/graphs/edge_connectivity.pyx +1215 -0
- sage/graphs/generators/all.py +1 -0
- sage/graphs/generators/basic.py +1769 -0
- sage/graphs/generators/chessboard.py +538 -0
- sage/graphs/generators/classical_geometries.py +1611 -0
- sage/graphs/generators/degree_sequence.py +235 -0
- sage/graphs/generators/distance_regular.cpython-310-aarch64-linux-gnu.so +0 -0
- sage/graphs/generators/distance_regular.pyx +2846 -0
- sage/graphs/generators/families.py +4759 -0
- sage/graphs/generators/intersection.py +565 -0
- sage/graphs/generators/platonic_solids.py +262 -0
- sage/graphs/generators/random.py +2623 -0
- sage/graphs/generators/smallgraphs.py +5741 -0
- sage/graphs/generators/world_map.py +724 -0
- sage/graphs/generic_graph.py +26867 -0
- sage/graphs/generic_graph_pyx.cpython-310-aarch64-linux-gnu.so +0 -0
- sage/graphs/generic_graph_pyx.pxd +34 -0
- sage/graphs/generic_graph_pyx.pyx +1673 -0
- sage/graphs/genus.cpython-310-aarch64-linux-gnu.so +0 -0
- sage/graphs/genus.pyx +622 -0
- sage/graphs/graph.py +9645 -0
- sage/graphs/graph_coloring.cpython-310-aarch64-linux-gnu.so +0 -0
- sage/graphs/graph_coloring.pyx +2284 -0
- sage/graphs/graph_database.py +1177 -0
- sage/graphs/graph_decompositions/all.py +1 -0
- sage/graphs/graph_decompositions/bandwidth.cpython-310-aarch64-linux-gnu.so +0 -0
- sage/graphs/graph_decompositions/bandwidth.pyx +428 -0
- sage/graphs/graph_decompositions/clique_separators.cpython-310-aarch64-linux-gnu.so +0 -0
- sage/graphs/graph_decompositions/clique_separators.pyx +616 -0
- sage/graphs/graph_decompositions/cutwidth.cpython-310-aarch64-linux-gnu.so +0 -0
- sage/graphs/graph_decompositions/cutwidth.pyx +753 -0
- sage/graphs/graph_decompositions/fast_digraph.cpython-310-aarch64-linux-gnu.so +0 -0
- sage/graphs/graph_decompositions/fast_digraph.pxd +13 -0
- sage/graphs/graph_decompositions/fast_digraph.pyx +212 -0
- sage/graphs/graph_decompositions/graph_products.cpython-310-aarch64-linux-gnu.so +0 -0
- sage/graphs/graph_decompositions/graph_products.pyx +508 -0
- sage/graphs/graph_decompositions/modular_decomposition.cpython-310-aarch64-linux-gnu.so +0 -0
- sage/graphs/graph_decompositions/modular_decomposition.pxd +27 -0
- sage/graphs/graph_decompositions/modular_decomposition.pyx +1536 -0
- sage/graphs/graph_decompositions/slice_decomposition.cpython-310-aarch64-linux-gnu.so +0 -0
- sage/graphs/graph_decompositions/slice_decomposition.pxd +18 -0
- sage/graphs/graph_decompositions/slice_decomposition.pyx +1106 -0
- sage/graphs/graph_decompositions/tree_decomposition.cpython-310-aarch64-linux-gnu.so +0 -0
- sage/graphs/graph_decompositions/tree_decomposition.pxd +17 -0
- sage/graphs/graph_decompositions/tree_decomposition.pyx +1996 -0
- sage/graphs/graph_decompositions/vertex_separation.cpython-310-aarch64-linux-gnu.so +0 -0
- sage/graphs/graph_decompositions/vertex_separation.pxd +5 -0
- sage/graphs/graph_decompositions/vertex_separation.pyx +1963 -0
- sage/graphs/graph_editor.py +82 -0
- sage/graphs/graph_generators.py +3314 -0
- sage/graphs/graph_generators_pyx.cpython-310-aarch64-linux-gnu.so +0 -0
- sage/graphs/graph_generators_pyx.pyx +95 -0
- sage/graphs/graph_input.py +812 -0
- sage/graphs/graph_latex.py +2064 -0
- sage/graphs/graph_list.py +410 -0
- sage/graphs/graph_plot.py +1756 -0
- sage/graphs/graph_plot_js.py +338 -0
- sage/graphs/hyperbolicity.cpython-310-aarch64-linux-gnu.so +0 -0
- sage/graphs/hyperbolicity.pyx +1704 -0
- sage/graphs/hypergraph_generators.py +364 -0
- sage/graphs/independent_sets.cpython-310-aarch64-linux-gnu.so +0 -0
- sage/graphs/independent_sets.pxd +13 -0
- sage/graphs/independent_sets.pyx +402 -0
- sage/graphs/isgci.py +1033 -0
- sage/graphs/isoperimetric_inequalities.cpython-310-aarch64-linux-gnu.so +0 -0
- sage/graphs/isoperimetric_inequalities.pyx +489 -0
- sage/graphs/line_graph.cpython-310-aarch64-linux-gnu.so +0 -0
- sage/graphs/line_graph.pyx +743 -0
- sage/graphs/lovasz_theta.py +77 -0
- sage/graphs/matching.py +1633 -0
- sage/graphs/matching_covered_graph.py +3590 -0
- sage/graphs/orientations.py +1489 -0
- sage/graphs/partial_cube.py +459 -0
- sage/graphs/path_enumeration.cpython-310-aarch64-linux-gnu.so +0 -0
- sage/graphs/path_enumeration.pyx +2040 -0
- sage/graphs/pq_trees.py +1129 -0
- sage/graphs/print_graphs.py +201 -0
- sage/graphs/schnyder.py +865 -0
- sage/graphs/spanning_tree.cpython-310-aarch64-linux-gnu.so +0 -0
- sage/graphs/spanning_tree.pyx +1457 -0
- sage/graphs/strongly_regular_db.cpython-310-aarch64-linux-gnu.so +0 -0
- sage/graphs/strongly_regular_db.pyx +3340 -0
- sage/graphs/traversals.cpython-310-aarch64-linux-gnu.so +0 -0
- sage/graphs/traversals.pxd +9 -0
- sage/graphs/traversals.pyx +1872 -0
- sage/graphs/trees.cpython-310-aarch64-linux-gnu.so +0 -0
- sage/graphs/trees.pxd +15 -0
- sage/graphs/trees.pyx +310 -0
- sage/graphs/tutte_polynomial.py +713 -0
- sage/graphs/views.cpython-310-aarch64-linux-gnu.so +0 -0
- sage/graphs/views.pyx +794 -0
- sage/graphs/weakly_chordal.cpython-310-aarch64-linux-gnu.so +0 -0
- sage/graphs/weakly_chordal.pyx +604 -0
- sage/groups/all__sagemath_graphs.py +1 -0
- sage/groups/perm_gps/all__sagemath_graphs.py +1 -0
- sage/groups/perm_gps/partn_ref/all__sagemath_graphs.py +1 -0
- sage/groups/perm_gps/partn_ref/refinement_graphs.cpython-310-aarch64-linux-gnu.so +0 -0
- sage/groups/perm_gps/partn_ref/refinement_graphs.pxd +38 -0
- sage/groups/perm_gps/partn_ref/refinement_graphs.pyx +1666 -0
- sage/knots/all.py +6 -0
- sage/knots/free_knotinfo_monoid.py +507 -0
- sage/knots/gauss_code.py +291 -0
- sage/knots/knot.py +682 -0
- sage/knots/knot_table.py +284 -0
- sage/knots/knotinfo.py +2900 -0
- sage/knots/link.py +4715 -0
- sage/sandpiles/all.py +13 -0
- sage/sandpiles/examples.py +225 -0
- sage/sandpiles/sandpile.py +6365 -0
- sage/topology/all.py +22 -0
- sage/topology/cell_complex.py +1214 -0
- sage/topology/cubical_complex.py +1976 -0
- sage/topology/delta_complex.py +1806 -0
- sage/topology/filtered_simplicial_complex.py +744 -0
- sage/topology/moment_angle_complex.py +823 -0
- sage/topology/simplicial_complex.py +5160 -0
- sage/topology/simplicial_complex_catalog.py +92 -0
- sage/topology/simplicial_complex_examples.py +1680 -0
- sage/topology/simplicial_complex_homset.py +205 -0
- sage/topology/simplicial_complex_morphism.py +836 -0
- sage/topology/simplicial_set.py +4102 -0
- sage/topology/simplicial_set_catalog.py +55 -0
- sage/topology/simplicial_set_constructions.py +2954 -0
- sage/topology/simplicial_set_examples.py +865 -0
- sage/topology/simplicial_set_morphism.py +1464 -0
sage/knots/all.py
ADDED
@@ -0,0 +1,507 @@
|
|
1
|
+
# sage_setup: distribution = sagemath-graphs
|
2
|
+
r"""
|
3
|
+
Free monoid generated by prime knots available via the
|
4
|
+
:class:`~sage.knots.knotinfo.KnotInfoBase` class.
|
5
|
+
|
6
|
+
A generator of this free abelian monoid is a prime knot according to
|
7
|
+
the list at `KnotInfo <https://knotinfo.math.indiana.edu/>`__. A fully
|
8
|
+
amphicheiral prime knot is represented by exactly one generator with
|
9
|
+
the corresponding name. For non-chiral prime knots, there are
|
10
|
+
additionally one or three generators with the suffixes ``m``, ``r``
|
11
|
+
and ``c`` which specify the mirror and reverse images according to
|
12
|
+
their symmetry type.
|
13
|
+
|
14
|
+
AUTHORS:
|
15
|
+
|
16
|
+
- Sebastian Oehms June 2024: initial version
|
17
|
+
"""
|
18
|
+
|
19
|
+
# ############################################################################
|
20
|
+
# Copyright (C) 2024 Sebastian Oehms <seb.oehms@gmail.com>
|
21
|
+
#
|
22
|
+
# This program is free software: you can redistribute it and/or modify
|
23
|
+
# it under the terms of the GNU General Public License as published by
|
24
|
+
# the Free Software Foundation, either version 2 of the License, or
|
25
|
+
# (at your option) any later version.
|
26
|
+
# https://www.gnu.org/licenses/
|
27
|
+
# ############################################################################
|
28
|
+
|
29
|
+
from sage.knots.knotinfo import SymmetryMutant
|
30
|
+
from sage.monoids.indexed_free_monoid import (IndexedFreeAbelianMonoid,
|
31
|
+
IndexedFreeAbelianMonoidElement)
|
32
|
+
from sage.misc.cachefunc import cached_method
|
33
|
+
from sage.structure.unique_representation import UniqueRepresentation
|
34
|
+
|
35
|
+
|
36
|
+
class FreeKnotInfoMonoidElement(IndexedFreeAbelianMonoidElement):
|
37
|
+
"""
|
38
|
+
An element of an indexed free abelian monoid.
|
39
|
+
"""
|
40
|
+
def as_knot(self):
|
41
|
+
r"""
|
42
|
+
Return the knot represented by ``self``.
|
43
|
+
|
44
|
+
EXAMPLES::
|
45
|
+
|
46
|
+
sage: from sage.knots.free_knotinfo_monoid import FreeKnotInfoMonoid
|
47
|
+
sage: FKIM = FreeKnotInfoMonoid()
|
48
|
+
sage: FKIM.inject_variables(select=3)
|
49
|
+
Defining K3_1
|
50
|
+
Defining K3_1m
|
51
|
+
sage: K = K3_1^2 * K3_1m
|
52
|
+
sage: K.as_knot()
|
53
|
+
Knot represented by 9 crossings
|
54
|
+
"""
|
55
|
+
wl = self.to_word_list()
|
56
|
+
P = self.parent()
|
57
|
+
if len(wl) == 1:
|
58
|
+
name = wl[0]
|
59
|
+
L = P._index_dict[name][0].link()
|
60
|
+
if name.endswith(SymmetryMutant.mirror_image.value):
|
61
|
+
return L.mirror_image()
|
62
|
+
if name.endswith(SymmetryMutant.reverse.value):
|
63
|
+
return L.reverse()
|
64
|
+
if name.endswith(SymmetryMutant.concordance_inverse.value):
|
65
|
+
return L.mirror_image().reverse()
|
66
|
+
return L
|
67
|
+
else:
|
68
|
+
from sage.misc.misc_c import prod
|
69
|
+
return prod(P.gen(wl[i]).as_knot() for i in range(len(wl)))
|
70
|
+
|
71
|
+
def to_knotinfo(self):
|
72
|
+
r"""
|
73
|
+
Return a word representing ``self`` as a list of pairs.
|
74
|
+
|
75
|
+
Each pair ``(ki, sym)`` consists of a
|
76
|
+
:class:`~sage.knots.knotinfo.KnotInfoBase` instance ``ki`` and
|
77
|
+
:class:`~sage.knots.knotinfo.SymmetryMutant` instance ``sym``.
|
78
|
+
|
79
|
+
EXAMPLES::
|
80
|
+
|
81
|
+
sage: from sage.knots.free_knotinfo_monoid import FreeKnotInfoMonoid
|
82
|
+
sage: FKIM = FreeKnotInfoMonoid()
|
83
|
+
sage: FKIM.inject_variables(select=3)
|
84
|
+
Defining K3_1
|
85
|
+
Defining K3_1m
|
86
|
+
sage: K = K3_1^2 * K3_1m
|
87
|
+
sage: K.to_knotinfo()
|
88
|
+
[(<KnotInfo.K3_1: '3_1'>, <SymmetryMutant.itself: 's'>),
|
89
|
+
(<KnotInfo.K3_1: '3_1'>, <SymmetryMutant.itself: 's'>),
|
90
|
+
(<KnotInfo.K3_1: '3_1'>, <SymmetryMutant.mirror_image: 'm'>)]
|
91
|
+
"""
|
92
|
+
wl = self.to_word_list()
|
93
|
+
P = self.parent()
|
94
|
+
return [P._index_dict[w] for w in wl]
|
95
|
+
|
96
|
+
|
97
|
+
class FreeKnotInfoMonoid(IndexedFreeAbelianMonoid):
|
98
|
+
|
99
|
+
Element = FreeKnotInfoMonoidElement
|
100
|
+
|
101
|
+
@staticmethod
|
102
|
+
def __classcall_private__(cls, max_crossing_number=6, prefix=None, **kwds):
|
103
|
+
r"""
|
104
|
+
Normalize input to ensure a unique representation.
|
105
|
+
|
106
|
+
EXAMPLES::
|
107
|
+
|
108
|
+
sage: from sage.knots.free_knotinfo_monoid import FreeKnotInfoMonoid
|
109
|
+
sage: FreeKnotInfoMonoid()
|
110
|
+
Free abelian monoid of knots with at most 6 crossings
|
111
|
+
sage: FreeKnotInfoMonoid(5)
|
112
|
+
Free abelian monoid of knots with at most 5 crossings
|
113
|
+
"""
|
114
|
+
if not prefix:
|
115
|
+
prefix = 'KnotInfo'
|
116
|
+
# We skip the IndexedMonoid__classcall__
|
117
|
+
return UniqueRepresentation.__classcall__(cls, max_crossing_number,
|
118
|
+
prefix=prefix, **kwds)
|
119
|
+
|
120
|
+
def __init__(self, max_crossing_number, category=None, prefix=None, **kwds):
|
121
|
+
r"""
|
122
|
+
Initialize ``self`` with generators belonging to prime knots with
|
123
|
+
at most ``max_crossing_number`` crossings.
|
124
|
+
|
125
|
+
TESTS:
|
126
|
+
|
127
|
+
sage: from sage.knots.free_knotinfo_monoid import FreeKnotInfoMonoid
|
128
|
+
sage: FKIM = FreeKnotInfoMonoid()
|
129
|
+
sage: FKIM4 = FreeKnotInfoMonoid(4)
|
130
|
+
sage: TestSuite(FKIM).run()
|
131
|
+
sage: TestSuite(FKIM4).run()
|
132
|
+
"""
|
133
|
+
self._max_crossing_number = None
|
134
|
+
self._set_index_dictionary(max_crossing_number=max_crossing_number)
|
135
|
+
from sage.sets.finite_enumerated_set import FiniteEnumeratedSet
|
136
|
+
indices = FiniteEnumeratedSet(self._index_dict)
|
137
|
+
super().__init__(indices, prefix)
|
138
|
+
|
139
|
+
def _from_knotinfo(self, knotinfo, symmetry_mutant):
|
140
|
+
r"""
|
141
|
+
Return the name on the generator for the given ``symmetry_mutant``
|
142
|
+
of the given entry ``knotinfo`` if the KnotInfo database.
|
143
|
+
|
144
|
+
EXAMPLES::
|
145
|
+
|
146
|
+
sage: from sage.knots.free_knotinfo_monoid import FreeKnotInfoMonoid
|
147
|
+
sage: from sage.knots.knotinfo import SymmetryMutant
|
148
|
+
sage: FKIM = FreeKnotInfoMonoid()
|
149
|
+
sage: ki = KnotInfo.K5_2
|
150
|
+
sage: FKIM._from_knotinfo(ki, SymmetryMutant.itself)
|
151
|
+
'K5_2'
|
152
|
+
sage: FKIM._from_knotinfo(ki, SymmetryMutant.concordance_inverse)
|
153
|
+
'K5_2c'
|
154
|
+
"""
|
155
|
+
if symmetry_mutant == SymmetryMutant.itself:
|
156
|
+
return knotinfo.name
|
157
|
+
else:
|
158
|
+
return '%s%s' % (knotinfo.name, symmetry_mutant.value)
|
159
|
+
|
160
|
+
def _set_index_dictionary(self, max_crossing_number=6):
|
161
|
+
r"""
|
162
|
+
Set or expand the set of generators.
|
163
|
+
EXAMPLES::
|
164
|
+
|
165
|
+
sage: from sage.knots.free_knotinfo_monoid import FreeKnotInfoMonoid
|
166
|
+
sage: FreeKnotInfoMonoid()
|
167
|
+
Free abelian monoid of knots with at most 6 crossings
|
168
|
+
|
169
|
+
TESTS::
|
170
|
+
|
171
|
+
sage: from sage.features.databases import DatabaseKnotInfo
|
172
|
+
sage: F = DatabaseKnotInfo()
|
173
|
+
sage: F.hide()
|
174
|
+
sage: FreeKnotInfoMonoid(7) # indirect doctest
|
175
|
+
Traceback (most recent call last):
|
176
|
+
...
|
177
|
+
sage.features.FeatureNotPresentError: database_knotinfo is not available.
|
178
|
+
Feature `database_knotinfo` is hidden.
|
179
|
+
Use method `unhide` to make it available again.
|
180
|
+
sage: F.unhide()
|
181
|
+
"""
|
182
|
+
if max_crossing_number > 6:
|
183
|
+
from sage.features.databases import DatabaseKnotInfo
|
184
|
+
DatabaseKnotInfo().require()
|
185
|
+
|
186
|
+
current_max_crossing_number = self._max_crossing_number
|
187
|
+
if not current_max_crossing_number:
|
188
|
+
current_max_crossing_number = - 1
|
189
|
+
self._index_dict = {}
|
190
|
+
self._max_crossing_number = max_crossing_number
|
191
|
+
|
192
|
+
def add_index(ki, sym):
|
193
|
+
self._index_dict[self._from_knotinfo(ki, sym)] = (ki, sym)
|
194
|
+
|
195
|
+
from sage.knots.knotinfo import KnotInfo
|
196
|
+
for K in KnotInfo:
|
197
|
+
ncr = K.crossing_number()
|
198
|
+
if ncr <= current_max_crossing_number:
|
199
|
+
continue
|
200
|
+
if ncr > self._max_crossing_number:
|
201
|
+
break
|
202
|
+
for sym in SymmetryMutant:
|
203
|
+
if sym.is_minimal(K):
|
204
|
+
add_index(K, sym)
|
205
|
+
if current_max_crossing_number > 0:
|
206
|
+
from sage.sets.finite_enumerated_set import FiniteEnumeratedSet
|
207
|
+
self._indices = FiniteEnumeratedSet(self._index_dict)
|
208
|
+
|
209
|
+
def _repr_(self):
|
210
|
+
"""
|
211
|
+
Return a string representation of ``self``.
|
212
|
+
|
213
|
+
EXAMPLES::
|
214
|
+
|
215
|
+
sage: from sage.knots.free_knotinfo_monoid import FreeKnotInfoMonoid
|
216
|
+
sage: FreeKnotInfoMonoid(4)
|
217
|
+
Free abelian monoid of knots with at most 4 crossings
|
218
|
+
"""
|
219
|
+
return "Free abelian monoid of knots with at most %s crossings" % self._max_crossing_number
|
220
|
+
|
221
|
+
def _element_constructor_(self, x=None):
|
222
|
+
"""
|
223
|
+
Create an element of this abelian monoid from ``x``.
|
224
|
+
|
225
|
+
EXAMPLES::
|
226
|
+
|
227
|
+
sage: from sage.knots.free_knotinfo_monoid import FreeKnotInfoMonoid
|
228
|
+
sage: FKIM = FreeKnotInfoMonoid()
|
229
|
+
sage: K = KnotInfo.K5_1.link().mirror_image()
|
230
|
+
sage: FKIM(K) # needs libhomfly sage.modules
|
231
|
+
KnotInfo['K5_1m']
|
232
|
+
"""
|
233
|
+
if isinstance(x, tuple):
|
234
|
+
if len(x) == 2:
|
235
|
+
ki, sym = x
|
236
|
+
from sage.knots.knotinfo import KnotInfoBase
|
237
|
+
if isinstance(ki, KnotInfoBase) and isinstance(sym, SymmetryMutant):
|
238
|
+
mcr = ki.crossing_number()
|
239
|
+
if mcr > self._max_crossing_number:
|
240
|
+
self._set_index_dictionary(max_crossing_number=mcr)
|
241
|
+
|
242
|
+
sym_min = min([sym] + sym.matches(ki))
|
243
|
+
return self.gen(self._from_knotinfo(ki, sym_min))
|
244
|
+
|
245
|
+
from sage.knots.knot import Knot
|
246
|
+
from sage.knots.link import Link
|
247
|
+
if not isinstance(x, Knot):
|
248
|
+
if isinstance(x, Link):
|
249
|
+
x = Knot(x.pd_code())
|
250
|
+
if isinstance(x, Knot):
|
251
|
+
return self.from_knot(x)
|
252
|
+
return self.element_class(self, x)
|
253
|
+
|
254
|
+
@cached_method
|
255
|
+
def _check_elements(self, knot, elems):
|
256
|
+
r"""
|
257
|
+
Return a matching item from the list in ``elems`` if it exists.
|
258
|
+
Elsewise return ``None``. This is a helper method for .meth:`from_knot`.
|
259
|
+
|
260
|
+
INPUT:
|
261
|
+
|
262
|
+
- ``knot`` -- an instance of :class:`~sage.knots.knot.Knot`
|
263
|
+
- ``elems`` -- a tuple of elements of ``self``
|
264
|
+
|
265
|
+
EXAMPLES::
|
266
|
+
|
267
|
+
sage: # needs sage.groups
|
268
|
+
sage: from sage.knots.free_knotinfo_monoid import FreeKnotInfoMonoid
|
269
|
+
sage: FKIM = FreeKnotInfoMonoid()
|
270
|
+
sage: FKIM.inject_variables(select=3)
|
271
|
+
Defining K3_1
|
272
|
+
Defining K3_1m
|
273
|
+
sage: elems = (K3_1, K3_1m)
|
274
|
+
sage: K = Knots().from_table(3, 1)
|
275
|
+
sage: FKIM._check_elements(K, elems)
|
276
|
+
KnotInfo['K3_1m']
|
277
|
+
sage: K = Knots().from_table(4, 1)
|
278
|
+
sage: FKIM._check_elements(K, elems) is None
|
279
|
+
True
|
280
|
+
"""
|
281
|
+
for e in elems:
|
282
|
+
k = e.as_knot()
|
283
|
+
if knot.pd_code() == k.pd_code():
|
284
|
+
return e
|
285
|
+
if knot._markov_move_cmp(k.braid()):
|
286
|
+
return e
|
287
|
+
return None
|
288
|
+
|
289
|
+
@cached_method
|
290
|
+
def _search_composition(self, max_cr, knot, hpoly):
|
291
|
+
r"""
|
292
|
+
Add KnotInfo items to the list of candidates that have
|
293
|
+
matching Homfly polynomial.
|
294
|
+
|
295
|
+
INPUT:
|
296
|
+
|
297
|
+
- ``max_cr`` -- max number of crossing to stop searching
|
298
|
+
- ``knot`` -- instance of :class:`~sage.knots.knot.Knot`
|
299
|
+
- ``hpoly`` -- Homfly polynomial to search for a component
|
300
|
+
|
301
|
+
OUTPUT:
|
302
|
+
|
303
|
+
A tuple of elements of ``self`` that match a (not necessarily prime or
|
304
|
+
proper) component of the given knot having the given Homfly polynomial.
|
305
|
+
|
306
|
+
EXAMPLES::
|
307
|
+
|
308
|
+
sage: from sage.knots.free_knotinfo_monoid import FreeKnotInfoMonoid
|
309
|
+
sage: FKIM = FreeKnotInfoMonoid()
|
310
|
+
sage: FKIM.inject_variables(select=3)
|
311
|
+
Defining K3_1
|
312
|
+
Defining K3_1m
|
313
|
+
sage: KI = K3_1 * K3_1m
|
314
|
+
sage: K = KI.as_knot()
|
315
|
+
sage: h = K3_1.to_knotinfo()[0][0].homfly_polynomial() # needs libhomfly sage.modules
|
316
|
+
sage: FKIM._search_composition(3, K, h) # needs libhomfly sage.modules
|
317
|
+
(KnotInfo['K3_1'],)
|
318
|
+
"""
|
319
|
+
from sage.knots.knotinfo import KnotInfo
|
320
|
+
|
321
|
+
def hp_mirr(hp):
|
322
|
+
v, z = hp.parent().gens()
|
323
|
+
return hp.subs({v: ~v, z: z})
|
324
|
+
|
325
|
+
former_cr = 3
|
326
|
+
res = []
|
327
|
+
for K in KnotInfo:
|
328
|
+
if not K.is_knot():
|
329
|
+
break
|
330
|
+
c = K.crossing_number()
|
331
|
+
if c < 3:
|
332
|
+
continue
|
333
|
+
if c > max_cr:
|
334
|
+
break
|
335
|
+
hp = K.homfly_polynomial()
|
336
|
+
hp_sym = {s: hp for s in SymmetryMutant if s.is_minimal(K)}
|
337
|
+
hpm = hp_mirr(hp)
|
338
|
+
if hp != hpm:
|
339
|
+
hp_sym[SymmetryMutant.mirror_image] = hpm
|
340
|
+
if SymmetryMutant.concordance_inverse in hp_sym.keys():
|
341
|
+
hp_sym[SymmetryMutant.concordance_inverse] = hpm
|
342
|
+
|
343
|
+
for sym_mut, hps in hp_sym.items():
|
344
|
+
if hps.divides(hpoly):
|
345
|
+
Kgen = self((K, sym_mut))
|
346
|
+
h = hpoly // hps
|
347
|
+
if h.is_unit():
|
348
|
+
res += [Kgen]
|
349
|
+
else:
|
350
|
+
res_rec = self._search_composition(max_cr - c, knot, h)
|
351
|
+
if res_rec:
|
352
|
+
res += [Kgen * k for k in res_rec]
|
353
|
+
if c > former_cr and res:
|
354
|
+
k = self._check_elements(knot, tuple(res))
|
355
|
+
if k:
|
356
|
+
# matching item found
|
357
|
+
return tuple([k])
|
358
|
+
former_cr = c
|
359
|
+
|
360
|
+
return tuple(sorted(set(res)))
|
361
|
+
|
362
|
+
@cached_method
|
363
|
+
def _from_knot(self, knot):
|
364
|
+
"""
|
365
|
+
Create a tuple of element of this abelian monoid which possibly
|
366
|
+
represent ``knot``. This method caches the performance relevant
|
367
|
+
part of :meth:`from_knot`.
|
368
|
+
|
369
|
+
INPUT:
|
370
|
+
|
371
|
+
- ``knot`` -- an instance of :class:`~sage.knots.knot.Knot`
|
372
|
+
|
373
|
+
EXAMPLES::
|
374
|
+
|
375
|
+
sage: from sage.knots.free_knotinfo_monoid import FreeKnotInfoMonoid
|
376
|
+
sage: FKIM = FreeKnotInfoMonoid()
|
377
|
+
sage: K = KnotInfo.K5_1.link().mirror_image()
|
378
|
+
sage: FKIM._from_knot(K) # needs sage.groups sage.modules
|
379
|
+
(KnotInfo['K5_1m'],)
|
380
|
+
"""
|
381
|
+
hp = knot.homfly_polynomial(normalization='vz')
|
382
|
+
return self._search_composition(13, knot, hp)
|
383
|
+
|
384
|
+
def from_knot(self, knot, unique=True):
|
385
|
+
"""
|
386
|
+
Create an element of this abelian monoid from ``knot``.
|
387
|
+
|
388
|
+
INPUT:
|
389
|
+
|
390
|
+
- ``knot`` -- an instance of :class:`~sage.knots.knot.Knot`
|
391
|
+
|
392
|
+
- ``unique`` -- boolean (default is ``True``). This only affects the case
|
393
|
+
where a unique identification is not possible. If set to ``False`` you
|
394
|
+
can obtain a matching list (see explanation of the output below)
|
395
|
+
|
396
|
+
OUTPUT:
|
397
|
+
|
398
|
+
An instance of the element class of ``self`` per default. If the keyword
|
399
|
+
argument ``unique`` then a list of such instances is returned.
|
400
|
+
|
401
|
+
EXAMPLES::
|
402
|
+
|
403
|
+
sage: from sage.knots.free_knotinfo_monoid import FreeKnotInfoMonoid
|
404
|
+
sage: FKIM = FreeKnotInfoMonoid()
|
405
|
+
sage: K = KnotInfo.K5_1.link().mirror_image()
|
406
|
+
sage: FKIM.from_knot(K) # needs libhomfly sage.modules
|
407
|
+
KnotInfo['K5_1m']
|
408
|
+
|
409
|
+
sage: # optional - database_knotinfo
|
410
|
+
sage: K = Knot(KnotInfo.K9_12.braid())
|
411
|
+
sage: FKIM.from_knot(K) # long time # optional - database_knotinfo
|
412
|
+
Traceback (most recent call last):
|
413
|
+
...
|
414
|
+
NotImplementedError: this (possibly non prime) knot cannot be
|
415
|
+
identified uniquely by KnotInfo
|
416
|
+
use keyword argument `unique` to obtain more details
|
417
|
+
sage: FKIM.from_knot(K, unique=False) # long time # optional - database_knotinfo
|
418
|
+
[KnotInfo['K4_1']*KnotInfo['K5_2'], KnotInfo['K9_12']]
|
419
|
+
"""
|
420
|
+
hp = knot.homfly_polynomial(normalization='vz')
|
421
|
+
num_summands = sum(e for _, e in hp.factor())
|
422
|
+
if num_summands == 1:
|
423
|
+
return knot.get_knotinfo()
|
424
|
+
|
425
|
+
res = self._from_knot(knot)
|
426
|
+
if res:
|
427
|
+
if len(res) == 1:
|
428
|
+
if unique:
|
429
|
+
return res[0]
|
430
|
+
return [res[0]] # to be consistent with get_knotinfo
|
431
|
+
k = self._check_elements(knot, res)
|
432
|
+
if k:
|
433
|
+
if unique:
|
434
|
+
return k
|
435
|
+
return [k] # to be consistent with get_knotinfo
|
436
|
+
|
437
|
+
if res and not unique:
|
438
|
+
return sorted(set(res))
|
439
|
+
if unique and len(res) > 1:
|
440
|
+
non_unique_hint = '\nuse keyword argument `unique` to obtain more details'
|
441
|
+
raise NotImplementedError('this (possibly non prime) knot cannot be identified uniquely by KnotInfo%s' % non_unique_hint)
|
442
|
+
raise NotImplementedError('this (possibly non prime) knot cannot be identified by KnotInfo')
|
443
|
+
|
444
|
+
def inject_variables(self, select=None, verbose=True):
|
445
|
+
"""
|
446
|
+
Inject ``self`` with its name into the namespace of the
|
447
|
+
Python code from which this function is called.
|
448
|
+
|
449
|
+
INPUT:
|
450
|
+
|
451
|
+
- ``select`` -- instance of :class:`~sage.knots.knotinfo.KnotInfoBase`,
|
452
|
+
:class:`~sage.knots.knotinfo.KnotInfoSeries` or an integer. In all
|
453
|
+
cases the input is used to restrict the injected generators to the
|
454
|
+
according subset (number of crossings in the case of integer)
|
455
|
+
- ``verbose`` -- boolean (optional, default ``True``) to suppress
|
456
|
+
the message printed on the invocation
|
457
|
+
|
458
|
+
EXAMPLES::
|
459
|
+
|
460
|
+
sage: from sage.knots.free_knotinfo_monoid import FreeKnotInfoMonoid
|
461
|
+
sage: FKIM = FreeKnotInfoMonoid(5)
|
462
|
+
sage: FKIM.inject_variables(select=3)
|
463
|
+
Defining K3_1
|
464
|
+
Defining K3_1m
|
465
|
+
sage: FKIM.inject_variables(select=KnotInfo.K5_2)
|
466
|
+
Defining K5_2
|
467
|
+
Defining K5_2m
|
468
|
+
sage: FKIM.inject_variables(select=KnotInfo.K5_2.series())
|
469
|
+
Defining K5_1
|
470
|
+
Defining K5_1m
|
471
|
+
sage: FKIM.inject_variables()
|
472
|
+
Defining K0_1
|
473
|
+
Defining K4_1
|
474
|
+
"""
|
475
|
+
from sage.knots.knotinfo import KnotInfoBase, KnotInfoSeries
|
476
|
+
from sage.rings.integer import Integer
|
477
|
+
gen_list = []
|
478
|
+
idx_dict = self._index_dict
|
479
|
+
max_crn = self._max_crossing_number
|
480
|
+
gens = self.gens()
|
481
|
+
if select:
|
482
|
+
if isinstance(select, KnotInfoBase):
|
483
|
+
crn = select.crossing_number()
|
484
|
+
if crn > max_crn:
|
485
|
+
self._set_index_dictionary(max_crossing_number=crn)
|
486
|
+
gen_list += [k for k, v in idx_dict.items() if v[0] == select]
|
487
|
+
elif isinstance(select, KnotInfoSeries):
|
488
|
+
for v in select:
|
489
|
+
self.inject_variables(select=v)
|
490
|
+
return
|
491
|
+
elif type(select) is int or isinstance(select, Integer):
|
492
|
+
crn = select
|
493
|
+
if crn > max_crn:
|
494
|
+
self._set_index_dictionary(max_crossing_number=crn)
|
495
|
+
gen_list += [k for k, v in idx_dict.items()
|
496
|
+
if v[0].crossing_number() == crn]
|
497
|
+
else:
|
498
|
+
raise TypeError('cannot select generators by %s' % select)
|
499
|
+
else:
|
500
|
+
gen_list = list(idx_dict.keys())
|
501
|
+
|
502
|
+
from sage.repl.user_globals import set_global, get_globals
|
503
|
+
for name in gen_list:
|
504
|
+
if name not in get_globals().keys():
|
505
|
+
set_global(name, gens[name])
|
506
|
+
if verbose:
|
507
|
+
print("Defining %s" % (name))
|