passagemath-graphs 10.5.43__cp312-cp312-macosx_14_0_arm64.whl → 10.6.1rc2__cp312-cp312-macosx_14_0_arm64.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (132) hide show
  1. {passagemath_graphs-10.5.43.dist-info → passagemath_graphs-10.6.1rc2.dist-info}/METADATA +5 -6
  2. {passagemath_graphs-10.5.43.dist-info → passagemath_graphs-10.6.1rc2.dist-info}/RECORD +132 -130
  3. sage/combinat/abstract_tree.py +188 -17
  4. sage/combinat/cluster_algebra_quiver/interact.py +1 -2
  5. sage/combinat/cluster_algebra_quiver/mutation_type.py +518 -519
  6. sage/combinat/cluster_algebra_quiver/quiver.py +233 -205
  7. sage/combinat/designs/covering_design.py +2 -6
  8. sage/combinat/designs/database.py +11 -10
  9. sage/combinat/designs/designs_pyx.cpython-312-darwin.so +0 -0
  10. sage/combinat/designs/designs_pyx.pyx +2 -2
  11. sage/combinat/designs/evenly_distributed_sets.cpython-312-darwin.so +0 -0
  12. sage/combinat/designs/evenly_distributed_sets.pyx +4 -4
  13. sage/combinat/designs/gen_quadrangles_with_spread.cpython-312-darwin.so +0 -0
  14. sage/combinat/designs/latin_squares.py +53 -20
  15. sage/combinat/designs/orthogonal_arrays.py +2 -1
  16. sage/combinat/designs/orthogonal_arrays_find_recursive.cpython-312-darwin.so +0 -0
  17. sage/combinat/designs/orthogonal_arrays_find_recursive.pyx +22 -21
  18. sage/combinat/designs/resolvable_bibd.py +191 -157
  19. sage/combinat/designs/subhypergraph_search.cpython-312-darwin.so +0 -0
  20. sage/combinat/designs/subhypergraph_search.pyx +4 -4
  21. sage/combinat/designs/twographs.py +2 -2
  22. sage/combinat/finite_state_machine.py +6 -6
  23. sage/combinat/posets/bubble_shuffle.py +247 -0
  24. sage/combinat/posets/d_complete.py +3 -3
  25. sage/combinat/posets/elements.py +3 -3
  26. sage/combinat/posets/hasse_cython.cpython-312-darwin.so +0 -0
  27. sage/combinat/posets/hasse_cython.pyx +1 -1
  28. sage/combinat/posets/hasse_diagram.py +16 -22
  29. sage/combinat/posets/hochschild_lattice.py +158 -0
  30. sage/combinat/posets/incidence_algebras.py +14 -16
  31. sage/combinat/posets/lattices.py +51 -53
  32. sage/combinat/posets/linear_extension_iterator.cpython-312-darwin.so +0 -0
  33. sage/combinat/posets/linear_extensions.py +10 -12
  34. sage/combinat/posets/moebius_algebra.py +4 -4
  35. sage/combinat/posets/poset_examples.py +70 -23
  36. sage/combinat/posets/posets.py +294 -103
  37. sage/databases/knotinfo_db.py +2 -1
  38. sage/graphs/asteroidal_triples.cpython-312-darwin.so +0 -0
  39. sage/graphs/asteroidal_triples.pyx +24 -3
  40. sage/graphs/base/boost_graph.cpython-312-darwin.so +0 -0
  41. sage/graphs/base/boost_graph.pxd +3 -3
  42. sage/graphs/base/c_graph.cpython-312-darwin.so +0 -0
  43. sage/graphs/base/c_graph.pyx +1 -1
  44. sage/graphs/base/dense_graph.cpython-312-darwin.so +0 -0
  45. sage/graphs/base/dense_graph.pxd +5 -3
  46. sage/graphs/base/dense_graph.pyx +44 -0
  47. sage/graphs/base/graph_backends.cpython-312-darwin.so +0 -0
  48. sage/graphs/base/sparse_graph.cpython-312-darwin.so +0 -0
  49. sage/graphs/base/static_dense_graph.cpython-312-darwin.so +0 -0
  50. sage/graphs/base/static_sparse_backend.cpython-312-darwin.so +0 -0
  51. sage/graphs/base/static_sparse_backend.pyx +8 -5
  52. sage/graphs/base/static_sparse_graph.cpython-312-darwin.so +0 -0
  53. sage/graphs/base/static_sparse_graph.pyx +86 -15
  54. sage/graphs/bipartite_graph.py +59 -36
  55. sage/graphs/centrality.cpython-312-darwin.so +0 -0
  56. sage/graphs/centrality.pyx +82 -9
  57. sage/graphs/cographs.py +1 -1
  58. sage/graphs/comparability.cpython-312-darwin.so +0 -0
  59. sage/graphs/comparability.pyx +64 -26
  60. sage/graphs/connectivity.cpython-312-darwin.so +0 -0
  61. sage/graphs/convexity_properties.cpython-312-darwin.so +0 -0
  62. sage/graphs/convexity_properties.pyx +52 -9
  63. sage/graphs/digraph.py +439 -95
  64. sage/graphs/digraph_generators.py +174 -102
  65. sage/graphs/distances_all_pairs.cpython-312-darwin.so +0 -0
  66. sage/graphs/dot2tex_utils.py +1 -1
  67. sage/graphs/edge_connectivity.cpython-312-darwin.so +0 -0
  68. sage/graphs/generators/basic.py +1 -1
  69. sage/graphs/generators/distance_regular.cpython-312-darwin.so +0 -0
  70. sage/graphs/generators/distance_regular.pyx +1 -1
  71. sage/graphs/generators/families.py +37 -27
  72. sage/graphs/generators/random.py +2 -2
  73. sage/graphs/generators/smallgraphs.py +3 -3
  74. sage/graphs/generic_graph.py +558 -86
  75. sage/graphs/generic_graph_pyx.cpython-312-darwin.so +0 -0
  76. sage/graphs/generic_graph_pyx.pyx +58 -11
  77. sage/graphs/genus.cpython-312-darwin.so +0 -0
  78. sage/graphs/genus.pyx +3 -4
  79. sage/graphs/graph.py +291 -8
  80. sage/graphs/graph_coloring.cpython-312-darwin.so +0 -0
  81. sage/graphs/graph_database.py +67 -12
  82. sage/graphs/graph_decompositions/bandwidth.cpython-312-darwin.so +0 -0
  83. sage/graphs/graph_decompositions/clique_separators.cpython-312-darwin.so +0 -0
  84. sage/graphs/graph_decompositions/clique_separators.pyx +24 -3
  85. sage/graphs/graph_decompositions/cutwidth.cpython-312-darwin.so +0 -0
  86. sage/graphs/graph_decompositions/fast_digraph.cpython-312-darwin.so +0 -0
  87. sage/graphs/graph_decompositions/fast_digraph.pyx +1 -1
  88. sage/graphs/graph_decompositions/graph_products.cpython-312-darwin.so +0 -0
  89. sage/graphs/graph_decompositions/graph_products.pyx +67 -21
  90. sage/graphs/graph_decompositions/modular_decomposition.cpython-312-darwin.so +0 -0
  91. sage/graphs/graph_decompositions/slice_decomposition.cpython-312-darwin.so +0 -0
  92. sage/graphs/graph_decompositions/slice_decomposition.pyx +34 -8
  93. sage/graphs/graph_decompositions/tree_decomposition.cpython-312-darwin.so +0 -0
  94. sage/graphs/graph_decompositions/vertex_separation.cpython-312-darwin.so +0 -0
  95. sage/graphs/graph_generators.py +45 -32
  96. sage/graphs/graph_generators_pyx.cpython-312-darwin.so +0 -0
  97. sage/graphs/graph_generators_pyx.pyx +15 -15
  98. sage/graphs/graph_latex.py +1 -1
  99. sage/graphs/graph_list.py +52 -9
  100. sage/graphs/graph_plot.py +7 -0
  101. sage/graphs/hyperbolicity.cpython-312-darwin.so +0 -0
  102. sage/graphs/hyperbolicity.pyx +2 -0
  103. sage/graphs/independent_sets.cpython-312-darwin.so +0 -0
  104. sage/graphs/isoperimetric_inequalities.cpython-312-darwin.so +0 -0
  105. sage/graphs/isoperimetric_inequalities.pyx +42 -6
  106. sage/graphs/line_graph.cpython-312-darwin.so +0 -0
  107. sage/graphs/line_graph.pyx +153 -37
  108. sage/graphs/matching_covered_graph.py +84 -60
  109. sage/graphs/orientations.py +3 -18
  110. sage/graphs/path_enumeration.cpython-312-darwin.so +0 -0
  111. sage/graphs/path_enumeration.pyx +2 -2
  112. sage/graphs/spanning_tree.cpython-312-darwin.so +0 -0
  113. sage/graphs/strongly_regular_db.cpython-312-darwin.so +0 -0
  114. sage/graphs/strongly_regular_db.pyx +15 -15
  115. sage/graphs/traversals.cpython-312-darwin.so +0 -0
  116. sage/graphs/traversals.pyx +13 -12
  117. sage/graphs/trees.cpython-312-darwin.so +0 -0
  118. sage/graphs/tutte_polynomial.py +1 -1
  119. sage/graphs/views.cpython-312-darwin.so +0 -0
  120. sage/graphs/weakly_chordal.cpython-312-darwin.so +0 -0
  121. sage/graphs/weakly_chordal.pyx +50 -8
  122. sage/groups/perm_gps/partn_ref/refinement_graphs.cpython-312-darwin.so +0 -0
  123. sage/knots/free_knotinfo_monoid.py +3 -3
  124. sage/knots/knotinfo.py +102 -82
  125. sage/knots/link.py +72 -39
  126. sage/topology/cubical_complex.py +4 -5
  127. sage/topology/delta_complex.py +4 -4
  128. sage/topology/simplicial_complex.py +0 -1
  129. sage/topology/simplicial_complex_catalog.py +6 -0
  130. sage/topology/simplicial_complex_examples.py +4 -16
  131. {passagemath_graphs-10.5.43.dist-info → passagemath_graphs-10.6.1rc2.dist-info}/WHEEL +0 -0
  132. {passagemath_graphs-10.5.43.dist-info → passagemath_graphs-10.6.1rc2.dist-info}/top_level.txt +0 -0
@@ -24,6 +24,8 @@ from cysignals.signals cimport sig_check
24
24
  from memory_allocator cimport MemoryAllocator
25
25
 
26
26
  from sage.data_structures.bitset_base cimport *
27
+ from sage.graphs.base.static_sparse_backend cimport StaticSparseCGraph
28
+ from sage.graphs.base.static_sparse_backend cimport StaticSparseBackend
27
29
  from sage.graphs.base.static_sparse_graph cimport *
28
30
  from sage.libs.gmp.mpq cimport *
29
31
  from sage.rings.rational cimport Rational
@@ -116,6 +118,19 @@ def centrality_betweenness(G, bint exact=False, bint normalize=True):
116
118
  {0: 0.0, 1: 0.0}
117
119
  sage: centrality_betweenness(Graph(2), exact=1)
118
120
  {0: 0, 1: 0}
121
+
122
+ The method is valid for immutable graphs::
123
+
124
+ sage: G = graphs.RandomGNP(10, .7)
125
+ sage: G._backend
126
+ <sage.graphs.base.sparse_graph.SparseGraphBackend ...>
127
+ sage: H = Graph(G, immutable=True)
128
+ sage: H._backend
129
+ <sage.graphs.base.static_sparse_backend.StaticSparseBackend ...>
130
+ sage: G.centrality_betweenness() == H.centrality_betweenness()
131
+ True
132
+ sage: G.centrality_betweenness(exact=True) == H.centrality_betweenness(exact=True)
133
+ True
119
134
  """
120
135
  if exact:
121
136
  return centrality_betweenness_C(G, <mpq_t> 0, normalize=normalize)
@@ -147,12 +162,13 @@ cdef dict centrality_betweenness_C(G, numerical_type _, bint normalize=True):
147
162
  return {v: zero for v in G}
148
163
 
149
164
  # A copy of G, for faster neighbor enumeration
165
+ cdef StaticSparseCGraph cg
150
166
  cdef short_digraph g
151
167
 
152
168
  # A second copy, to remember the edges used during the BFS (see doc)
153
169
  cdef short_digraph bfs_dag
154
170
 
155
- cdef list int_to_vertex = list(G)
171
+ cdef list int_to_vertex
156
172
 
157
173
  cdef int n = G.order()
158
174
 
@@ -179,7 +195,14 @@ cdef dict centrality_betweenness_C(G, numerical_type _, bint normalize=True):
179
195
  mpq_init(mpq_tmp)
180
196
 
181
197
  try:
182
- init_short_digraph(g, G, edge_labelled=False, vertex_list=int_to_vertex)
198
+ if isinstance(G, StaticSparseBackend):
199
+ cg = <StaticSparseCGraph> G._cg
200
+ g = <short_digraph> cg.g
201
+ int_to_vertex = cg._vertex_to_labels
202
+ else:
203
+ int_to_vertex = list(G)
204
+ init_short_digraph(g, G, edge_labelled=False, vertex_list=int_to_vertex)
205
+
183
206
  init_reverse(bfs_dag, g)
184
207
 
185
208
  queue = <uint32_t*> check_allocarray(n, sizeof(uint32_t))
@@ -305,7 +328,8 @@ cdef dict centrality_betweenness_C(G, numerical_type _, bint normalize=True):
305
328
  mpq_clear(mpq_tmp)
306
329
 
307
330
  finally:
308
- free_short_digraph(g)
331
+ if not isinstance(G, StaticSparseBackend):
332
+ free_short_digraph(g)
309
333
  free_short_digraph(bfs_dag)
310
334
  bitset_free(seen)
311
335
  bitset_free(next_layer)
@@ -459,6 +483,8 @@ cdef void _estimate_reachable_vertices_dir(short_digraph g, int* reachL, int* re
459
483
  reachL[i] = reachL_scc[scc[i]]
460
484
  reachU[i] = min(<int>reachU_scc[scc[i]], g.n)
461
485
 
486
+ free_short_digraph(sccgraph)
487
+
462
488
 
463
489
  cdef void _compute_reachable_vertices_undir(short_digraph g, int* reachable) noexcept:
464
490
  r"""
@@ -668,6 +694,19 @@ def centrality_closeness_top_k(G, int k=1, int verbose=0):
668
694
  True
669
695
  sage: all(abs(topk[i][0] - sorted_centr[i]) < 1e-12 for i in range(len(topk)))
670
696
  True
697
+
698
+ Immutable graphs::
699
+
700
+ sage: from sage.graphs.centrality import centrality_closeness_top_k
701
+ sage: G = graphs.RandomGNP(10, .7)
702
+ sage: G._backend
703
+ <sage.graphs.base.sparse_graph.SparseGraphBackend ...>
704
+ sage: H = Graph(G, immutable=True)
705
+ sage: H._backend
706
+ <sage.graphs.base.static_sparse_backend.StaticSparseBackend ...>
707
+ sage: k = randint(1, 10)
708
+ sage: centrality_closeness_top_k(G, k) == centrality_closeness_top_k(H, k)
709
+ True
671
710
  """
672
711
  cdef list res
673
712
  if k >= G.order():
@@ -685,12 +724,19 @@ def centrality_closeness_top_k(G, int k=1, int verbose=0):
685
724
  return []
686
725
 
687
726
  cdef MemoryAllocator mem = MemoryAllocator()
727
+ cdef StaticSparseCGraph cg
688
728
  cdef short_digraph sd
689
729
  # Copying the whole graph to obtain the list of neighbors quicker than by
690
730
  # calling out_neighbors. This data structure is well documented in the
691
731
  # module sage.graphs.base.static_sparse_graph
692
- cdef list V = list(G)
693
- init_short_digraph(sd, G, edge_labelled=False, vertex_list=V)
732
+ cdef list V
733
+ if isinstance(G, StaticSparseBackend):
734
+ cg = <StaticSparseCGraph> G._cg
735
+ sd = <short_digraph> cg.g
736
+ V = cg._vertex_to_labels
737
+ else:
738
+ V = list(G)
739
+ init_short_digraph(sd, G, edge_labelled=False, vertex_list=V)
694
740
  cdef int n = sd.n
695
741
  cdef int* reachL = <int*> mem.malloc(n * sizeof(int))
696
742
  cdef int* reachU
@@ -825,6 +871,9 @@ def centrality_closeness_top_k(G, int k=1, int verbose=0):
825
871
  if verbose > 0:
826
872
  print("Final performance ratio: {}".format(visited / (n * <double> (sd.neighbors[sd.n] - sd.edges))))
827
873
 
874
+ if not isinstance(G, StaticSparseBackend):
875
+ free_short_digraph(sd)
876
+
828
877
  res = [(1.0 / farness[v], V[v]) for v in topk[:k] if v != -1]
829
878
  try:
830
879
  res = sorted(res, reverse=True)
@@ -885,6 +934,18 @@ def centrality_closeness_random_k(G, int k=1):
885
934
  Traceback (most recent call last):
886
935
  ...
887
936
  ValueError: G must be an undirected Graph
937
+
938
+ The method is valid for immutable graphs::
939
+
940
+ sage: from sage.graphs.centrality import centrality_closeness_random_k
941
+ sage: G = graphs.RandomGNP(10, .7)
942
+ sage: G._backend
943
+ <sage.graphs.base.sparse_graph.SparseGraphBackend ...>
944
+ sage: H = Graph(G, immutable=True)
945
+ sage: H._backend
946
+ <sage.graphs.base.static_sparse_backend.StaticSparseBackend ...>
947
+ sage: centrality_closeness_random_k(G, 10) == centrality_closeness_random_k(H, 10)
948
+ True
888
949
  """
889
950
  G._scream_if_not_simple()
890
951
  if G.is_directed():
@@ -906,13 +967,21 @@ def centrality_closeness_random_k(G, int k=1):
906
967
  cdef double* partial_farness = <double*> mem.malloc(n * sizeof(double))
907
968
  cdef uint32_t* distance
908
969
  cdef uint32_t* waiting_list
970
+ cdef StaticSparseCGraph cg
909
971
  cdef short_digraph sd
910
972
  cdef bitset_t seen
911
973
  cdef double farness
912
974
  cdef int i, j
913
975
  cdef dict closeness_centrality_array = {}
914
- cdef list int_to_vertex = list(G)
915
- cdef dict vertex_to_int = {v: i for i, v in enumerate(int_to_vertex)}
976
+ cdef list int_to_vertex
977
+ cdef dict vertex_to_int
978
+ if isinstance(G, StaticSparseBackend):
979
+ cg = <StaticSparseCGraph> G._cg
980
+ int_to_vertex = cg._vertex_to_labels
981
+ vertex_to_int = cg._vertex_to_int
982
+ else:
983
+ int_to_vertex = list(G)
984
+ vertex_to_int = {v: i for i, v in enumerate(int_to_vertex)}
916
985
 
917
986
  # Initialize
918
987
  for i in range(n):
@@ -940,7 +1009,10 @@ def centrality_closeness_random_k(G, int k=1):
940
1009
  # Copying the whole graph as a static_sparse_graph for fast shortest
941
1010
  # paths computation in unweighted graph. This data structure is well
942
1011
  # documented in module sage.graphs.base.static_sparse_graph
943
- init_short_digraph(sd, G, edge_labelled=False, vertex_list=int_to_vertex)
1012
+ if isinstance(G, StaticSparseBackend):
1013
+ sd = <short_digraph> cg.g
1014
+ else:
1015
+ init_short_digraph(sd, G, edge_labelled=False, vertex_list=int_to_vertex)
944
1016
  distance = <uint32_t*> mem.malloc(n * sizeof(uint32_t))
945
1017
  waiting_list = <uint32_t*> mem.malloc(n * sizeof(uint32_t))
946
1018
  bitset_init(seen, n)
@@ -956,7 +1028,8 @@ def centrality_closeness_random_k(G, int k=1):
956
1028
  closeness_centrality_array[int_to_vertex[V[i]]] = (n - 1) / farness
957
1029
 
958
1030
  bitset_free(seen)
959
- free_short_digraph(sd)
1031
+ if not isinstance(G, StaticSparseBackend):
1032
+ free_short_digraph(sd)
960
1033
 
961
1034
  # Estimate the closeness centrality for remaining n-k vertices.
962
1035
  for i in range(k, n):
sage/graphs/cographs.py CHANGED
@@ -399,7 +399,7 @@ def change_label(tree, status, counter):
399
399
 
400
400
  - ``tree`` -- the tree to relabel
401
401
 
402
- - ``status`` -- boolean; used to to detect series (``True``) and parallel
402
+ - ``status`` -- boolean; used to detect series (``True``) and parallel
403
403
  (``False``) internal nodes
404
404
 
405
405
  - ``counter`` -- list; the first integer of the list is used to assign a
@@ -200,8 +200,18 @@ Methods
200
200
  # https://www.gnu.org/licenses/
201
201
  # ****************************************************************************
202
202
 
203
- from cysignals.memory cimport sig_free
204
- from sage.graphs.distances_all_pairs cimport c_distances_all_pairs
203
+ from libc.stdint cimport uint32_t
204
+ from memory_allocator cimport MemoryAllocator
205
+
206
+ from sage.data_structures.bitset_base cimport *
207
+ from sage.graphs.base.static_sparse_backend cimport StaticSparseCGraph
208
+ from sage.graphs.base.static_sparse_backend cimport StaticSparseBackend
209
+ from sage.graphs.base.static_sparse_graph cimport (short_digraph,
210
+ init_short_digraph,
211
+ free_short_digraph,
212
+ simple_BFS,
213
+ out_degree)
214
+
205
215
  from copy import copy
206
216
 
207
217
 
@@ -748,14 +758,17 @@ def is_permutation(g, algorithm='greedy', certificate=False, check=True,
748
758
 
749
759
  def is_transitive(g, certificate=False):
750
760
  r"""
751
- Test whether the digraph is transitive.
761
+ Check whether the digraph is transitive.
752
762
 
753
763
  A digraph is transitive if for any pair of vertices `u,v\in G` linked by a
754
764
  `uv`-path the edge `uv` belongs to `G`.
755
765
 
756
766
  INPUT:
757
767
 
758
- - ``certificate`` -- whether to return a certificate for negative answers
768
+ - ``g`` -- a digraph
769
+
770
+ - ``certificate`` -- boolean (default: ``False``); whether to return a
771
+ certificate for negative answers
759
772
 
760
773
  - If ``certificate = False`` (default), this method returns ``True`` or
761
774
  ``False`` according to the graph.
@@ -784,30 +797,55 @@ def is_transitive(g, certificate=False):
784
797
  True
785
798
  """
786
799
  cdef int n = g.order()
787
-
788
800
  if n <= 2:
789
801
  return True
790
802
 
791
- cdef list int_to_vertex = list(g)
792
- cdef unsigned short * distances = c_distances_all_pairs(g, vertex_list=int_to_vertex)
793
- cdef unsigned short * c_distances = distances
794
-
795
- cdef int i, j
796
-
797
- # Only 3 distances can appear in the matrix of all distances : 0, 1, and
798
- # infinity. Anything else is a proof of nontransitivity !
799
-
800
- for j in range(n):
801
- for i in range(n):
802
- if c_distances[i] != <unsigned short> -1 and c_distances[i] > 1:
803
- sig_free(distances)
804
- if certificate:
805
-
806
- return int_to_vertex[j], int_to_vertex[i]
807
- else:
808
- return False
809
-
810
- c_distances += n
803
+ # Copying the whole graph to obtain the list of neighbors quicker than by
804
+ # calling out_neighbors. This data structure is well documented in the
805
+ # module sage.graphs.base.static_sparse_graph
806
+ cdef list int_to_vertex
807
+ cdef StaticSparseCGraph cg
808
+ cdef short_digraph sd
809
+ if isinstance(g, StaticSparseBackend):
810
+ cg = <StaticSparseCGraph> g._cg
811
+ sd = <short_digraph> cg.g
812
+ int_to_vertex = cg._vertex_to_labels
813
+ else:
814
+ int_to_vertex = list(g)
815
+ init_short_digraph(sd, g, edge_labelled=False, vertex_list=int_to_vertex)
816
+
817
+ cdef MemoryAllocator mem = MemoryAllocator()
818
+ cdef uint32_t * distances = <uint32_t *> mem.malloc(n * sizeof(uint32_t))
819
+ cdef uint32_t * waiting_list = <uint32_t *> mem.malloc(n * sizeof(uint32_t))
820
+ cdef bitset_t seen
821
+ bitset_init(seen, n)
822
+
823
+ cdef uint32_t u, v
824
+ cdef int i
825
+
826
+ for u in range(n):
827
+
828
+ # 1. perform a breadth first search from u
829
+ _ = simple_BFS(sd, u, distances, NULL, waiting_list, seen)
830
+
831
+ # 2. Check whether the BFS reaches vertices that are not in the closed
832
+ # neighborhood of u.
833
+ if bitset_len(seen) != out_degree(sd, u) + 1:
834
+ if certificate:
835
+ bitset_discard(seen, u)
836
+ for i in range(out_degree(sd, u)):
837
+ bitset_discard(seen, sd.neighbors[u][i])
838
+ v = bitset_first(seen)
839
+
840
+ bitset_free(seen)
841
+ if not isinstance(g, StaticSparseBackend):
842
+ free_short_digraph(sd)
843
+ if certificate:
844
+ return (int_to_vertex[u], int_to_vertex[v])
845
+ return False
846
+
847
+ bitset_free(seen)
848
+ if not isinstance(g, StaticSparseBackend):
849
+ free_short_digraph(sd)
811
850
 
812
- sig_free(distances)
813
851
  return True
@@ -41,6 +41,8 @@ from sage.graphs.distances_all_pairs cimport c_distances_all_pairs
41
41
  from cysignals.memory cimport sig_free
42
42
  from memory_allocator cimport MemoryAllocator
43
43
  from libc.stdint cimport uint32_t
44
+ from sage.graphs.base.static_sparse_backend cimport StaticSparseCGraph
45
+ from sage.graphs.base.static_sparse_backend cimport StaticSparseBackend
44
46
  from sage.graphs.base.static_sparse_graph cimport (short_digraph,
45
47
  init_short_digraph,
46
48
  free_short_digraph,
@@ -573,6 +575,17 @@ def geodetic_closure(G, S):
573
575
  Traceback (most recent call last):
574
576
  ...
575
577
  NotImplementedError: the geodetic closure of digraphs has not been implemented yet
578
+
579
+ The method is valid for immutable graphs::
580
+
581
+ sage: G = graphs.RandomGNP(10, .7)
582
+ sage: G._backend
583
+ <sage.graphs.base.sparse_graph.SparseGraphBackend ...>
584
+ sage: H = Graph(G, immutable=True)
585
+ sage: H._backend
586
+ <sage.graphs.base.static_sparse_backend.StaticSparseBackend ...>
587
+ sage: geodetic_closure(G, [0, 3]) == geodetic_closure(H, [0, 3])
588
+ True
576
589
  """
577
590
  if G.is_directed():
578
591
  raise NotImplementedError("the geodetic closure of digraphs has not been implemented yet")
@@ -592,13 +605,23 @@ def geodetic_closure(G, S):
592
605
 
593
606
  cdef int n = G.order()
594
607
  cdef int nS = len(S)
595
- cdef list int_to_vertex = list(G)
596
- cdef dict vertex_to_int = {u: i for i, u in enumerate(int_to_vertex)}
597
- cdef list S_int = [vertex_to_int[u] for u in S]
608
+ cdef list int_to_vertex
609
+ cdef dict vertex_to_int
598
610
 
599
611
  # Copy the graph as a short digraph
612
+ cdef StaticSparseCGraph cg
600
613
  cdef short_digraph sd
601
- init_short_digraph(sd, G, edge_labelled=False, vertex_list=int_to_vertex)
614
+ if isinstance(G, StaticSparseBackend):
615
+ cg = <StaticSparseCGraph> G._cg
616
+ sd = <short_digraph> cg.g
617
+ int_to_vertex = cg._vertex_to_labels
618
+ vertex_to_int = cg._vertex_to_int
619
+ else:
620
+ int_to_vertex = list(G)
621
+ vertex_to_int = {u: i for i, u in enumerate(int_to_vertex)}
622
+ init_short_digraph(sd, G, edge_labelled=False, vertex_list=int_to_vertex)
623
+
624
+ cdef list S_int = [vertex_to_int[u] for u in S]
602
625
 
603
626
  # Allocate some data structures
604
627
  cdef MemoryAllocator mem = MemoryAllocator()
@@ -669,7 +692,8 @@ def geodetic_closure(G, S):
669
692
  bitset_free(seen)
670
693
  bitset_free(visited)
671
694
  bitset_free(closure)
672
- free_short_digraph(sd)
695
+ if not isinstance(G, StaticSparseBackend):
696
+ free_short_digraph(sd)
673
697
 
674
698
  return ret
675
699
 
@@ -746,6 +770,17 @@ def is_geodetic(G):
746
770
  sage: G.add_edge(G.random_edge())
747
771
  sage: G.is_geodetic()
748
772
  False
773
+
774
+ The method is valid for immutable graphs::
775
+
776
+ sage: G = graphs.RandomGNP(10, .7)
777
+ sage: G._backend
778
+ <sage.graphs.base.sparse_graph.SparseGraphBackend ...>
779
+ sage: H = Graph(G, immutable=True)
780
+ sage: H._backend
781
+ <sage.graphs.base.static_sparse_backend.StaticSparseBackend ...>
782
+ sage: G.is_geodetic() == H.is_geodetic()
783
+ True
749
784
  """
750
785
  if G.has_multiple_edges():
751
786
  return False
@@ -755,15 +790,21 @@ def is_geodetic(G):
755
790
 
756
791
  # Copy the graph as a short digraph
757
792
  cdef int n = G.order()
793
+ cdef StaticSparseCGraph cg
758
794
  cdef short_digraph sd
759
- init_short_digraph(sd, G, edge_labelled=False, vertex_list=list(G))
795
+ if isinstance(G, StaticSparseBackend):
796
+ cg = <StaticSparseCGraph> G._cg
797
+ sd = <short_digraph> cg.g
798
+ else:
799
+ init_short_digraph(sd, G, edge_labelled=False, vertex_list=list(G))
760
800
 
761
801
  # Allocate some data structures
762
802
  cdef MemoryAllocator mem = MemoryAllocator()
763
803
  cdef uint32_t * distances = <uint32_t *> mem.malloc(n * sizeof(uint32_t))
764
804
  cdef uint32_t * waiting_list = <uint32_t *> mem.malloc(n * sizeof(uint32_t))
765
805
  if not distances or not waiting_list:
766
- free_short_digraph(sd)
806
+ if not isinstance(G, StaticSparseBackend):
807
+ free_short_digraph(sd)
767
808
  raise MemoryError()
768
809
  cdef bitset_t seen
769
810
  bitset_init(seen, n)
@@ -812,7 +853,8 @@ def is_geodetic(G):
812
853
  elif distances[u] == distances[v] + 1:
813
854
  # G is not geodetic
814
855
  bitset_free(seen)
815
- free_short_digraph(sd)
856
+ if not isinstance(G, StaticSparseBackend):
857
+ free_short_digraph(sd)
816
858
  return False
817
859
 
818
860
  p_tmp += 1
@@ -821,7 +863,8 @@ def is_geodetic(G):
821
863
  waiting_beginning += 1
822
864
 
823
865
  bitset_free(seen)
824
- free_short_digraph(sd)
866
+ if not isinstance(G, StaticSparseBackend):
867
+ free_short_digraph(sd)
825
868
 
826
869
  # The graph is geodetic
827
870
  return True