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.
Files changed (260) hide show
  1. passagemath_graphs-10.6.1rc1.dist-info/METADATA +292 -0
  2. passagemath_graphs-10.6.1rc1.dist-info/RECORD +260 -0
  3. passagemath_graphs-10.6.1rc1.dist-info/WHEEL +5 -0
  4. passagemath_graphs-10.6.1rc1.dist-info/top_level.txt +2 -0
  5. passagemath_graphs.libs/libgcc_s-69c45f16.so.1 +0 -0
  6. passagemath_graphs.libs/libgmp-8e78bd9b.so.10.5.0 +0 -0
  7. passagemath_graphs.libs/libstdc++-1f1a71be.so.6.0.33 +0 -0
  8. sage/all__sagemath_graphs.py +39 -0
  9. sage/combinat/abstract_tree.py +2723 -0
  10. sage/combinat/all__sagemath_graphs.py +34 -0
  11. sage/combinat/binary_tree.py +5306 -0
  12. sage/combinat/cluster_algebra_quiver/all.py +22 -0
  13. sage/combinat/cluster_algebra_quiver/cluster_seed.py +5208 -0
  14. sage/combinat/cluster_algebra_quiver/interact.py +124 -0
  15. sage/combinat/cluster_algebra_quiver/mutation_class.py +625 -0
  16. sage/combinat/cluster_algebra_quiver/mutation_type.py +1555 -0
  17. sage/combinat/cluster_algebra_quiver/quiver.py +2290 -0
  18. sage/combinat/cluster_algebra_quiver/quiver_mutation_type.py +2468 -0
  19. sage/combinat/designs/MOLS_handbook_data.py +570 -0
  20. sage/combinat/designs/all.py +58 -0
  21. sage/combinat/designs/bibd.py +1655 -0
  22. sage/combinat/designs/block_design.py +1071 -0
  23. sage/combinat/designs/covering_array.py +269 -0
  24. sage/combinat/designs/covering_design.py +530 -0
  25. sage/combinat/designs/database.py +5615 -0
  26. sage/combinat/designs/design_catalog.py +122 -0
  27. sage/combinat/designs/designs_pyx.cpython-310-aarch64-linux-gnu.so +0 -0
  28. sage/combinat/designs/designs_pyx.pxd +21 -0
  29. sage/combinat/designs/designs_pyx.pyx +993 -0
  30. sage/combinat/designs/difference_family.py +3951 -0
  31. sage/combinat/designs/difference_matrices.py +279 -0
  32. sage/combinat/designs/evenly_distributed_sets.cpython-310-aarch64-linux-gnu.so +0 -0
  33. sage/combinat/designs/evenly_distributed_sets.pyx +661 -0
  34. sage/combinat/designs/ext_rep.py +1064 -0
  35. sage/combinat/designs/gen_quadrangles_with_spread.cpython-310-aarch64-linux-gnu.so +0 -0
  36. sage/combinat/designs/gen_quadrangles_with_spread.pyx +339 -0
  37. sage/combinat/designs/group_divisible_designs.py +361 -0
  38. sage/combinat/designs/incidence_structures.py +2357 -0
  39. sage/combinat/designs/latin_squares.py +581 -0
  40. sage/combinat/designs/orthogonal_arrays.py +2244 -0
  41. sage/combinat/designs/orthogonal_arrays_build_recursive.py +1780 -0
  42. sage/combinat/designs/orthogonal_arrays_find_recursive.cpython-310-aarch64-linux-gnu.so +0 -0
  43. sage/combinat/designs/orthogonal_arrays_find_recursive.pyx +967 -0
  44. sage/combinat/designs/resolvable_bibd.py +815 -0
  45. sage/combinat/designs/steiner_quadruple_systems.py +1306 -0
  46. sage/combinat/designs/subhypergraph_search.cpython-310-aarch64-linux-gnu.so +0 -0
  47. sage/combinat/designs/subhypergraph_search.pyx +530 -0
  48. sage/combinat/designs/twographs.py +306 -0
  49. sage/combinat/finite_state_machine.py +14874 -0
  50. sage/combinat/finite_state_machine_generators.py +2006 -0
  51. sage/combinat/graph_path.py +448 -0
  52. sage/combinat/interval_posets.py +3908 -0
  53. sage/combinat/nu_tamari_lattice.py +269 -0
  54. sage/combinat/ordered_tree.py +1446 -0
  55. sage/combinat/posets/all.py +46 -0
  56. sage/combinat/posets/bubble_shuffle.py +247 -0
  57. sage/combinat/posets/cartesian_product.py +493 -0
  58. sage/combinat/posets/d_complete.py +182 -0
  59. sage/combinat/posets/elements.py +273 -0
  60. sage/combinat/posets/forest.py +30 -0
  61. sage/combinat/posets/hasse_cython.cpython-310-aarch64-linux-gnu.so +0 -0
  62. sage/combinat/posets/hasse_cython.pyx +174 -0
  63. sage/combinat/posets/hasse_diagram.py +3672 -0
  64. sage/combinat/posets/hochschild_lattice.py +158 -0
  65. sage/combinat/posets/incidence_algebras.py +794 -0
  66. sage/combinat/posets/lattices.py +5117 -0
  67. sage/combinat/posets/linear_extension_iterator.cpython-310-aarch64-linux-gnu.so +0 -0
  68. sage/combinat/posets/linear_extension_iterator.pyx +292 -0
  69. sage/combinat/posets/linear_extensions.py +1037 -0
  70. sage/combinat/posets/mobile.py +275 -0
  71. sage/combinat/posets/moebius_algebra.py +776 -0
  72. sage/combinat/posets/poset_examples.py +2178 -0
  73. sage/combinat/posets/posets.py +9360 -0
  74. sage/combinat/rooted_tree.py +1070 -0
  75. sage/combinat/shard_order.py +239 -0
  76. sage/combinat/tamari_lattices.py +384 -0
  77. sage/combinat/yang_baxter_graph.py +923 -0
  78. sage/databases/all__sagemath_graphs.py +1 -0
  79. sage/databases/knotinfo_db.py +1231 -0
  80. sage/ext_data/all__sagemath_graphs.py +1 -0
  81. sage/ext_data/graphs/graph_plot_js.html +330 -0
  82. sage/ext_data/kenzo/CP2.txt +45 -0
  83. sage/ext_data/kenzo/CP3.txt +349 -0
  84. sage/ext_data/kenzo/CP4.txt +4774 -0
  85. sage/ext_data/kenzo/README.txt +49 -0
  86. sage/ext_data/kenzo/S4.txt +20 -0
  87. sage/graphs/all.py +42 -0
  88. sage/graphs/asteroidal_triples.cpython-310-aarch64-linux-gnu.so +0 -0
  89. sage/graphs/asteroidal_triples.pyx +320 -0
  90. sage/graphs/base/all.py +1 -0
  91. sage/graphs/base/boost_graph.cpython-310-aarch64-linux-gnu.so +0 -0
  92. sage/graphs/base/boost_graph.pxd +106 -0
  93. sage/graphs/base/boost_graph.pyx +3045 -0
  94. sage/graphs/base/c_graph.cpython-310-aarch64-linux-gnu.so +0 -0
  95. sage/graphs/base/c_graph.pxd +106 -0
  96. sage/graphs/base/c_graph.pyx +5096 -0
  97. sage/graphs/base/dense_graph.cpython-310-aarch64-linux-gnu.so +0 -0
  98. sage/graphs/base/dense_graph.pxd +28 -0
  99. sage/graphs/base/dense_graph.pyx +801 -0
  100. sage/graphs/base/graph_backends.cpython-310-aarch64-linux-gnu.so +0 -0
  101. sage/graphs/base/graph_backends.pxd +5 -0
  102. sage/graphs/base/graph_backends.pyx +797 -0
  103. sage/graphs/base/overview.py +85 -0
  104. sage/graphs/base/sparse_graph.cpython-310-aarch64-linux-gnu.so +0 -0
  105. sage/graphs/base/sparse_graph.pxd +90 -0
  106. sage/graphs/base/sparse_graph.pyx +1653 -0
  107. sage/graphs/base/static_dense_graph.cpython-310-aarch64-linux-gnu.so +0 -0
  108. sage/graphs/base/static_dense_graph.pxd +5 -0
  109. sage/graphs/base/static_dense_graph.pyx +1032 -0
  110. sage/graphs/base/static_sparse_backend.cpython-310-aarch64-linux-gnu.so +0 -0
  111. sage/graphs/base/static_sparse_backend.pxd +27 -0
  112. sage/graphs/base/static_sparse_backend.pyx +1583 -0
  113. sage/graphs/base/static_sparse_graph.cpython-310-aarch64-linux-gnu.so +0 -0
  114. sage/graphs/base/static_sparse_graph.pxd +37 -0
  115. sage/graphs/base/static_sparse_graph.pyx +1375 -0
  116. sage/graphs/bipartite_graph.py +2732 -0
  117. sage/graphs/centrality.cpython-310-aarch64-linux-gnu.so +0 -0
  118. sage/graphs/centrality.pyx +1038 -0
  119. sage/graphs/cographs.py +519 -0
  120. sage/graphs/comparability.cpython-310-aarch64-linux-gnu.so +0 -0
  121. sage/graphs/comparability.pyx +851 -0
  122. sage/graphs/connectivity.cpython-310-aarch64-linux-gnu.so +0 -0
  123. sage/graphs/connectivity.pxd +157 -0
  124. sage/graphs/connectivity.pyx +4813 -0
  125. sage/graphs/convexity_properties.cpython-310-aarch64-linux-gnu.so +0 -0
  126. sage/graphs/convexity_properties.pxd +16 -0
  127. sage/graphs/convexity_properties.pyx +870 -0
  128. sage/graphs/digraph.py +4754 -0
  129. sage/graphs/digraph_generators.py +1993 -0
  130. sage/graphs/distances_all_pairs.cpython-310-aarch64-linux-gnu.so +0 -0
  131. sage/graphs/distances_all_pairs.pxd +12 -0
  132. sage/graphs/distances_all_pairs.pyx +2938 -0
  133. sage/graphs/domination.py +1363 -0
  134. sage/graphs/dot2tex_utils.py +100 -0
  135. sage/graphs/edge_connectivity.cpython-310-aarch64-linux-gnu.so +0 -0
  136. sage/graphs/edge_connectivity.pyx +1215 -0
  137. sage/graphs/generators/all.py +1 -0
  138. sage/graphs/generators/basic.py +1769 -0
  139. sage/graphs/generators/chessboard.py +538 -0
  140. sage/graphs/generators/classical_geometries.py +1611 -0
  141. sage/graphs/generators/degree_sequence.py +235 -0
  142. sage/graphs/generators/distance_regular.cpython-310-aarch64-linux-gnu.so +0 -0
  143. sage/graphs/generators/distance_regular.pyx +2846 -0
  144. sage/graphs/generators/families.py +4759 -0
  145. sage/graphs/generators/intersection.py +565 -0
  146. sage/graphs/generators/platonic_solids.py +262 -0
  147. sage/graphs/generators/random.py +2623 -0
  148. sage/graphs/generators/smallgraphs.py +5741 -0
  149. sage/graphs/generators/world_map.py +724 -0
  150. sage/graphs/generic_graph.py +26867 -0
  151. sage/graphs/generic_graph_pyx.cpython-310-aarch64-linux-gnu.so +0 -0
  152. sage/graphs/generic_graph_pyx.pxd +34 -0
  153. sage/graphs/generic_graph_pyx.pyx +1673 -0
  154. sage/graphs/genus.cpython-310-aarch64-linux-gnu.so +0 -0
  155. sage/graphs/genus.pyx +622 -0
  156. sage/graphs/graph.py +9645 -0
  157. sage/graphs/graph_coloring.cpython-310-aarch64-linux-gnu.so +0 -0
  158. sage/graphs/graph_coloring.pyx +2284 -0
  159. sage/graphs/graph_database.py +1177 -0
  160. sage/graphs/graph_decompositions/all.py +1 -0
  161. sage/graphs/graph_decompositions/bandwidth.cpython-310-aarch64-linux-gnu.so +0 -0
  162. sage/graphs/graph_decompositions/bandwidth.pyx +428 -0
  163. sage/graphs/graph_decompositions/clique_separators.cpython-310-aarch64-linux-gnu.so +0 -0
  164. sage/graphs/graph_decompositions/clique_separators.pyx +616 -0
  165. sage/graphs/graph_decompositions/cutwidth.cpython-310-aarch64-linux-gnu.so +0 -0
  166. sage/graphs/graph_decompositions/cutwidth.pyx +753 -0
  167. sage/graphs/graph_decompositions/fast_digraph.cpython-310-aarch64-linux-gnu.so +0 -0
  168. sage/graphs/graph_decompositions/fast_digraph.pxd +13 -0
  169. sage/graphs/graph_decompositions/fast_digraph.pyx +212 -0
  170. sage/graphs/graph_decompositions/graph_products.cpython-310-aarch64-linux-gnu.so +0 -0
  171. sage/graphs/graph_decompositions/graph_products.pyx +508 -0
  172. sage/graphs/graph_decompositions/modular_decomposition.cpython-310-aarch64-linux-gnu.so +0 -0
  173. sage/graphs/graph_decompositions/modular_decomposition.pxd +27 -0
  174. sage/graphs/graph_decompositions/modular_decomposition.pyx +1536 -0
  175. sage/graphs/graph_decompositions/slice_decomposition.cpython-310-aarch64-linux-gnu.so +0 -0
  176. sage/graphs/graph_decompositions/slice_decomposition.pxd +18 -0
  177. sage/graphs/graph_decompositions/slice_decomposition.pyx +1106 -0
  178. sage/graphs/graph_decompositions/tree_decomposition.cpython-310-aarch64-linux-gnu.so +0 -0
  179. sage/graphs/graph_decompositions/tree_decomposition.pxd +17 -0
  180. sage/graphs/graph_decompositions/tree_decomposition.pyx +1996 -0
  181. sage/graphs/graph_decompositions/vertex_separation.cpython-310-aarch64-linux-gnu.so +0 -0
  182. sage/graphs/graph_decompositions/vertex_separation.pxd +5 -0
  183. sage/graphs/graph_decompositions/vertex_separation.pyx +1963 -0
  184. sage/graphs/graph_editor.py +82 -0
  185. sage/graphs/graph_generators.py +3314 -0
  186. sage/graphs/graph_generators_pyx.cpython-310-aarch64-linux-gnu.so +0 -0
  187. sage/graphs/graph_generators_pyx.pyx +95 -0
  188. sage/graphs/graph_input.py +812 -0
  189. sage/graphs/graph_latex.py +2064 -0
  190. sage/graphs/graph_list.py +410 -0
  191. sage/graphs/graph_plot.py +1756 -0
  192. sage/graphs/graph_plot_js.py +338 -0
  193. sage/graphs/hyperbolicity.cpython-310-aarch64-linux-gnu.so +0 -0
  194. sage/graphs/hyperbolicity.pyx +1704 -0
  195. sage/graphs/hypergraph_generators.py +364 -0
  196. sage/graphs/independent_sets.cpython-310-aarch64-linux-gnu.so +0 -0
  197. sage/graphs/independent_sets.pxd +13 -0
  198. sage/graphs/independent_sets.pyx +402 -0
  199. sage/graphs/isgci.py +1033 -0
  200. sage/graphs/isoperimetric_inequalities.cpython-310-aarch64-linux-gnu.so +0 -0
  201. sage/graphs/isoperimetric_inequalities.pyx +489 -0
  202. sage/graphs/line_graph.cpython-310-aarch64-linux-gnu.so +0 -0
  203. sage/graphs/line_graph.pyx +743 -0
  204. sage/graphs/lovasz_theta.py +77 -0
  205. sage/graphs/matching.py +1633 -0
  206. sage/graphs/matching_covered_graph.py +3590 -0
  207. sage/graphs/orientations.py +1489 -0
  208. sage/graphs/partial_cube.py +459 -0
  209. sage/graphs/path_enumeration.cpython-310-aarch64-linux-gnu.so +0 -0
  210. sage/graphs/path_enumeration.pyx +2040 -0
  211. sage/graphs/pq_trees.py +1129 -0
  212. sage/graphs/print_graphs.py +201 -0
  213. sage/graphs/schnyder.py +865 -0
  214. sage/graphs/spanning_tree.cpython-310-aarch64-linux-gnu.so +0 -0
  215. sage/graphs/spanning_tree.pyx +1457 -0
  216. sage/graphs/strongly_regular_db.cpython-310-aarch64-linux-gnu.so +0 -0
  217. sage/graphs/strongly_regular_db.pyx +3340 -0
  218. sage/graphs/traversals.cpython-310-aarch64-linux-gnu.so +0 -0
  219. sage/graphs/traversals.pxd +9 -0
  220. sage/graphs/traversals.pyx +1872 -0
  221. sage/graphs/trees.cpython-310-aarch64-linux-gnu.so +0 -0
  222. sage/graphs/trees.pxd +15 -0
  223. sage/graphs/trees.pyx +310 -0
  224. sage/graphs/tutte_polynomial.py +713 -0
  225. sage/graphs/views.cpython-310-aarch64-linux-gnu.so +0 -0
  226. sage/graphs/views.pyx +794 -0
  227. sage/graphs/weakly_chordal.cpython-310-aarch64-linux-gnu.so +0 -0
  228. sage/graphs/weakly_chordal.pyx +604 -0
  229. sage/groups/all__sagemath_graphs.py +1 -0
  230. sage/groups/perm_gps/all__sagemath_graphs.py +1 -0
  231. sage/groups/perm_gps/partn_ref/all__sagemath_graphs.py +1 -0
  232. sage/groups/perm_gps/partn_ref/refinement_graphs.cpython-310-aarch64-linux-gnu.so +0 -0
  233. sage/groups/perm_gps/partn_ref/refinement_graphs.pxd +38 -0
  234. sage/groups/perm_gps/partn_ref/refinement_graphs.pyx +1666 -0
  235. sage/knots/all.py +6 -0
  236. sage/knots/free_knotinfo_monoid.py +507 -0
  237. sage/knots/gauss_code.py +291 -0
  238. sage/knots/knot.py +682 -0
  239. sage/knots/knot_table.py +284 -0
  240. sage/knots/knotinfo.py +2900 -0
  241. sage/knots/link.py +4715 -0
  242. sage/sandpiles/all.py +13 -0
  243. sage/sandpiles/examples.py +225 -0
  244. sage/sandpiles/sandpile.py +6365 -0
  245. sage/topology/all.py +22 -0
  246. sage/topology/cell_complex.py +1214 -0
  247. sage/topology/cubical_complex.py +1976 -0
  248. sage/topology/delta_complex.py +1806 -0
  249. sage/topology/filtered_simplicial_complex.py +744 -0
  250. sage/topology/moment_angle_complex.py +823 -0
  251. sage/topology/simplicial_complex.py +5160 -0
  252. sage/topology/simplicial_complex_catalog.py +92 -0
  253. sage/topology/simplicial_complex_examples.py +1680 -0
  254. sage/topology/simplicial_complex_homset.py +205 -0
  255. sage/topology/simplicial_complex_morphism.py +836 -0
  256. sage/topology/simplicial_set.py +4102 -0
  257. sage/topology/simplicial_set_catalog.py +55 -0
  258. sage/topology/simplicial_set_constructions.py +2954 -0
  259. sage/topology/simplicial_set_examples.py +865 -0
  260. sage/topology/simplicial_set_morphism.py +1464 -0
@@ -0,0 +1,489 @@
1
+ # sage_setup: distribution = sagemath-graphs
2
+ # cython: binding = True
3
+ r"""
4
+ Isoperimetric inequalities
5
+
6
+ This module contains various functions to compute isoperimetric numbers
7
+ of a graph.
8
+
9
+ Authors:
10
+
11
+ - Peleg Michaeli
12
+ - Vincent Delecroix
13
+ """
14
+ # ****************************************************************************
15
+ # Copyright (C) 2018 Vincent Delecroix <20100.delecroix@gmail.com>
16
+ #
17
+ # Distributed under the terms of the GNU General Public License (GPL)
18
+ # as published by the Free Software Foundation; either version 2 of
19
+ # the License, or (at your option) any later version.
20
+ # https://www.gnu.org/licenses/
21
+ # ****************************************************************************
22
+
23
+
24
+ from cysignals.signals cimport sig_on, sig_off
25
+ from cysignals.memory cimport check_malloc, sig_free
26
+
27
+ from sage.data_structures.binary_matrix cimport *
28
+ from sage.graphs.base.static_dense_graph cimport dense_graph_init
29
+ from sage.graphs.base.static_sparse_backend cimport StaticSparseCGraph
30
+ from sage.graphs.base.static_sparse_backend cimport StaticSparseBackend
31
+ from sage.graphs.base.static_sparse_graph cimport short_digraph, init_short_digraph, free_short_digraph
32
+
33
+ from sage.rings.infinity import Infinity
34
+ from sage.rings.rational_field import QQ
35
+
36
+
37
+ def cheeger_constant(g):
38
+ r"""
39
+ Return the cheeger constant of the graph.
40
+
41
+ The Cheeger constant of a graph `G = (V,E)` is the minimum of `|\partial S|
42
+ / |Vol(S)|` where `Vol(S)` is the sum of degrees of element in `S`,
43
+ `\partial S` is the edge boundary of `S` (number of edges with one end in
44
+ `S` and one end in `V \setminus S`) and the minimum is taken over all
45
+ non-empty subsets `S` of vertices so that `|Vol(S)| \leq |E|`.
46
+
47
+ .. SEEALSO::
48
+
49
+ Alternative but similar quantities can be obtained via the methods
50
+ :meth:`edge_isoperimetric_number` and :meth:`vertex_isoperimetric_number`.
51
+
52
+ EXAMPLES::
53
+
54
+ sage: graphs.PetersenGraph().cheeger_constant()
55
+ 1/3
56
+
57
+ The Cheeger constant of a cycle on `n` vertices is
58
+ `1/\lfloor n/2 \rfloor`::
59
+
60
+ sage: [graphs.CycleGraph(k).cheeger_constant() for k in range(2,10)]
61
+ [1, 1, 1/2, 1/2, 1/3, 1/3, 1/4, 1/4]
62
+
63
+ The Cheeger constant of a complete graph on `n` vertices is
64
+ `\lceil n/2 \rceil / (n-1)`::
65
+
66
+ sage: [graphs.CompleteGraph(k).cheeger_constant() for k in range(2,10)]
67
+ [1, 1, 2/3, 3/4, 3/5, 2/3, 4/7, 5/8]
68
+
69
+ For complete bipartite::
70
+
71
+ sage: [graphs.CompleteBipartiteGraph(i,j).cheeger_constant() for i in range(2,7) for j in range(2, i)]
72
+ [3/5, 1/2, 3/5, 5/9, 4/7, 5/9, 1/2, 5/9, 1/2, 5/9]
73
+
74
+ More examples::
75
+
76
+ sage: G = Graph([(0, 1), (0, 3), (0, 8), (1, 4), (1, 6), (2, 4), (2, 7), (2, 9),
77
+ ....: (3, 6), (3, 8), (4, 9), (5, 6), (5, 7), (5, 8), (7, 9)])
78
+ sage: G.cheeger_constant()
79
+ 1/6
80
+
81
+ sage: G = Graph([(0, 1), (0, 2), (1, 2), (1, 3), (1, 4), (1, 5), (2, 3), (3, 4), (3, 5)])
82
+ sage: G.cheeger_constant()
83
+ 1/2
84
+
85
+ sage: Graph([[1,2,3,4],[(1,2),(3,4)]]).cheeger_constant()
86
+ 0
87
+
88
+ TESTS::
89
+
90
+ sage: graphs.EmptyGraph().cheeger_constant()
91
+ Traceback (most recent call last):
92
+ ...
93
+ ValueError: Cheeger constant is not defined for the empty graph
94
+
95
+ Immutable graph::
96
+
97
+ sage: G = graphs.RandomGNP(10, .7)
98
+ sage: G._backend
99
+ <sage.graphs.base.sparse_graph.SparseGraphBackend ...>
100
+ sage: H = Graph(G, immutable=True)
101
+ sage: H._backend
102
+ <sage.graphs.base.static_sparse_backend.StaticSparseBackend ...>
103
+ sage: G.cheeger_constant() == H.cheeger_constant()
104
+ True
105
+ """
106
+ if g.is_directed():
107
+ raise ValueError("Cheeger constant is only defined on non-oriented graph")
108
+ g._scream_if_not_simple()
109
+ if g.num_verts() == 0:
110
+ raise ValueError("Cheeger constant is not defined for the empty graph")
111
+ elif g.num_verts() == 1:
112
+ return Infinity
113
+ elif not g.is_connected():
114
+ return QQ.zero()
115
+
116
+ cdef StaticSparseCGraph cg
117
+ cdef short_digraph sd # a copy of the graph g
118
+ cdef int * subgraph # vertices of the subgraph (stack)
119
+ cdef int * bitsubgraph # vertices of the subgraph (bit array of +1 (in) or -1 (not in))
120
+ cdef int k = 0 # number of vertices in subgraph
121
+ cdef int vol = 0 # number of edges in the subgraph
122
+ cdef int boundary = 0 # number of edges in the boundary
123
+ cdef int u = 0 # current vertex
124
+ cdef unsigned long bmin = 1 # value of boundary for the min
125
+ cdef unsigned long vmin = 1 # value of the volume for the min
126
+ cdef int i
127
+
128
+ if isinstance(g, StaticSparseBackend):
129
+ cg = <StaticSparseCGraph> g._cg
130
+ sd = <short_digraph> cg.g
131
+ else:
132
+ init_short_digraph(sd, g, edge_labelled=False, vertex_list=list(g))
133
+
134
+ subgraph = <int *> check_malloc(sd.n * sizeof(int))
135
+ bitsubgraph = <int *> check_malloc(sd.n * sizeof(int))
136
+
137
+ sig_on()
138
+ try:
139
+ for i in range(sd.n):
140
+ bitsubgraph[i] = -1
141
+ while True:
142
+ while True:
143
+ # add vertex u to the subgraph, update the boundary/volume
144
+ # we repeat the operation until we reach the maximum volume
145
+ # or have no more vertex available
146
+ for i in range(sd.neighbors[u+1] - sd.neighbors[u]):
147
+ boundary -= bitsubgraph[sd.neighbors[u][i]]
148
+ vol += 1
149
+
150
+ bitsubgraph[u] = 1
151
+ subgraph[k] = u
152
+ u += 1
153
+ k += 1
154
+
155
+ if vol > sd.m:
156
+ break
157
+
158
+ if boundary * vmin < bmin * vol:
159
+ bmin = boundary
160
+ vmin = vol
161
+
162
+ if u == sd.n:
163
+ break
164
+
165
+ # backtrack
166
+ k -= 1
167
+ u = subgraph[k]
168
+
169
+ bitsubgraph[u] = -1
170
+ for i in range(sd.neighbors[u+1] - sd.neighbors[u]):
171
+ boundary += bitsubgraph[sd.neighbors[u][i]]
172
+ vol -= 1
173
+ u += 1
174
+
175
+ if u == sd.n:
176
+ if k == 0:
177
+ # end of the loop
178
+ break
179
+ else:
180
+ # remove one more vertex in order to continue
181
+ k -= 1
182
+ u = subgraph[k]
183
+
184
+ bitsubgraph[u] = -1
185
+ for i in range(sd.neighbors[u+1] - sd.neighbors[u]):
186
+ boundary += bitsubgraph[sd.neighbors[u][i]]
187
+ vol -= 1
188
+ u += 1
189
+ return QQ((bmin, vmin))
190
+
191
+ finally:
192
+ if not isinstance(g, StaticSparseBackend):
193
+ free_short_digraph(sd)
194
+ sig_free(subgraph)
195
+ sig_free(bitsubgraph)
196
+ sig_off()
197
+
198
+
199
+ def edge_isoperimetric_number(g):
200
+ r"""
201
+ Return the edge-isoperimetric number of the graph.
202
+
203
+ The edge-isoperimetric number of a graph `G = (V,E)` is also sometimes
204
+ called the *isoperimetric number*. It is defined as the minimum of
205
+ `|\partial S| / |S|` where `\partial S` is the edge boundary of `S` (number
206
+ of edges with one end in `S` and one end in `V \setminus S`) and the
207
+ minimum is taken over all subsets of vertices whose cardinality does not
208
+ exceed half the size `|V|` of the graph.
209
+
210
+ .. SEEALSO::
211
+
212
+ Alternative but similar quantities can be obtained via the methods
213
+ :meth:`cheeger_constant` and :meth:`vertex_isoperimetric_number`.
214
+
215
+ EXAMPLES:
216
+
217
+ The edge-isoperimetric number of a complete graph on `n` vertices is
218
+ `\lceil n/2 \rceil`::
219
+
220
+ sage: [graphs.CompleteGraph(n).edge_isoperimetric_number() for n in range(2,10)]
221
+ [1, 2, 2, 3, 3, 4, 4, 5]
222
+
223
+ The edge-isoperimetric constant of a cycle on `n` vertices is
224
+ `2/\lfloor n/2 \rfloor`::
225
+
226
+ sage: [graphs.CycleGraph(n).edge_isoperimetric_number() for n in range(2,15)]
227
+ [1, 2, 1, 1, 2/3, 2/3, 1/2, 1/2, 2/5, 2/5, 1/3, 1/3, 2/7]
228
+
229
+ In general, for `d`-regular graphs the edge-isoperimetric number is
230
+ `d` times larger than the Cheeger constant of the graph::
231
+
232
+ sage: g = graphs.RandomRegular(3, 10) # needs networkx
233
+ sage: g.edge_isoperimetric_number() == g.cheeger_constant() * 3 # needs networkx
234
+ True
235
+
236
+ And the edge-isoperimetric constant of a disconnected graph is `0`::
237
+
238
+ sage: Graph([[1,2,3,4],[(1,2),(3,4)]]).edge_isoperimetric_number()
239
+ 0
240
+
241
+ TESTS::
242
+
243
+ sage: graphs.EmptyGraph().edge_isoperimetric_number()
244
+ Traceback (most recent call last):
245
+ ...
246
+ ValueError: edge-isoperimetric number not defined for the empty graph
247
+
248
+ Immutable graph::
249
+
250
+ sage: G = graphs.RandomGNP(10, .7)
251
+ sage: G._backend
252
+ <sage.graphs.base.sparse_graph.SparseGraphBackend ...>
253
+ sage: H = Graph(G, immutable=True)
254
+ sage: H._backend
255
+ <sage.graphs.base.static_sparse_backend.StaticSparseBackend ...>
256
+ sage: G.edge_isoperimetric_number() == H.edge_isoperimetric_number()
257
+ True
258
+ """
259
+ if g.is_directed():
260
+ raise ValueError("edge isoperimetric number is only defined on non-oriented graph")
261
+ g._scream_if_not_simple()
262
+ if g.num_verts() == 0:
263
+ raise ValueError("edge-isoperimetric number not defined for the empty graph")
264
+ elif g.num_verts() == 1:
265
+ return Infinity
266
+ elif not g.is_connected():
267
+ return QQ((0, 1))
268
+
269
+ cdef StaticSparseCGraph cg
270
+ cdef short_digraph sd # a copy of the graph g
271
+ cdef int * subgraph # vertices of the subgraph (stack)
272
+ cdef int * bitsubgraph # vertices of the subgraph (bit array of +1 (in) or -1 (not in))
273
+ cdef int k = 0 # number of vertices in subgraph
274
+ cdef unsigned long vol = 0 # number of edges in the subgraph
275
+ cdef unsigned long boundary = 0 # number of edges in the boundary
276
+ cdef int u = 0 # current vertex
277
+ cdef int i
278
+
279
+ if isinstance(g, StaticSparseBackend):
280
+ cg = <StaticSparseCGraph> g._cg
281
+ sd = <short_digraph> cg.g
282
+ else:
283
+ init_short_digraph(sd, g, edge_labelled=False, vertex_list=list(g))
284
+
285
+ cdef unsigned long bmin = sd.neighbors[1] - sd.neighbors[0] # value of boundary for the min
286
+ cdef unsigned long vmin = 1 # value of the volume for the min
287
+
288
+ subgraph = <int *> check_malloc(sd.n * sizeof(int))
289
+ bitsubgraph = <int *> check_malloc(sd.n * sizeof(int))
290
+
291
+ sig_on()
292
+ try:
293
+ for i in range(sd.n):
294
+ bitsubgraph[i] = -1
295
+
296
+ while True:
297
+ while True:
298
+ # add vertex u to the subgraph, update the boundary/volume
299
+ # we repeat the operation until we reach the maximum volume
300
+ # or have no more vertex available
301
+ for i in range(sd.neighbors[u+1] - sd.neighbors[u]):
302
+ boundary -= bitsubgraph[sd.neighbors[u][i]]
303
+ vol += 1
304
+
305
+ bitsubgraph[u] = 1
306
+ subgraph[k] = u
307
+ u += 1
308
+ k += 1
309
+
310
+ if 2*vol > sd.n:
311
+ break
312
+
313
+ if boundary * vmin < bmin * vol:
314
+ bmin = boundary
315
+ vmin = vol
316
+
317
+ if u == sd.n:
318
+ break
319
+
320
+ # backtrack
321
+ k -= 1
322
+ u = subgraph[k]
323
+
324
+ bitsubgraph[u] = -1
325
+ for i in range(sd.neighbors[u+1] - sd.neighbors[u]):
326
+ boundary += bitsubgraph[sd.neighbors[u][i]]
327
+ vol -= 1
328
+ u += 1
329
+
330
+ if u == sd.n:
331
+ if k == 0:
332
+ # end of the loop
333
+ break
334
+ else:
335
+ # remove one more vertex in order to continue
336
+ k -= 1
337
+ u = subgraph[k]
338
+
339
+ bitsubgraph[u] = -1
340
+ for i in range(sd.neighbors[u+1] - sd.neighbors[u]):
341
+ boundary += bitsubgraph[sd.neighbors[u][i]]
342
+ vol -= 1
343
+ u += 1
344
+
345
+ return QQ((bmin, vmin))
346
+
347
+ finally:
348
+ sig_off()
349
+ if not isinstance(g, StaticSparseBackend):
350
+ free_short_digraph(sd)
351
+ sig_free(subgraph)
352
+ sig_free(bitsubgraph)
353
+
354
+
355
+ def vertex_isoperimetric_number(g):
356
+ r"""
357
+ Return the vertex-isoperimetric number of the graph.
358
+
359
+ The vertex-isoperimetric number of a graph `G = (V,E)` is also sometimes
360
+ called the *magnifying constant*. It is defined as the minimum of `|N(S)| /
361
+ |S|` where `|N(S)|` is the vertex boundary of `S` and the minimum is taken
362
+ over the subsets `S` of vertices of size at most half of the vertices.
363
+
364
+ .. SEEALSO::
365
+
366
+ Alternative but similar quantities can be obtained via the methods
367
+ :meth:`cheeger_constant` and :meth:`edge_isoperimetric_number`.
368
+
369
+ EXAMPLES:
370
+
371
+ The vertex-isoperimetric number of a complete graph on `n` vertices is
372
+ `\lceil n/2 \rceil/\lfloor n/2 \rfloor`::
373
+
374
+ sage: [graphs.CompleteGraph(k).vertex_isoperimetric_number() for k in range(2,15)]
375
+ [1, 2, 1, 3/2, 1, 4/3, 1, 5/4, 1, 6/5, 1, 7/6, 1]
376
+
377
+ The vertex-isoperimetric number of a cycle on `n` vertices is
378
+ `2/\lfloor n/2 \rfloor`::
379
+
380
+ sage: [graphs.CycleGraph(k).vertex_isoperimetric_number() for k in range(2,15)]
381
+ [1, 2, 1, 1, 2/3, 2/3, 1/2, 1/2, 2/5, 2/5, 1/3, 1/3, 2/7]
382
+
383
+ And the vertex-isoperimetric number of a disconnected graph is `0`::
384
+
385
+ sage: Graph([[1,2,3],[(1,2)]]).vertex_isoperimetric_number()
386
+ 0
387
+
388
+ The vertex-isoperimetric number is independent of edge multiplicity::
389
+
390
+ sage: G = graphs.CycleGraph(6)
391
+ sage: G.vertex_isoperimetric_number()
392
+ 2/3
393
+ sage: G.allow_multiple_edges(True)
394
+ sage: G.add_edges(G.edges(sort=False))
395
+ sage: G.vertex_isoperimetric_number()
396
+ 2/3
397
+
398
+ TESTS::
399
+
400
+ sage: graphs.EmptyGraph().vertex_isoperimetric_number()
401
+ Traceback (most recent call last):
402
+ ...
403
+ ValueError: vertex-isoperimetric number not defined for the empty graph
404
+ """
405
+ if g.is_directed():
406
+ raise ValueError("vertex-isoperimetric number is only defined on non-oriented graph")
407
+ if not g:
408
+ raise ValueError("vertex-isoperimetric number not defined for the empty graph")
409
+ elif g.order() == 1:
410
+ return Infinity
411
+ elif not g.is_connected():
412
+ return QQ((0, 1))
413
+
414
+ # We convert the graph to a static dense graph
415
+ cdef binary_matrix_t DG
416
+ dense_graph_init(DG, g)
417
+ cdef int n = g.order()
418
+ cdef int k = n / 2 # maximum size of a subset
419
+
420
+ sig_on()
421
+
422
+ # We use a stack of bitsets. For that, we need 3 bitsets per level with at
423
+ # most n/2 + 1 levels, so 3 * (n / 2) + 3 bitsets. We also need another
424
+ # bitset that we create at the same time, so overall 3 * (n / 2) + 4 bitsets
425
+ cdef binary_matrix_t stack
426
+ binary_matrix_init(stack, 3 * (n / 2) + 4, n)
427
+
428
+ cdef bitset_t candidates = stack.rows[3 * (n / 2) + 3]
429
+ cdef bitset_t left # vertices not yet explored
430
+ cdef bitset_t current # vertices in the current subset
431
+ cdef bitset_t boundary # union of neighbors of vertices in current subset
432
+
433
+ cdef int level = 0
434
+ cdef int p = n
435
+ cdef int q = 0
436
+ cdef int c, b, v
437
+
438
+ # We initialize the first level
439
+ for v in range(3):
440
+ bitset_clear(stack.rows[v])
441
+ bitset_complement(stack.rows[0], stack.rows[0])
442
+
443
+ while level >= 0:
444
+
445
+ # We take the values at the top of the stack
446
+ left = stack.rows[level]
447
+ current = stack.rows[level + 1]
448
+ boundary = stack.rows[level + 2]
449
+
450
+ if bitset_isempty(current):
451
+ bitset_copy(candidates, left)
452
+ else:
453
+ bitset_and(candidates, left, boundary)
454
+
455
+ if bitset_isempty(candidates):
456
+ # We decrease l to pop the stack
457
+ level -= 3
458
+
459
+ # If the current set if non empty, we update the lower bound
460
+ c = bitset_len(current)
461
+ if c:
462
+ bitset_difference(boundary, boundary, current)
463
+ b = bitset_len(boundary)
464
+ if b * q < p * c:
465
+ p = b
466
+ q = c
467
+
468
+ else:
469
+ # Choose a candidate vertex v
470
+ v = bitset_first(candidates)
471
+ bitset_discard(left, v)
472
+
473
+ # Since we have not modified l, the bitsets for iterating without v
474
+ # in the subset current are now at the top of the stack, with
475
+ # correct values
476
+
477
+ if bitset_len(current) < k:
478
+ # We continue with v in the subset current
479
+ level += 3
480
+ bitset_copy(stack.rows[level], left)
481
+ bitset_copy(stack.rows[level + 1], current)
482
+ bitset_add(stack.rows[level + 1], v)
483
+ bitset_union(stack.rows[level + 2], boundary, DG.rows[v])
484
+
485
+ binary_matrix_free(stack)
486
+ binary_matrix_free(DG)
487
+ sig_off()
488
+
489
+ return QQ((p, q))