passagemath-graphs 10.5.43__cp39-cp39-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 (258) hide show
  1. passagemath_graphs-10.5.43.dist-info/METADATA +293 -0
  2. passagemath_graphs-10.5.43.dist-info/RECORD +258 -0
  3. passagemath_graphs-10.5.43.dist-info/WHEEL +5 -0
  4. passagemath_graphs-10.5.43.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 +2552 -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 +125 -0
  15. sage/combinat/cluster_algebra_quiver/mutation_class.py +625 -0
  16. sage/combinat/cluster_algebra_quiver/mutation_type.py +1556 -0
  17. sage/combinat/cluster_algebra_quiver/quiver.py +2262 -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 +534 -0
  25. sage/combinat/designs/database.py +5614 -0
  26. sage/combinat/designs/design_catalog.py +122 -0
  27. sage/combinat/designs/designs_pyx.cpython-39-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-39-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-39-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 +548 -0
  40. sage/combinat/designs/orthogonal_arrays.py +2243 -0
  41. sage/combinat/designs/orthogonal_arrays_build_recursive.py +1780 -0
  42. sage/combinat/designs/orthogonal_arrays_find_recursive.cpython-39-aarch64-linux-gnu.so +0 -0
  43. sage/combinat/designs/orthogonal_arrays_find_recursive.pyx +966 -0
  44. sage/combinat/designs/resolvable_bibd.py +781 -0
  45. sage/combinat/designs/steiner_quadruple_systems.py +1306 -0
  46. sage/combinat/designs/subhypergraph_search.cpython-39-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/cartesian_product.py +493 -0
  57. sage/combinat/posets/d_complete.py +182 -0
  58. sage/combinat/posets/elements.py +273 -0
  59. sage/combinat/posets/forest.py +30 -0
  60. sage/combinat/posets/hasse_cython.cpython-39-aarch64-linux-gnu.so +0 -0
  61. sage/combinat/posets/hasse_cython.pyx +174 -0
  62. sage/combinat/posets/hasse_diagram.py +3678 -0
  63. sage/combinat/posets/incidence_algebras.py +796 -0
  64. sage/combinat/posets/lattices.py +5119 -0
  65. sage/combinat/posets/linear_extension_iterator.cpython-39-aarch64-linux-gnu.so +0 -0
  66. sage/combinat/posets/linear_extension_iterator.pyx +292 -0
  67. sage/combinat/posets/linear_extensions.py +1039 -0
  68. sage/combinat/posets/mobile.py +275 -0
  69. sage/combinat/posets/moebius_algebra.py +776 -0
  70. sage/combinat/posets/poset_examples.py +2131 -0
  71. sage/combinat/posets/posets.py +9169 -0
  72. sage/combinat/rooted_tree.py +1070 -0
  73. sage/combinat/shard_order.py +239 -0
  74. sage/combinat/tamari_lattices.py +384 -0
  75. sage/combinat/yang_baxter_graph.py +923 -0
  76. sage/databases/all__sagemath_graphs.py +1 -0
  77. sage/databases/knotinfo_db.py +1230 -0
  78. sage/ext_data/all__sagemath_graphs.py +1 -0
  79. sage/ext_data/graphs/graph_plot_js.html +330 -0
  80. sage/ext_data/kenzo/CP2.txt +45 -0
  81. sage/ext_data/kenzo/CP3.txt +349 -0
  82. sage/ext_data/kenzo/CP4.txt +4774 -0
  83. sage/ext_data/kenzo/README.txt +49 -0
  84. sage/ext_data/kenzo/S4.txt +20 -0
  85. sage/graphs/all.py +42 -0
  86. sage/graphs/asteroidal_triples.cpython-39-aarch64-linux-gnu.so +0 -0
  87. sage/graphs/asteroidal_triples.pyx +299 -0
  88. sage/graphs/base/all.py +1 -0
  89. sage/graphs/base/boost_graph.cpython-39-aarch64-linux-gnu.so +0 -0
  90. sage/graphs/base/boost_graph.pxd +106 -0
  91. sage/graphs/base/boost_graph.pyx +3045 -0
  92. sage/graphs/base/c_graph.cpython-39-aarch64-linux-gnu.so +0 -0
  93. sage/graphs/base/c_graph.pxd +106 -0
  94. sage/graphs/base/c_graph.pyx +5096 -0
  95. sage/graphs/base/dense_graph.cpython-39-aarch64-linux-gnu.so +0 -0
  96. sage/graphs/base/dense_graph.pxd +26 -0
  97. sage/graphs/base/dense_graph.pyx +757 -0
  98. sage/graphs/base/graph_backends.cpython-39-aarch64-linux-gnu.so +0 -0
  99. sage/graphs/base/graph_backends.pxd +5 -0
  100. sage/graphs/base/graph_backends.pyx +797 -0
  101. sage/graphs/base/overview.py +85 -0
  102. sage/graphs/base/sparse_graph.cpython-39-aarch64-linux-gnu.so +0 -0
  103. sage/graphs/base/sparse_graph.pxd +90 -0
  104. sage/graphs/base/sparse_graph.pyx +1653 -0
  105. sage/graphs/base/static_dense_graph.cpython-39-aarch64-linux-gnu.so +0 -0
  106. sage/graphs/base/static_dense_graph.pxd +5 -0
  107. sage/graphs/base/static_dense_graph.pyx +1032 -0
  108. sage/graphs/base/static_sparse_backend.cpython-39-aarch64-linux-gnu.so +0 -0
  109. sage/graphs/base/static_sparse_backend.pxd +27 -0
  110. sage/graphs/base/static_sparse_backend.pyx +1580 -0
  111. sage/graphs/base/static_sparse_graph.cpython-39-aarch64-linux-gnu.so +0 -0
  112. sage/graphs/base/static_sparse_graph.pxd +37 -0
  113. sage/graphs/base/static_sparse_graph.pyx +1304 -0
  114. sage/graphs/bipartite_graph.py +2709 -0
  115. sage/graphs/centrality.cpython-39-aarch64-linux-gnu.so +0 -0
  116. sage/graphs/centrality.pyx +965 -0
  117. sage/graphs/cographs.py +519 -0
  118. sage/graphs/comparability.cpython-39-aarch64-linux-gnu.so +0 -0
  119. sage/graphs/comparability.pyx +813 -0
  120. sage/graphs/connectivity.cpython-39-aarch64-linux-gnu.so +0 -0
  121. sage/graphs/connectivity.pxd +157 -0
  122. sage/graphs/connectivity.pyx +4813 -0
  123. sage/graphs/convexity_properties.cpython-39-aarch64-linux-gnu.so +0 -0
  124. sage/graphs/convexity_properties.pxd +16 -0
  125. sage/graphs/convexity_properties.pyx +827 -0
  126. sage/graphs/digraph.py +4410 -0
  127. sage/graphs/digraph_generators.py +1921 -0
  128. sage/graphs/distances_all_pairs.cpython-39-aarch64-linux-gnu.so +0 -0
  129. sage/graphs/distances_all_pairs.pxd +12 -0
  130. sage/graphs/distances_all_pairs.pyx +2938 -0
  131. sage/graphs/domination.py +1363 -0
  132. sage/graphs/dot2tex_utils.py +100 -0
  133. sage/graphs/edge_connectivity.cpython-39-aarch64-linux-gnu.so +0 -0
  134. sage/graphs/edge_connectivity.pyx +1215 -0
  135. sage/graphs/generators/all.py +1 -0
  136. sage/graphs/generators/basic.py +1769 -0
  137. sage/graphs/generators/chessboard.py +538 -0
  138. sage/graphs/generators/classical_geometries.py +1611 -0
  139. sage/graphs/generators/degree_sequence.py +235 -0
  140. sage/graphs/generators/distance_regular.cpython-39-aarch64-linux-gnu.so +0 -0
  141. sage/graphs/generators/distance_regular.pyx +2846 -0
  142. sage/graphs/generators/families.py +4749 -0
  143. sage/graphs/generators/intersection.py +565 -0
  144. sage/graphs/generators/platonic_solids.py +262 -0
  145. sage/graphs/generators/random.py +2623 -0
  146. sage/graphs/generators/smallgraphs.py +5741 -0
  147. sage/graphs/generators/world_map.py +724 -0
  148. sage/graphs/generic_graph.py +26395 -0
  149. sage/graphs/generic_graph_pyx.cpython-39-aarch64-linux-gnu.so +0 -0
  150. sage/graphs/generic_graph_pyx.pxd +34 -0
  151. sage/graphs/generic_graph_pyx.pyx +1626 -0
  152. sage/graphs/genus.cpython-39-aarch64-linux-gnu.so +0 -0
  153. sage/graphs/genus.pyx +623 -0
  154. sage/graphs/graph.py +9362 -0
  155. sage/graphs/graph_coloring.cpython-39-aarch64-linux-gnu.so +0 -0
  156. sage/graphs/graph_coloring.pyx +2284 -0
  157. sage/graphs/graph_database.py +1122 -0
  158. sage/graphs/graph_decompositions/all.py +1 -0
  159. sage/graphs/graph_decompositions/bandwidth.cpython-39-aarch64-linux-gnu.so +0 -0
  160. sage/graphs/graph_decompositions/bandwidth.pyx +428 -0
  161. sage/graphs/graph_decompositions/clique_separators.cpython-39-aarch64-linux-gnu.so +0 -0
  162. sage/graphs/graph_decompositions/clique_separators.pyx +595 -0
  163. sage/graphs/graph_decompositions/cutwidth.cpython-39-aarch64-linux-gnu.so +0 -0
  164. sage/graphs/graph_decompositions/cutwidth.pyx +753 -0
  165. sage/graphs/graph_decompositions/fast_digraph.cpython-39-aarch64-linux-gnu.so +0 -0
  166. sage/graphs/graph_decompositions/fast_digraph.pxd +13 -0
  167. sage/graphs/graph_decompositions/fast_digraph.pyx +212 -0
  168. sage/graphs/graph_decompositions/graph_products.cpython-39-aarch64-linux-gnu.so +0 -0
  169. sage/graphs/graph_decompositions/graph_products.pyx +462 -0
  170. sage/graphs/graph_decompositions/modular_decomposition.cpython-39-aarch64-linux-gnu.so +0 -0
  171. sage/graphs/graph_decompositions/modular_decomposition.pxd +27 -0
  172. sage/graphs/graph_decompositions/modular_decomposition.pyx +1536 -0
  173. sage/graphs/graph_decompositions/slice_decomposition.cpython-39-aarch64-linux-gnu.so +0 -0
  174. sage/graphs/graph_decompositions/slice_decomposition.pxd +18 -0
  175. sage/graphs/graph_decompositions/slice_decomposition.pyx +1080 -0
  176. sage/graphs/graph_decompositions/tree_decomposition.cpython-39-aarch64-linux-gnu.so +0 -0
  177. sage/graphs/graph_decompositions/tree_decomposition.pxd +17 -0
  178. sage/graphs/graph_decompositions/tree_decomposition.pyx +1996 -0
  179. sage/graphs/graph_decompositions/vertex_separation.cpython-39-aarch64-linux-gnu.so +0 -0
  180. sage/graphs/graph_decompositions/vertex_separation.pxd +5 -0
  181. sage/graphs/graph_decompositions/vertex_separation.pyx +1963 -0
  182. sage/graphs/graph_editor.py +82 -0
  183. sage/graphs/graph_generators.py +3301 -0
  184. sage/graphs/graph_generators_pyx.cpython-39-aarch64-linux-gnu.so +0 -0
  185. sage/graphs/graph_generators_pyx.pyx +95 -0
  186. sage/graphs/graph_input.py +812 -0
  187. sage/graphs/graph_latex.py +2064 -0
  188. sage/graphs/graph_list.py +367 -0
  189. sage/graphs/graph_plot.py +1749 -0
  190. sage/graphs/graph_plot_js.py +338 -0
  191. sage/graphs/hyperbolicity.cpython-39-aarch64-linux-gnu.so +0 -0
  192. sage/graphs/hyperbolicity.pyx +1702 -0
  193. sage/graphs/hypergraph_generators.py +364 -0
  194. sage/graphs/independent_sets.cpython-39-aarch64-linux-gnu.so +0 -0
  195. sage/graphs/independent_sets.pxd +13 -0
  196. sage/graphs/independent_sets.pyx +402 -0
  197. sage/graphs/isgci.py +1033 -0
  198. sage/graphs/isoperimetric_inequalities.cpython-39-aarch64-linux-gnu.so +0 -0
  199. sage/graphs/isoperimetric_inequalities.pyx +453 -0
  200. sage/graphs/line_graph.cpython-39-aarch64-linux-gnu.so +0 -0
  201. sage/graphs/line_graph.pyx +627 -0
  202. sage/graphs/lovasz_theta.py +77 -0
  203. sage/graphs/matching.py +1633 -0
  204. sage/graphs/matching_covered_graph.py +3566 -0
  205. sage/graphs/orientations.py +1504 -0
  206. sage/graphs/partial_cube.py +459 -0
  207. sage/graphs/path_enumeration.cpython-39-aarch64-linux-gnu.so +0 -0
  208. sage/graphs/path_enumeration.pyx +2040 -0
  209. sage/graphs/pq_trees.py +1129 -0
  210. sage/graphs/print_graphs.py +201 -0
  211. sage/graphs/schnyder.py +865 -0
  212. sage/graphs/spanning_tree.cpython-39-aarch64-linux-gnu.so +0 -0
  213. sage/graphs/spanning_tree.pyx +1457 -0
  214. sage/graphs/strongly_regular_db.cpython-39-aarch64-linux-gnu.so +0 -0
  215. sage/graphs/strongly_regular_db.pyx +3340 -0
  216. sage/graphs/traversals.cpython-39-aarch64-linux-gnu.so +0 -0
  217. sage/graphs/traversals.pxd +9 -0
  218. sage/graphs/traversals.pyx +1871 -0
  219. sage/graphs/trees.cpython-39-aarch64-linux-gnu.so +0 -0
  220. sage/graphs/trees.pxd +15 -0
  221. sage/graphs/trees.pyx +310 -0
  222. sage/graphs/tutte_polynomial.py +713 -0
  223. sage/graphs/views.cpython-39-aarch64-linux-gnu.so +0 -0
  224. sage/graphs/views.pyx +794 -0
  225. sage/graphs/weakly_chordal.cpython-39-aarch64-linux-gnu.so +0 -0
  226. sage/graphs/weakly_chordal.pyx +562 -0
  227. sage/groups/all__sagemath_graphs.py +1 -0
  228. sage/groups/perm_gps/all__sagemath_graphs.py +1 -0
  229. sage/groups/perm_gps/partn_ref/all__sagemath_graphs.py +1 -0
  230. sage/groups/perm_gps/partn_ref/refinement_graphs.cpython-39-aarch64-linux-gnu.so +0 -0
  231. sage/groups/perm_gps/partn_ref/refinement_graphs.pxd +38 -0
  232. sage/groups/perm_gps/partn_ref/refinement_graphs.pyx +1666 -0
  233. sage/knots/all.py +6 -0
  234. sage/knots/free_knotinfo_monoid.py +507 -0
  235. sage/knots/gauss_code.py +291 -0
  236. sage/knots/knot.py +682 -0
  237. sage/knots/knot_table.py +284 -0
  238. sage/knots/knotinfo.py +2880 -0
  239. sage/knots/link.py +4682 -0
  240. sage/sandpiles/all.py +13 -0
  241. sage/sandpiles/examples.py +225 -0
  242. sage/sandpiles/sandpile.py +6365 -0
  243. sage/topology/all.py +22 -0
  244. sage/topology/cell_complex.py +1214 -0
  245. sage/topology/cubical_complex.py +1977 -0
  246. sage/topology/delta_complex.py +1806 -0
  247. sage/topology/filtered_simplicial_complex.py +744 -0
  248. sage/topology/moment_angle_complex.py +823 -0
  249. sage/topology/simplicial_complex.py +5161 -0
  250. sage/topology/simplicial_complex_catalog.py +86 -0
  251. sage/topology/simplicial_complex_examples.py +1692 -0
  252. sage/topology/simplicial_complex_homset.py +205 -0
  253. sage/topology/simplicial_complex_morphism.py +836 -0
  254. sage/topology/simplicial_set.py +4102 -0
  255. sage/topology/simplicial_set_catalog.py +55 -0
  256. sage/topology/simplicial_set_constructions.py +2954 -0
  257. sage/topology/simplicial_set_examples.py +865 -0
  258. sage/topology/simplicial_set_morphism.py +1464 -0
@@ -0,0 +1,453 @@
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.graphs.base.static_sparse_graph cimport short_digraph, init_short_digraph, free_short_digraph
28
+ from sage.data_structures.binary_matrix cimport *
29
+ from sage.graphs.base.static_dense_graph cimport dense_graph_init
30
+
31
+ from sage.rings.infinity import Infinity
32
+ from sage.rings.rational_field import QQ
33
+
34
+
35
+ def cheeger_constant(g):
36
+ r"""
37
+ Return the cheeger constant of the graph.
38
+
39
+ The Cheeger constant of a graph `G = (V,E)` is the minimum of `|\partial S|
40
+ / |Vol(S)|` where `Vol(S)` is the sum of degrees of element in `S`,
41
+ `\partial S` is the edge boundary of `S` (number of edges with one end in
42
+ `S` and one end in `V \setminus S`) and the minimum is taken over all
43
+ non-empty subsets `S` of vertices so that `|Vol(S)| \leq |E|`.
44
+
45
+ .. SEEALSO::
46
+
47
+ Alternative but similar quantities can be obtained via the methods
48
+ :meth:`edge_isoperimetric_number` and :meth:`vertex_isoperimetric_number`.
49
+
50
+ EXAMPLES::
51
+
52
+ sage: graphs.PetersenGraph().cheeger_constant()
53
+ 1/3
54
+
55
+ The Cheeger constant of a cycle on `n` vertices is
56
+ `1/\lfloor n/2 \rfloor`::
57
+
58
+ sage: [graphs.CycleGraph(k).cheeger_constant() for k in range(2,10)]
59
+ [1, 1, 1/2, 1/2, 1/3, 1/3, 1/4, 1/4]
60
+
61
+ The Cheeger constant of a complete graph on `n` vertices is
62
+ `\lceil n/2 \rceil / (n-1)`::
63
+
64
+ sage: [graphs.CompleteGraph(k).cheeger_constant() for k in range(2,10)]
65
+ [1, 1, 2/3, 3/4, 3/5, 2/3, 4/7, 5/8]
66
+
67
+ For complete bipartite::
68
+
69
+ sage: [graphs.CompleteBipartiteGraph(i,j).cheeger_constant() for i in range(2,7) for j in range(2, i)]
70
+ [3/5, 1/2, 3/5, 5/9, 4/7, 5/9, 1/2, 5/9, 1/2, 5/9]
71
+
72
+ More examples::
73
+
74
+ sage: G = Graph([(0, 1), (0, 3), (0, 8), (1, 4), (1, 6), (2, 4), (2, 7), (2, 9),
75
+ ....: (3, 6), (3, 8), (4, 9), (5, 6), (5, 7), (5, 8), (7, 9)])
76
+ sage: G.cheeger_constant()
77
+ 1/6
78
+
79
+ sage: G = Graph([(0, 1), (0, 2), (1, 2), (1, 3), (1, 4), (1, 5), (2, 3), (3, 4), (3, 5)])
80
+ sage: G.cheeger_constant()
81
+ 1/2
82
+
83
+ sage: Graph([[1,2,3,4],[(1,2),(3,4)]]).cheeger_constant()
84
+ 0
85
+
86
+ TESTS::
87
+
88
+ sage: graphs.EmptyGraph().cheeger_constant()
89
+ Traceback (most recent call last):
90
+ ...
91
+ ValueError: Cheeger constant is not defined for the empty graph
92
+ """
93
+ if g.is_directed():
94
+ raise ValueError("Cheeger constant is only defined on non-oriented graph")
95
+ g._scream_if_not_simple()
96
+ if g.num_verts() == 0:
97
+ raise ValueError("Cheeger constant is not defined for the empty graph")
98
+ elif g.num_verts() == 1:
99
+ return Infinity
100
+ elif not g.is_connected():
101
+ return QQ((0, 1))
102
+
103
+ cdef short_digraph sd # a copy of the graph g
104
+ cdef int * subgraph # vertices of the subgraph (stack)
105
+ cdef int * bitsubgraph # vertices of the subgraph (bit array of +1 (in) or -1 (not in))
106
+ cdef int k = 0 # number of vertices in subgraph
107
+ cdef int vol = 0 # number of edges in the subgraph
108
+ cdef int boundary = 0 # number of edges in the boundary
109
+ cdef int u = 0 # current vertex
110
+ cdef unsigned long bmin = 1 # value of boundary for the min
111
+ cdef unsigned long vmin = 1 # value of the volume for the min
112
+ cdef int i
113
+
114
+ init_short_digraph(sd, g, edge_labelled=False, vertex_list=list(g))
115
+
116
+ subgraph = <int *> check_malloc(sd.n * sizeof(int))
117
+ bitsubgraph = <int *> check_malloc(sd.n * sizeof(int))
118
+
119
+ sig_on()
120
+ try:
121
+ for i in range(sd.n):
122
+ bitsubgraph[i] = -1
123
+ while True:
124
+ while True:
125
+ # add vertex u to the subgraph, update the boundary/volume
126
+ # we repeat the operation until we reach the maximum volume
127
+ # or have no more vertex available
128
+ for i in range(sd.neighbors[u+1] - sd.neighbors[u]):
129
+ boundary -= bitsubgraph[sd.neighbors[u][i]]
130
+ vol += 1
131
+
132
+ bitsubgraph[u] = 1
133
+ subgraph[k] = u
134
+ u += 1
135
+ k += 1
136
+
137
+ if vol > sd.m:
138
+ break
139
+
140
+ if boundary * vmin < bmin * vol:
141
+ bmin = boundary
142
+ vmin = vol
143
+
144
+ if u == sd.n:
145
+ break
146
+
147
+ # backtrack
148
+ k -= 1
149
+ u = subgraph[k]
150
+
151
+ bitsubgraph[u] = -1
152
+ for i in range(sd.neighbors[u+1] - sd.neighbors[u]):
153
+ boundary += bitsubgraph[sd.neighbors[u][i]]
154
+ vol -= 1
155
+ u += 1
156
+
157
+ if u == sd.n:
158
+ if k == 0:
159
+ # end of the loop
160
+ break
161
+ else:
162
+ # remove one more vertex in order to continue
163
+ k -= 1
164
+ u = subgraph[k]
165
+
166
+ bitsubgraph[u] = -1
167
+ for i in range(sd.neighbors[u+1] - sd.neighbors[u]):
168
+ boundary += bitsubgraph[sd.neighbors[u][i]]
169
+ vol -= 1
170
+ u += 1
171
+ return QQ((bmin, vmin))
172
+
173
+ finally:
174
+ free_short_digraph(sd)
175
+ sig_free(subgraph)
176
+ sig_free(bitsubgraph)
177
+ sig_off()
178
+
179
+
180
+ def edge_isoperimetric_number(g):
181
+ r"""
182
+ Return the edge-isoperimetric number of the graph.
183
+
184
+ The edge-isoperimetric number of a graph `G = (V,E)` is also sometimes
185
+ called the *isoperimetric number*. It is defined as the minimum of
186
+ `|\partial S| / |S|` where `\partial S` is the edge boundary of `S` (number
187
+ of edges with one end in `S` and one end in `V \setminus S`) and the
188
+ minimum is taken over all subsets of vertices whose cardinality does not
189
+ exceed half the size `|V|` of the graph.
190
+
191
+ .. SEEALSO::
192
+
193
+ Alternative but similar quantities can be obtained via the methods
194
+ :meth:`cheeger_constant` and :meth:`vertex_isoperimetric_number`.
195
+
196
+ EXAMPLES:
197
+
198
+ The edge-isoperimetric number of a complete graph on `n` vertices is
199
+ `\lceil n/2 \rceil`::
200
+
201
+ sage: [graphs.CompleteGraph(n).edge_isoperimetric_number() for n in range(2,10)]
202
+ [1, 2, 2, 3, 3, 4, 4, 5]
203
+
204
+ The edge-isoperimetric constant of a cycle on `n` vertices is
205
+ `2/\lfloor n/2 \rfloor`::
206
+
207
+ sage: [graphs.CycleGraph(n).edge_isoperimetric_number() for n in range(2,15)]
208
+ [1, 2, 1, 1, 2/3, 2/3, 1/2, 1/2, 2/5, 2/5, 1/3, 1/3, 2/7]
209
+
210
+ In general, for `d`-regular graphs the edge-isoperimetric number is
211
+ `d` times larger than the Cheeger constant of the graph::
212
+
213
+ sage: g = graphs.RandomRegular(3, 10) # needs networkx
214
+ sage: g.edge_isoperimetric_number() == g.cheeger_constant() * 3 # needs networkx
215
+ True
216
+
217
+ And the edge-isoperimetric constant of a disconnected graph is `0`::
218
+
219
+ sage: Graph([[1,2,3,4],[(1,2),(3,4)]]).edge_isoperimetric_number()
220
+ 0
221
+
222
+ TESTS::
223
+
224
+ sage: graphs.EmptyGraph().edge_isoperimetric_number()
225
+ Traceback (most recent call last):
226
+ ...
227
+ ValueError: edge-isoperimetric number not defined for the empty graph
228
+ """
229
+ if g.is_directed():
230
+ raise ValueError("edge isoperimetric number is only defined on non-oriented graph")
231
+ g._scream_if_not_simple()
232
+ if g.num_verts() == 0:
233
+ raise ValueError("edge-isoperimetric number not defined for the empty graph")
234
+ elif g.num_verts() == 1:
235
+ return Infinity
236
+ elif not g.is_connected():
237
+ return QQ((0, 1))
238
+
239
+ cdef short_digraph sd # a copy of the graph g
240
+ cdef int * subgraph # vertices of the subgraph (stack)
241
+ cdef int * bitsubgraph # vertices of the subgraph (bit array of +1 (in) or -1 (not in))
242
+ cdef int k = 0 # number of vertices in subgraph
243
+ cdef unsigned long vol = 0 # number of edges in the subgraph
244
+ cdef unsigned long boundary = 0 # number of edges in the boundary
245
+ cdef int u = 0 # current vertex
246
+ cdef int i
247
+
248
+ init_short_digraph(sd, g, edge_labelled=False, vertex_list=list(g))
249
+
250
+ cdef unsigned long bmin = sd.neighbors[1] - sd.neighbors[0] # value of boundary for the min
251
+ cdef unsigned long vmin = 1 # value of the volume for the min
252
+
253
+ subgraph = <int *> check_malloc(sd.n * sizeof(int))
254
+ bitsubgraph = <int *> check_malloc(sd.n * sizeof(int))
255
+
256
+ sig_on()
257
+ try:
258
+ for i in range(sd.n):
259
+ bitsubgraph[i] = -1
260
+
261
+ while True:
262
+ while True:
263
+ # add vertex u to the subgraph, update the boundary/volume
264
+ # we repeat the operation until we reach the maximum volume
265
+ # or have no more vertex available
266
+ for i in range(sd.neighbors[u+1] - sd.neighbors[u]):
267
+ boundary -= bitsubgraph[sd.neighbors[u][i]]
268
+ vol += 1
269
+
270
+ bitsubgraph[u] = 1
271
+ subgraph[k] = u
272
+ u += 1
273
+ k += 1
274
+
275
+ if 2*vol > sd.n:
276
+ break
277
+
278
+ if boundary * vmin < bmin * vol:
279
+ bmin = boundary
280
+ vmin = vol
281
+
282
+ if u == sd.n:
283
+ break
284
+
285
+ # backtrack
286
+ k -= 1
287
+ u = subgraph[k]
288
+
289
+ bitsubgraph[u] = -1
290
+ for i in range(sd.neighbors[u+1] - sd.neighbors[u]):
291
+ boundary += bitsubgraph[sd.neighbors[u][i]]
292
+ vol -= 1
293
+ u += 1
294
+
295
+ if u == sd.n:
296
+ if k == 0:
297
+ # end of the loop
298
+ break
299
+ else:
300
+ # remove one more vertex in order to continue
301
+ k -= 1
302
+ u = subgraph[k]
303
+
304
+ bitsubgraph[u] = -1
305
+ for i in range(sd.neighbors[u+1] - sd.neighbors[u]):
306
+ boundary += bitsubgraph[sd.neighbors[u][i]]
307
+ vol -= 1
308
+ u += 1
309
+
310
+ return QQ((bmin, vmin))
311
+
312
+ finally:
313
+ sig_off()
314
+ free_short_digraph(sd)
315
+ sig_free(subgraph)
316
+ sig_free(bitsubgraph)
317
+
318
+
319
+ def vertex_isoperimetric_number(g):
320
+ r"""
321
+ Return the vertex-isoperimetric number of the graph.
322
+
323
+ The vertex-isoperimetric number of a graph `G = (V,E)` is also sometimes
324
+ called the *magnifying constant*. It is defined as the minimum of `|N(S)| /
325
+ |S|` where `|N(S)|` is the vertex boundary of `S` and the minimum is taken
326
+ over the subsets `S` of vertices of size at most half of the vertices.
327
+
328
+ .. SEEALSO::
329
+
330
+ Alternative but similar quantities can be obtained via the methods
331
+ :meth:`cheeger_constant` and :meth:`edge_isoperimetric_number`.
332
+
333
+ EXAMPLES:
334
+
335
+ The vertex-isoperimetric number of a complete graph on `n` vertices is
336
+ `\lceil n/2 \rceil/\lfloor n/2 \rfloor`::
337
+
338
+ sage: [graphs.CompleteGraph(k).vertex_isoperimetric_number() for k in range(2,15)]
339
+ [1, 2, 1, 3/2, 1, 4/3, 1, 5/4, 1, 6/5, 1, 7/6, 1]
340
+
341
+ The vertex-isoperimetric number of a cycle on `n` vertices is
342
+ `2/\lfloor n/2 \rfloor`::
343
+
344
+ sage: [graphs.CycleGraph(k).vertex_isoperimetric_number() for k in range(2,15)]
345
+ [1, 2, 1, 1, 2/3, 2/3, 1/2, 1/2, 2/5, 2/5, 1/3, 1/3, 2/7]
346
+
347
+ And the vertex-isoperimetric number of a disconnected graph is `0`::
348
+
349
+ sage: Graph([[1,2,3],[(1,2)]]).vertex_isoperimetric_number()
350
+ 0
351
+
352
+ The vertex-isoperimetric number is independent of edge multiplicity::
353
+
354
+ sage: G = graphs.CycleGraph(6)
355
+ sage: G.vertex_isoperimetric_number()
356
+ 2/3
357
+ sage: G.allow_multiple_edges(True)
358
+ sage: G.add_edges(G.edges(sort=False))
359
+ sage: G.vertex_isoperimetric_number()
360
+ 2/3
361
+
362
+ TESTS::
363
+
364
+ sage: graphs.EmptyGraph().vertex_isoperimetric_number()
365
+ Traceback (most recent call last):
366
+ ...
367
+ ValueError: vertex-isoperimetric number not defined for the empty graph
368
+ """
369
+ if g.is_directed():
370
+ raise ValueError("vertex-isoperimetric number is only defined on non-oriented graph")
371
+ if not g:
372
+ raise ValueError("vertex-isoperimetric number not defined for the empty graph")
373
+ elif g.order() == 1:
374
+ return Infinity
375
+ elif not g.is_connected():
376
+ return QQ((0, 1))
377
+
378
+ # We convert the graph to a static dense graph
379
+ cdef binary_matrix_t DG
380
+ dense_graph_init(DG, g)
381
+ cdef int n = g.order()
382
+ cdef int k = n / 2 # maximum size of a subset
383
+
384
+ sig_on()
385
+
386
+ # We use a stack of bitsets. For that, we need 3 bitsets per level with at
387
+ # most n/2 + 1 levels, so 3 * (n / 2) + 3 bitsets. We also need another
388
+ # bitset that we create at the same time, so overall 3 * (n / 2) + 4 bitsets
389
+ cdef binary_matrix_t stack
390
+ binary_matrix_init(stack, 3 * (n / 2) + 4, n)
391
+
392
+ cdef bitset_t candidates = stack.rows[3 * (n / 2) + 3]
393
+ cdef bitset_t left # vertices not yet explored
394
+ cdef bitset_t current # vertices in the current subset
395
+ cdef bitset_t boundary # union of neighbors of vertices in current subset
396
+
397
+ cdef int level = 0
398
+ cdef int p = n
399
+ cdef int q = 0
400
+ cdef int c, b, v
401
+
402
+ # We initialize the first level
403
+ for v in range(3):
404
+ bitset_clear(stack.rows[v])
405
+ bitset_complement(stack.rows[0], stack.rows[0])
406
+
407
+ while level >= 0:
408
+
409
+ # We take the values at the top of the stack
410
+ left = stack.rows[level]
411
+ current = stack.rows[level + 1]
412
+ boundary = stack.rows[level + 2]
413
+
414
+ if bitset_isempty(current):
415
+ bitset_copy(candidates, left)
416
+ else:
417
+ bitset_and(candidates, left, boundary)
418
+
419
+ if bitset_isempty(candidates):
420
+ # We decrease l to pop the stack
421
+ level -= 3
422
+
423
+ # If the current set if non empty, we update the lower bound
424
+ c = bitset_len(current)
425
+ if c:
426
+ bitset_difference(boundary, boundary, current)
427
+ b = bitset_len(boundary)
428
+ if b * q < p * c:
429
+ p = b
430
+ q = c
431
+
432
+ else:
433
+ # Choose a candidate vertex v
434
+ v = bitset_first(candidates)
435
+ bitset_discard(left, v)
436
+
437
+ # Since we have not modified l, the bitsets for iterating without v
438
+ # in the subset current are now at the top of the stack, with
439
+ # correct values
440
+
441
+ if bitset_len(current) < k:
442
+ # We continue with v in the subset current
443
+ level += 3
444
+ bitset_copy(stack.rows[level], left)
445
+ bitset_copy(stack.rows[level + 1], current)
446
+ bitset_add(stack.rows[level + 1], v)
447
+ bitset_union(stack.rows[level + 2], boundary, DG.rows[v])
448
+
449
+ binary_matrix_free(stack)
450
+ binary_matrix_free(DG)
451
+ sig_off()
452
+
453
+ return QQ((p, q))