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
@@ -0,0 +1,565 @@
|
|
1
|
+
# sage_setup: distribution = sagemath-graphs
|
2
|
+
r"""
|
3
|
+
Intersection graphs
|
4
|
+
|
5
|
+
The methods defined here appear in :mod:`sage.graphs.graph_generators`.
|
6
|
+
"""
|
7
|
+
|
8
|
+
# ****************************************************************************
|
9
|
+
# Copyright (C) 2006 Robert L. Miller <rlmillster@gmail.com>
|
10
|
+
# Copyright (C) 2006 Emily A. Kirkman
|
11
|
+
# Copyright (C) 2009 Michael C. Yurko <myurko@gmail.com>
|
12
|
+
#
|
13
|
+
# This program is free software: you can redistribute it and/or modify
|
14
|
+
# it under the terms of the GNU General Public License as published by
|
15
|
+
# the Free Software Foundation, either version 2 of the License, or
|
16
|
+
# (at your option) any later version.
|
17
|
+
# https://www.gnu.org/licenses/
|
18
|
+
# ****************************************************************************
|
19
|
+
|
20
|
+
# import from Sage library
|
21
|
+
from sage.graphs.graph import Graph
|
22
|
+
|
23
|
+
|
24
|
+
def IntervalGraph(intervals, points_ordered=False):
|
25
|
+
r"""
|
26
|
+
Return the graph corresponding to the given intervals.
|
27
|
+
|
28
|
+
An interval graph is built from a list `(a_i,b_i)_{1\leq i \leq n}` of
|
29
|
+
intervals : to each interval of the list is associated one vertex, two
|
30
|
+
vertices being adjacent if the two corresponding (closed) intervals
|
31
|
+
intersect.
|
32
|
+
|
33
|
+
INPUT:
|
34
|
+
|
35
|
+
- ``intervals`` -- the list of pairs `(a_i,b_i)` defining the graph
|
36
|
+
|
37
|
+
- ``points_ordered`` -- states whether every interval `(a_i,b_i)` of
|
38
|
+
`intervals` satisfies `a_i<b_i`. If satisfied then setting
|
39
|
+
``points_ordered`` to ``True`` will speed up the creation of the graph.
|
40
|
+
|
41
|
+
.. NOTE::
|
42
|
+
|
43
|
+
* The vertices are named 0, 1, 2, and so on. The intervals used
|
44
|
+
to create the graph are saved with the graph and can be recovered
|
45
|
+
using ``get_vertex()`` or ``get_vertices()``.
|
46
|
+
|
47
|
+
EXAMPLES:
|
48
|
+
|
49
|
+
The following line creates the sequence of intervals
|
50
|
+
`(i, i+2)` for i in `[0, ..., 8]`::
|
51
|
+
|
52
|
+
sage: intervals = [(i,i+2) for i in range(9)]
|
53
|
+
|
54
|
+
In the corresponding graph ::
|
55
|
+
|
56
|
+
sage: g = graphs.IntervalGraph(intervals)
|
57
|
+
sage: g.get_vertex(3)
|
58
|
+
(3, 5)
|
59
|
+
sage: neigh = g.neighbors(3)
|
60
|
+
sage: for v in neigh: print(g.get_vertex(v))
|
61
|
+
(1, 3)
|
62
|
+
(2, 4)
|
63
|
+
(4, 6)
|
64
|
+
(5, 7)
|
65
|
+
|
66
|
+
The is_interval() method verifies that this graph is an interval graph. ::
|
67
|
+
|
68
|
+
sage: g.is_interval()
|
69
|
+
True
|
70
|
+
|
71
|
+
The intervals in the list need not be distinct. ::
|
72
|
+
|
73
|
+
sage: intervals = [ (1,2), (1,2), (1,2), (2,3), (3,4) ]
|
74
|
+
sage: g = graphs.IntervalGraph(intervals,True)
|
75
|
+
sage: g.clique_maximum() # needs cliquer
|
76
|
+
[0, 1, 2, 3]
|
77
|
+
sage: g.get_vertices()
|
78
|
+
{0: (1, 2), 1: (1, 2), 2: (1, 2), 3: (2, 3), 4: (3, 4)}
|
79
|
+
|
80
|
+
The endpoints of the intervals are not ordered we get the same graph
|
81
|
+
(except for the vertex labels). ::
|
82
|
+
|
83
|
+
sage: rev_intervals = [ (2,1), (2,1), (2,1), (3,2), (4,3) ]
|
84
|
+
sage: h = graphs.IntervalGraph(rev_intervals,False)
|
85
|
+
sage: h.get_vertices()
|
86
|
+
{0: (2, 1), 1: (2, 1), 2: (2, 1), 3: (3, 2), 4: (4, 3)}
|
87
|
+
sage: g.edges(sort=True) == h.edges(sort=True)
|
88
|
+
True
|
89
|
+
"""
|
90
|
+
intervals = list(intervals)
|
91
|
+
n = len(intervals)
|
92
|
+
g = Graph(n)
|
93
|
+
|
94
|
+
if points_ordered:
|
95
|
+
for i in range(n - 1):
|
96
|
+
li, ri = intervals[i]
|
97
|
+
for j in range(i + 1, n):
|
98
|
+
lj, rj = intervals[j]
|
99
|
+
if ri < lj or rj < li:
|
100
|
+
continue
|
101
|
+
g.add_edge(i, j)
|
102
|
+
else:
|
103
|
+
for i in range(n - 1):
|
104
|
+
min_I = min(intervals[i])
|
105
|
+
max_I = max(intervals[i])
|
106
|
+
for j in range(i + 1, n):
|
107
|
+
J = intervals[j]
|
108
|
+
if max_I < min(J) or max(J) < min_I:
|
109
|
+
continue
|
110
|
+
g.add_edge(i, j)
|
111
|
+
|
112
|
+
rep = dict(zip(range(n), intervals))
|
113
|
+
g.set_vertices(rep)
|
114
|
+
|
115
|
+
return g
|
116
|
+
|
117
|
+
|
118
|
+
def PermutationGraph(second_permutation, first_permutation=None):
|
119
|
+
r"""
|
120
|
+
Build a permutation graph from one permutation or from two lists.
|
121
|
+
|
122
|
+
Definition:
|
123
|
+
|
124
|
+
If `\sigma` is a permutation of `\{ 1, 2, \ldots, n \}`, then the
|
125
|
+
permutation graph of `\sigma` is the graph on vertex set
|
126
|
+
`\{ 1, 2, \ldots, n \}` in which two vertices `i` and `j` satisfying
|
127
|
+
`i < j` are connected by an edge if and only if
|
128
|
+
`\sigma^{-1}(i) > \sigma^{-1}(j)`. A visual way to construct this
|
129
|
+
graph is as follows:
|
130
|
+
|
131
|
+
Take two horizontal lines in the euclidean plane, and mark points
|
132
|
+
`1, ..., n` from left to right on the first of them. On the second
|
133
|
+
one, still from left to right, mark `n` points
|
134
|
+
`\sigma(1), \sigma(2), \ldots, \sigma(n)`.
|
135
|
+
Now, link by a segment the two points marked with `1`, then link
|
136
|
+
together the points marked with `2`, and so on. The permutation
|
137
|
+
graph of `\sigma` is the intersection graph of those segments: there
|
138
|
+
exists a vertex in this graph for each element from `1` to `n`, two
|
139
|
+
vertices `i, j` being adjacent if the segments `i` and `j` cross
|
140
|
+
each other.
|
141
|
+
|
142
|
+
The set of edges of the permutation graph can thus be identified with
|
143
|
+
the set of inversions of the inverse of the given permutation
|
144
|
+
`\sigma`.
|
145
|
+
|
146
|
+
A more general notion of permutation graph can be defined as
|
147
|
+
follows: If `S` is a set, and `(a_1, a_2, \ldots, a_n)` and
|
148
|
+
`(b_1, b_2, \ldots, b_n)` are two lists of elements of `S`, each of
|
149
|
+
which lists contains every element of `S` exactly once, then the
|
150
|
+
permutation graph defined by these two lists is the graph on the
|
151
|
+
vertex set `S` in which two vertices `i` and `j` are connected by an
|
152
|
+
edge if and only if the order in which these vertices appear in the
|
153
|
+
list `(a_1, a_2, \ldots, a_n)` is the opposite of the order in which
|
154
|
+
they appear in the list `(b_1, b_2, \ldots, b_n)`. When
|
155
|
+
`(a_1, a_2, \ldots, a_n) = (1, 2, \ldots, n)`, this graph is the
|
156
|
+
permutation graph of the permutation
|
157
|
+
`(b_1, b_2, \ldots, b_n) \in S_n`. Notice that `S` does not have to
|
158
|
+
be a set of integers here, but can be a set of strings, tuples, or
|
159
|
+
anything else. We can still use the above visual description to
|
160
|
+
construct the permutation graph, but now we have to mark points
|
161
|
+
`a_1, a_2, \ldots, a_n` from left to right on the first horizontal
|
162
|
+
line and points `b_1, b_2, \ldots, b_n` from left to right on the
|
163
|
+
second horizontal line.
|
164
|
+
|
165
|
+
INPUT:
|
166
|
+
|
167
|
+
- ``second_permutation`` -- the unique permutation/list defining the graph,
|
168
|
+
or the second of the two (if the graph is to be built from two
|
169
|
+
permutations/lists)
|
170
|
+
|
171
|
+
- ``first_permutation`` -- (optional) the first of the two
|
172
|
+
permutations/lists from which the graph should be built, if it is to be
|
173
|
+
built from two permutations/lists
|
174
|
+
|
175
|
+
When ``first_permutation is None`` (default), it is set to be equal to
|
176
|
+
``sorted(second_permutation)``, which yields the expected ordering when
|
177
|
+
the elements of the graph are integers.
|
178
|
+
|
179
|
+
.. SEEALSO::
|
180
|
+
|
181
|
+
- Recognition of Permutation graphs in the :mod:`comparability module
|
182
|
+
<sage.graphs.comparability>`.
|
183
|
+
|
184
|
+
- Drawings of permutation graphs as intersection graphs of segments is
|
185
|
+
possible through the
|
186
|
+
:meth:`~sage.combinat.permutation.Permutation.show` method of
|
187
|
+
:class:`~sage.combinat.permutation.Permutation` objects.
|
188
|
+
|
189
|
+
The correct argument to use in this case is ``show(representation =
|
190
|
+
"braid")``.
|
191
|
+
|
192
|
+
- :meth:`~sage.combinat.permutation.Permutation.inversions`
|
193
|
+
|
194
|
+
EXAMPLES::
|
195
|
+
|
196
|
+
sage: p = Permutations(5).random_element()
|
197
|
+
sage: PG = graphs.PermutationGraph(p)
|
198
|
+
sage: edges = PG.edges(sort=True, labels=False)
|
199
|
+
sage: set(edges) == set(p.inverse().inversions())
|
200
|
+
True
|
201
|
+
|
202
|
+
sage: PG = graphs.PermutationGraph([3,4,5,1,2])
|
203
|
+
sage: sorted(PG.edges(sort=True))
|
204
|
+
[(1, 3, None),
|
205
|
+
(1, 4, None),
|
206
|
+
(1, 5, None),
|
207
|
+
(2, 3, None),
|
208
|
+
(2, 4, None),
|
209
|
+
(2, 5, None)]
|
210
|
+
sage: PG = graphs.PermutationGraph([3,4,5,1,2], [1,4,2,5,3])
|
211
|
+
sage: sorted(PG.edges(sort=True))
|
212
|
+
[(1, 3, None),
|
213
|
+
(1, 4, None),
|
214
|
+
(1, 5, None),
|
215
|
+
(2, 3, None),
|
216
|
+
(2, 5, None),
|
217
|
+
(3, 4, None),
|
218
|
+
(3, 5, None)]
|
219
|
+
sage: PG = graphs.PermutationGraph([1,4,2,5,3], [3,4,5,1,2])
|
220
|
+
sage: sorted(PG.edges(sort=True))
|
221
|
+
[(1, 3, None),
|
222
|
+
(1, 4, None),
|
223
|
+
(1, 5, None),
|
224
|
+
(2, 3, None),
|
225
|
+
(2, 5, None),
|
226
|
+
(3, 4, None),
|
227
|
+
(3, 5, None)]
|
228
|
+
|
229
|
+
sage: PG = graphs.PermutationGraph(Permutation([1,3,2]), Permutation([1,2,3]))
|
230
|
+
sage: sorted(PG.edges(sort=True))
|
231
|
+
[(2, 3, None)]
|
232
|
+
|
233
|
+
sage: graphs.PermutationGraph([]).edges(sort=True)
|
234
|
+
[]
|
235
|
+
sage: graphs.PermutationGraph([], []).edges(sort=True)
|
236
|
+
[]
|
237
|
+
|
238
|
+
sage: PG = graphs.PermutationGraph("graph", "phrag")
|
239
|
+
sage: sorted(PG.edges(sort=True))
|
240
|
+
[('a', 'g', None),
|
241
|
+
('a', 'h', None),
|
242
|
+
('a', 'p', None),
|
243
|
+
('g', 'h', None),
|
244
|
+
('g', 'p', None),
|
245
|
+
('g', 'r', None),
|
246
|
+
('h', 'r', None),
|
247
|
+
('p', 'r', None)]
|
248
|
+
|
249
|
+
TESTS::
|
250
|
+
|
251
|
+
sage: graphs.PermutationGraph([1, 2, 3], [4, 5, 6])
|
252
|
+
Traceback (most recent call last):
|
253
|
+
...
|
254
|
+
ValueError: The two permutations do not contain the same set of elements ...
|
255
|
+
"""
|
256
|
+
if first_permutation is None:
|
257
|
+
first_permutation = sorted(second_permutation)
|
258
|
+
else:
|
259
|
+
if set(second_permutation) != set(first_permutation):
|
260
|
+
raise ValueError("The two permutations do not contain the same "
|
261
|
+
"set of elements ! It is going to be pretty "
|
262
|
+
"hard to define a permutation graph from that !")
|
263
|
+
|
264
|
+
vertex_to_index = {}
|
265
|
+
for i, v in enumerate(first_permutation):
|
266
|
+
vertex_to_index[v] = i + 1
|
267
|
+
|
268
|
+
from sage.combinat.permutation import Permutation
|
269
|
+
p2 = Permutation([vertex_to_index[x] for x in second_permutation])
|
270
|
+
p2 = p2.inverse()
|
271
|
+
|
272
|
+
g = Graph(name="Permutation graph for "+str(second_permutation))
|
273
|
+
g.add_vertices(second_permutation)
|
274
|
+
|
275
|
+
for u, v in p2.inversions():
|
276
|
+
g.add_edge(first_permutation[u - 1], first_permutation[v - 1])
|
277
|
+
|
278
|
+
return g
|
279
|
+
|
280
|
+
|
281
|
+
def ToleranceGraph(tolrep):
|
282
|
+
r"""
|
283
|
+
Return the graph generated by the tolerance representation ``tolrep``.
|
284
|
+
|
285
|
+
The tolerance representation ``tolrep`` is described by the list
|
286
|
+
`((l_0,r_0,t_0), (l_1,r_1,t_1), \ldots, (l_k,r_k,t_k))` where `I_i =
|
287
|
+
(l_i,r_i)` denotes a closed interval on the real line with `l_i < r_i` and
|
288
|
+
`t_i` a strictly positive value, called tolerance. This representation
|
289
|
+
generates the tolerance graph with the vertex set `\{0,1, \ldots, k\}` and
|
290
|
+
the edge set `\{(i,j): |I_i \cap I_j| \ge \min\{t_i, t_j\}\}` where `|I_i
|
291
|
+
\cap I_j|` denotes the length of the intersection of `I_i` and `I_j`.
|
292
|
+
|
293
|
+
INPUT:
|
294
|
+
|
295
|
+
- ``tolrep`` -- list of triples `(l_i,r_i,t_i)` where `(l_i,r_i)` denotes a
|
296
|
+
closed interval on the real line and `t_i` a positive value
|
297
|
+
|
298
|
+
.. NOTE::
|
299
|
+
|
300
|
+
The vertices are named `0, 1, \ldots, k`. The tolerance representation
|
301
|
+
used to create the graph is saved with the graph and can be recovered
|
302
|
+
using ``get_vertex()`` or ``get_vertices()``.
|
303
|
+
|
304
|
+
EXAMPLES:
|
305
|
+
|
306
|
+
The following code creates a tolerance representation ``tolrep``, generates
|
307
|
+
its tolerance graph ``g``, and applies some checks::
|
308
|
+
|
309
|
+
sage: tolrep = [(1,4,3),(1,2,1),(2,3,1),(0,3,3)]
|
310
|
+
sage: g = graphs.ToleranceGraph(tolrep)
|
311
|
+
sage: g.get_vertex(3)
|
312
|
+
(0, 3, 3)
|
313
|
+
sage: neigh = g.neighbors(3)
|
314
|
+
sage: for v in neigh: print(g.get_vertex(v))
|
315
|
+
(1, 2, 1)
|
316
|
+
(2, 3, 1)
|
317
|
+
sage: g.is_interval()
|
318
|
+
False
|
319
|
+
sage: g.is_weakly_chordal()
|
320
|
+
True
|
321
|
+
|
322
|
+
The intervals in the list need not be distinct ::
|
323
|
+
|
324
|
+
sage: tolrep2 = [(0,4,5),(1,2,1),(2,3,1),(0,4,5)]
|
325
|
+
sage: g2 = graphs.ToleranceGraph(tolrep2)
|
326
|
+
sage: g2.get_vertices()
|
327
|
+
{0: (0, 4, 5), 1: (1, 2, 1), 2: (2, 3, 1), 3: (0, 4, 5)}
|
328
|
+
sage: g2.is_isomorphic(g)
|
329
|
+
True
|
330
|
+
|
331
|
+
Real values are also allowed ::
|
332
|
+
|
333
|
+
sage: tolrep = [(0.1,3.3,4.4),(1.1,2.5,1.1),(1.4,4.4,3.3)]
|
334
|
+
sage: g = graphs.ToleranceGraph(tolrep)
|
335
|
+
sage: g.is_isomorphic(graphs.PathGraph(3))
|
336
|
+
True
|
337
|
+
|
338
|
+
TESTS:
|
339
|
+
|
340
|
+
Giving negative third value::
|
341
|
+
|
342
|
+
sage: tolrep = [(0.1,3.3,-4.4),(1.1,2.5,1.1),(1.4,4.4,3.3)]
|
343
|
+
sage: g = graphs.ToleranceGraph(tolrep)
|
344
|
+
Traceback (most recent call last):
|
345
|
+
...
|
346
|
+
ValueError: Invalid tolerance representation at position 0; third value must be > 0
|
347
|
+
sage: g = graphs.ToleranceGraph([(1, 2, 0)])
|
348
|
+
Traceback (most recent call last):
|
349
|
+
...
|
350
|
+
ValueError: Invalid tolerance representation at position 0; third value must be > 0
|
351
|
+
"""
|
352
|
+
n = len(tolrep)
|
353
|
+
|
354
|
+
for i in range(n):
|
355
|
+
if tolrep[i][2] <= 0:
|
356
|
+
raise ValueError("Invalid tolerance representation at position "
|
357
|
+
"{}; third value must be > 0".format(i))
|
358
|
+
|
359
|
+
g = Graph(n, name="Tolerance Graph")
|
360
|
+
|
361
|
+
for i in range(n):
|
362
|
+
li, ri, ti = tolrep[i]
|
363
|
+
for j in range(i + 1, n):
|
364
|
+
lj, rj, tj = tolrep[j]
|
365
|
+
if min(ri, rj) - max(li, lj) >= min(ti, tj):
|
366
|
+
g.add_edge(i, j)
|
367
|
+
|
368
|
+
rep = dict(zip(range(n), tolrep))
|
369
|
+
g.set_vertices(rep)
|
370
|
+
|
371
|
+
return g
|
372
|
+
|
373
|
+
|
374
|
+
def OrthogonalArrayBlockGraph(k, n, OA=None):
|
375
|
+
r"""
|
376
|
+
Return the graph of an `OA(k,n)`.
|
377
|
+
|
378
|
+
The intersection graph of the blocks of a transversal design with parameters
|
379
|
+
`(k,n)`, or `TD(k,n)` for short, is a strongly regular graph (unless it is a
|
380
|
+
complete graph). Its parameters `(v,k',\lambda,\mu)` are determined by the
|
381
|
+
parameters `k,n` via:
|
382
|
+
|
383
|
+
.. MATH::
|
384
|
+
|
385
|
+
v=n^2, k'=k(n-1), \lambda=(k-1)(k-2)+n-2, \mu=k(k-1)
|
386
|
+
|
387
|
+
As transversal designs and orthogonal arrays (OA for short) are equivalent
|
388
|
+
objects, this graph can also be built from the blocks of an `OA(k,n)`, two
|
389
|
+
of them being adjacent if one of their coordinates match.
|
390
|
+
|
391
|
+
For more information on these graphs, see `Andries Brouwer's page
|
392
|
+
on Orthogonal Array graphs <https://www.win.tue.nl/~aeb/graphs/OA.html>`_.
|
393
|
+
|
394
|
+
.. WARNING::
|
395
|
+
|
396
|
+
- Brouwer's website uses the notation `OA(n,k)` instead of `OA(k,n)`
|
397
|
+
|
398
|
+
- For given parameters `k` and `n` there can be many `OA(k,n)` : the
|
399
|
+
graphs returned are not uniquely defined by their parameters (see the
|
400
|
+
examples below).
|
401
|
+
|
402
|
+
- If the function is called only with the parameter ``k`` and ``n`` the
|
403
|
+
results might be different with two versions of Sage, or even worse :
|
404
|
+
some could not be available anymore.
|
405
|
+
|
406
|
+
.. SEEALSO::
|
407
|
+
|
408
|
+
:mod:`sage.combinat.designs.orthogonal_arrays`
|
409
|
+
|
410
|
+
INPUT:
|
411
|
+
|
412
|
+
- ``k``, ``n`` -- integers
|
413
|
+
|
414
|
+
- ``OA`` -- an orthogonal array; if set to ``None`` (default) then
|
415
|
+
:func:`~sage.combinat.designs.orthogonal_arrays.orthogonal_array` is
|
416
|
+
called to compute an `OA(k,n)`
|
417
|
+
|
418
|
+
EXAMPLES::
|
419
|
+
|
420
|
+
sage: # needs sage.modules
|
421
|
+
sage: G = graphs.OrthogonalArrayBlockGraph(5,5); G # needs sage.schemes
|
422
|
+
OA(5,5): Graph on 25 vertices
|
423
|
+
sage: G.is_strongly_regular(parameters=True) # needs sage.schemes
|
424
|
+
(25, 20, 15, 20)
|
425
|
+
sage: G = graphs.OrthogonalArrayBlockGraph(4,10); G
|
426
|
+
OA(4,10): Graph on 100 vertices
|
427
|
+
sage: G.is_strongly_regular(parameters=True)
|
428
|
+
(100, 36, 14, 12)
|
429
|
+
|
430
|
+
Two graphs built from different orthogonal arrays are also different::
|
431
|
+
|
432
|
+
sage: # needs sage.modules
|
433
|
+
sage: k = 4; n = 10
|
434
|
+
sage: OAa = designs.orthogonal_arrays.build(k,n)
|
435
|
+
sage: OAb = [[(x+1)%n for x in R] for R in OAa]
|
436
|
+
sage: set(map(tuple,OAa)) == set(map(tuple,OAb))
|
437
|
+
False
|
438
|
+
sage: Ga = graphs.OrthogonalArrayBlockGraph(k, n, OAa)
|
439
|
+
sage: Gb = graphs.OrthogonalArrayBlockGraph(k, n, OAb)
|
440
|
+
sage: Ga == Gb
|
441
|
+
False
|
442
|
+
|
443
|
+
As ``OAb`` was obtained from ``OAa`` by a relabelling the two graphs are
|
444
|
+
isomorphic::
|
445
|
+
|
446
|
+
sage: Ga.is_isomorphic(Gb) # needs sage.modules
|
447
|
+
True
|
448
|
+
|
449
|
+
But there are examples of `OA(k,n)` for which the resulting graphs are not
|
450
|
+
isomorphic::
|
451
|
+
|
452
|
+
sage: oa0 = [[0, 0, 1], [0, 1, 3], [0, 2, 0], [0, 3, 2],
|
453
|
+
....: [1, 0, 3], [1, 1, 1], [1, 2, 2], [1, 3, 0],
|
454
|
+
....: [2, 0, 0], [2, 1, 2], [2, 2, 1], [2, 3, 3],
|
455
|
+
....: [3, 0, 2], [3, 1, 0], [3, 2, 3], [3, 3, 1]]
|
456
|
+
sage: oa1 = [[0, 0, 1], [0, 1, 0], [0, 2, 3], [0, 3, 2],
|
457
|
+
....: [1, 0, 3], [1, 1, 2], [1, 2, 0], [1, 3, 1],
|
458
|
+
....: [2, 0, 0], [2, 1, 1], [2, 2, 2], [2, 3, 3],
|
459
|
+
....: [3, 0, 2], [3, 1, 3], [3, 2, 1], [3, 3, 0]]
|
460
|
+
sage: g0 = graphs.OrthogonalArrayBlockGraph(3, 4, oa0) # needs sage.modules
|
461
|
+
sage: g1 = graphs.OrthogonalArrayBlockGraph(3, 4, oa1) # needs sage.modules
|
462
|
+
sage: g0.is_isomorphic(g1) # needs sage.modules
|
463
|
+
False
|
464
|
+
|
465
|
+
But nevertheless isospectral::
|
466
|
+
|
467
|
+
sage: g0.spectrum() # needs sage.modules sage.rings.number_field
|
468
|
+
[9, 1, 1, 1, 1, 1, 1, 1, 1, 1, -3, -3, -3, -3, -3, -3]
|
469
|
+
sage: g1.spectrum() # needs sage.modules sage.rings.number_field
|
470
|
+
[9, 1, 1, 1, 1, 1, 1, 1, 1, 1, -3, -3, -3, -3, -3, -3]
|
471
|
+
|
472
|
+
Note that the graph ``g0`` is actually isomorphic to the affine polar graph
|
473
|
+
`VO^+(4,2)`::
|
474
|
+
|
475
|
+
sage: graphs.AffineOrthogonalPolarGraph(4,2,'+').is_isomorphic(g0) # needs sage.libs.gap sage.modules
|
476
|
+
True
|
477
|
+
|
478
|
+
TESTS::
|
479
|
+
|
480
|
+
sage: G = graphs.OrthogonalArrayBlockGraph(4,6) # needs sage.modules sage.schemes
|
481
|
+
Traceback (most recent call last):
|
482
|
+
...
|
483
|
+
NotImplementedError: I don't know how to build an OA(4,6)!
|
484
|
+
sage: G = graphs.OrthogonalArrayBlockGraph(8,2) # needs sage.modules
|
485
|
+
Traceback (most recent call last):
|
486
|
+
...
|
487
|
+
ValueError: There is no OA(8,2). Beware, Brouwer's website uses OA(n,k) instead of OA(k,n) !
|
488
|
+
"""
|
489
|
+
if n > 1 and k >= n + 2:
|
490
|
+
raise ValueError("There is no OA({},{}). Beware, Brouwer's website uses OA(n,k) instead of OA(k,n) !".format(k, n))
|
491
|
+
|
492
|
+
from itertools import combinations
|
493
|
+
|
494
|
+
if OA is None:
|
495
|
+
from sage.combinat.designs.orthogonal_arrays import orthogonal_array
|
496
|
+
OA = orthogonal_array(k, n)
|
497
|
+
else:
|
498
|
+
assert len(OA) == n**2
|
499
|
+
assert n == 0 or k == len(OA[0])
|
500
|
+
|
501
|
+
OA = map(tuple, OA)
|
502
|
+
|
503
|
+
d = [[[] for j in range(n)] for i in range(k)]
|
504
|
+
for R in OA:
|
505
|
+
for i, x in enumerate(R):
|
506
|
+
d[i][x].append(R)
|
507
|
+
|
508
|
+
g = Graph()
|
509
|
+
for L in d:
|
510
|
+
for ll in L:
|
511
|
+
g.add_edges(combinations(ll, 2))
|
512
|
+
|
513
|
+
g.name("OA({},{})".format(k, n))
|
514
|
+
|
515
|
+
return g
|
516
|
+
|
517
|
+
|
518
|
+
def IntersectionGraph(S):
|
519
|
+
r"""
|
520
|
+
Return the intersection graph of the family `S`.
|
521
|
+
|
522
|
+
The intersection graph of a family `S` is a graph `G` with `V(G)=S` such
|
523
|
+
that two elements `s_1,s_2\in S` are adjacent in `G` if and only if `s_1\cap
|
524
|
+
s_2\neq \emptyset`.
|
525
|
+
|
526
|
+
INPUT:
|
527
|
+
|
528
|
+
- ``S`` -- list of sets/tuples/iterables
|
529
|
+
|
530
|
+
.. NOTE::
|
531
|
+
|
532
|
+
The elements of `S` must be finite, hashable, and the elements of
|
533
|
+
any `s\in S` must be hashable too.
|
534
|
+
|
535
|
+
EXAMPLES::
|
536
|
+
|
537
|
+
sage: graphs.IntersectionGraph([(1,2,3),(3,4,5),(5,6,7)])
|
538
|
+
Intersection Graph: Graph on 3 vertices
|
539
|
+
|
540
|
+
TESTS::
|
541
|
+
|
542
|
+
sage: graphs.IntersectionGraph([(1,2,[1])])
|
543
|
+
Traceback (most recent call last):
|
544
|
+
...
|
545
|
+
TypeError: The elements of S must be hashable, and this one is not: (1, 2, [1])
|
546
|
+
"""
|
547
|
+
for s in S:
|
548
|
+
try:
|
549
|
+
hash(s)
|
550
|
+
except TypeError:
|
551
|
+
raise TypeError("The elements of S must be hashable, and this one is not: {}".format(s))
|
552
|
+
|
553
|
+
ground_set_to_sets = {}
|
554
|
+
for s in S:
|
555
|
+
for x in s:
|
556
|
+
if x not in ground_set_to_sets:
|
557
|
+
ground_set_to_sets[x] = []
|
558
|
+
ground_set_to_sets[x].append(s)
|
559
|
+
|
560
|
+
g = Graph(name="Intersection Graph")
|
561
|
+
g.add_vertices(S)
|
562
|
+
for clique in ground_set_to_sets.values():
|
563
|
+
g.add_clique(set(clique))
|
564
|
+
|
565
|
+
return g
|