Skip to content

Commit 999faf4

Browse files
author
Release Manager
committed
gh-39223: avoid some conversions to `short_digraph` in `distances_all_pairs.pyx` Similarly to #39216, we avoid the conversion to `short_digraph` in `distances_all_pairs.pyx` when the input graph is an instance of `StaticSparseBackend`. ### 📝 Checklist <!-- Put an `x` in all the boxes that apply. --> - [x] The title is concise and informative. - [x] The description explains in detail what this PR is about. - [x] I have linked a relevant issue or discussion. - [x] I have created tests covering the changes. - [ ] I have updated the documentation and checked the documentation preview. ### ⌛ Dependencies <!-- List all open PRs that this PR logically depends on. For example, --> <!-- - #12345: short description why this is a dependency --> <!-- - #34567: ... --> URL: #39223 Reported by: David Coudert Reviewer(s): Frédéric Chapoton
2 parents 8612691 + d9677c0 commit 999faf4

File tree

1 file changed

+145
-27
lines changed

1 file changed

+145
-27
lines changed

src/sage/graphs/distances_all_pairs.pyx

+145-27
Original file line numberDiff line numberDiff line change
@@ -122,17 +122,18 @@ Functions
122122
# https://www.gnu.org/licenses/
123123
# ****************************************************************************
124124

125-
from sage.data_structures.binary_matrix cimport *
126125
from libc.string cimport memset
127126
from libc.stdint cimport uint64_t, UINT64_MAX
128127
from libc.stdint cimport uint32_t, INT32_MAX, UINT32_MAX
129128
from cysignals.memory cimport sig_malloc, sig_calloc, sig_free
130129
from cysignals.signals cimport sig_on, sig_off
131130
from memory_allocator cimport MemoryAllocator
132131

132+
from sage.data_structures.binary_matrix cimport *
133133
from sage.graphs.base.c_graph cimport CGraphBackend
134134
from sage.graphs.base.c_graph cimport CGraph
135-
135+
from sage.graphs.base.static_sparse_backend cimport StaticSparseCGraph
136+
from sage.graphs.base.static_sparse_backend cimport StaticSparseBackend
136137
from sage.graphs.base.static_sparse_graph cimport (short_digraph,
137138
init_short_digraph,
138139
init_reverse,
@@ -446,15 +447,15 @@ def distances_all_pairs(G):
446447
sage: g = graphs.PetersenGraph()
447448
sage: distances_all_pairs(g)
448449
{0: {0: 0, 1: 1, 2: 2, 3: 2, 4: 1, 5: 1, 6: 2, 7: 2, 8: 2, 9: 2},
449-
1: {0: 1, 1: 0, 2: 1, 3: 2, 4: 2, 5: 2, 6: 1, 7: 2, 8: 2, 9: 2},
450-
2: {0: 2, 1: 1, 2: 0, 3: 1, 4: 2, 5: 2, 6: 2, 7: 1, 8: 2, 9: 2},
451-
3: {0: 2, 1: 2, 2: 1, 3: 0, 4: 1, 5: 2, 6: 2, 7: 2, 8: 1, 9: 2},
452-
4: {0: 1, 1: 2, 2: 2, 3: 1, 4: 0, 5: 2, 6: 2, 7: 2, 8: 2, 9: 1},
453-
5: {0: 1, 1: 2, 2: 2, 3: 2, 4: 2, 5: 0, 6: 2, 7: 1, 8: 1, 9: 2},
454-
6: {0: 2, 1: 1, 2: 2, 3: 2, 4: 2, 5: 2, 6: 0, 7: 2, 8: 1, 9: 1},
455-
7: {0: 2, 1: 2, 2: 1, 3: 2, 4: 2, 5: 1, 6: 2, 7: 0, 8: 2, 9: 1},
456-
8: {0: 2, 1: 2, 2: 2, 3: 1, 4: 2, 5: 1, 6: 1, 7: 2, 8: 0, 9: 2},
457-
9: {0: 2, 1: 2, 2: 2, 3: 2, 4: 1, 5: 2, 6: 1, 7: 1, 8: 2, 9: 0}}
450+
1: {0: 1, 1: 0, 2: 1, 3: 2, 4: 2, 5: 2, 6: 1, 7: 2, 8: 2, 9: 2},
451+
2: {0: 2, 1: 1, 2: 0, 3: 1, 4: 2, 5: 2, 6: 2, 7: 1, 8: 2, 9: 2},
452+
3: {0: 2, 1: 2, 2: 1, 3: 0, 4: 1, 5: 2, 6: 2, 7: 2, 8: 1, 9: 2},
453+
4: {0: 1, 1: 2, 2: 2, 3: 1, 4: 0, 5: 2, 6: 2, 7: 2, 8: 2, 9: 1},
454+
5: {0: 1, 1: 2, 2: 2, 3: 2, 4: 2, 5: 0, 6: 2, 7: 1, 8: 1, 9: 2},
455+
6: {0: 2, 1: 1, 2: 2, 3: 2, 4: 2, 5: 2, 6: 0, 7: 2, 8: 1, 9: 1},
456+
7: {0: 2, 1: 2, 2: 1, 3: 2, 4: 2, 5: 1, 6: 2, 7: 0, 8: 2, 9: 1},
457+
8: {0: 2, 1: 2, 2: 2, 3: 1, 4: 2, 5: 1, 6: 1, 7: 2, 8: 0, 9: 2},
458+
9: {0: 2, 1: 2, 2: 2, 3: 2, 4: 1, 5: 2, 6: 1, 7: 1, 8: 2, 9: 0}}
458459
"""
459460
from sage.rings.infinity import Infinity
460461

@@ -1806,6 +1807,17 @@ def diameter(G, algorithm=None, source=None):
18061807
sage: G = graphs.PathGraph(1)
18071808
sage: diameter(G, algorithm='iFUB')
18081809
0
1810+
1811+
Immutable graphs::
1812+
1813+
sage: G = graphs.RandomGNP(10, .5)
1814+
sage: G._backend
1815+
<sage.graphs.base.sparse_graph.SparseGraphBackend ...>
1816+
sage: H = Graph(G, immutable=True)
1817+
sage: H._backend
1818+
<sage.graphs.base.static_sparse_backend.StaticSparseBackend ...>
1819+
sage: diameter(G, algorithm='iFUB') == diameter(H, algorithm='iFUB')
1820+
True
18091821
"""
18101822
cdef uint32_t n = G.order()
18111823
if n <= 1:
@@ -1832,9 +1844,16 @@ def diameter(G, algorithm=None, source=None):
18321844
# Copying the whole graph to obtain the list of neighbors quicker than by
18331845
# calling out_neighbors. This data structure is well documented in the
18341846
# module sage.graphs.base.static_sparse_graph
1835-
cdef list int_to_vertex = list(G)
1847+
cdef list int_to_vertex
1848+
cdef StaticSparseCGraph cg
18361849
cdef short_digraph sd
1837-
init_short_digraph(sd, G, edge_labelled=False, vertex_list=int_to_vertex)
1850+
if isinstance(G, StaticSparseBackend):
1851+
cg = <StaticSparseCGraph> G._cg
1852+
sd = <short_digraph> cg.g
1853+
int_to_vertex = cg._vertex_to_labels
1854+
else:
1855+
int_to_vertex = list(G)
1856+
init_short_digraph(sd, G, edge_labelled=False, vertex_list=int_to_vertex)
18381857
cdef short_digraph rev_sd # to store copy of sd with edges reversed
18391858

18401859
# and we map the source to an int in [0,n-1]
@@ -1849,7 +1868,8 @@ def diameter(G, algorithm=None, source=None):
18491868
bitset_init(seen, n)
18501869
tab = <uint32_t*> sig_malloc(2* n * sizeof(uint32_t))
18511870
if not tab:
1852-
free_short_digraph(sd)
1871+
if not isinstance(G, StaticSparseBackend):
1872+
free_short_digraph(sd)
18531873
bitset_free(seen)
18541874
raise MemoryError()
18551875

@@ -1875,7 +1895,8 @@ def diameter(G, algorithm=None, source=None):
18751895
else: # algorithm == 'iFUB'
18761896
LB = diameter_iFUB(sd, isource)
18771897

1878-
free_short_digraph(sd)
1898+
if not isinstance(G, StaticSparseBackend):
1899+
free_short_digraph(sd)
18791900

18801901
if LB < 0 or LB > n:
18811902
from sage.rings.infinity import Infinity
@@ -1926,6 +1947,17 @@ def radius_DHV(G):
19261947
Traceback (most recent call last):
19271948
...
19281949
TypeError: this method works for unweighted undirected graphs only
1950+
1951+
Immutable graphs::
1952+
1953+
sage: G = graphs.RandomGNP(10, .5)
1954+
sage: G._backend
1955+
<sage.graphs.base.sparse_graph.SparseGraphBackend ...>
1956+
sage: H = Graph(G, immutable=True)
1957+
sage: H._backend
1958+
<sage.graphs.base.static_sparse_backend.StaticSparseBackend ...>
1959+
sage: radius_DHV(G) == radius_DHV(H)
1960+
True
19291961
"""
19301962
if G.is_directed():
19311963
raise TypeError("this method works for unweighted undirected graphs only")
@@ -1934,9 +1966,16 @@ def radius_DHV(G):
19341966
if n <= 1:
19351967
return 0
19361968

1937-
cdef list int_to_vertex = list(G)
1969+
cdef list int_to_vertex
1970+
cdef StaticSparseCGraph cg
19381971
cdef short_digraph sd
1939-
init_short_digraph(sd, G, edge_labelled=False, vertex_list=int_to_vertex)
1972+
if isinstance(G, StaticSparseBackend):
1973+
cg = <StaticSparseCGraph> G._cg
1974+
sd = <short_digraph> cg.g
1975+
int_to_vertex = cg._vertex_to_labels
1976+
else:
1977+
int_to_vertex = list(G)
1978+
init_short_digraph(sd, G, edge_labelled=False, vertex_list=int_to_vertex)
19401979

19411980
cdef uint32_t source, ecc_source
19421981
cdef uint32_t antipode, ecc_antipode
@@ -1946,6 +1985,8 @@ def radius_DHV(G):
19461985
cdef MemoryAllocator mem = MemoryAllocator()
19471986
cdef uint32_t * distances = <uint32_t *>mem.malloc(3 * n * sizeof(uint32_t))
19481987
if not distances:
1988+
if not isinstance(G, StaticSparseBackend):
1989+
free_short_digraph(sd)
19491990
raise MemoryError()
19501991

19511992
cdef uint32_t * waiting_list = distances + n
@@ -1987,7 +2028,8 @@ def radius_DHV(G):
19872028
LB = ecc_lower_bound[v]
19882029
source = v # vertex with minimum eccentricity lower bound
19892030

1990-
free_short_digraph(sd)
2031+
if not isinstance(G, StaticSparseBackend):
2032+
free_short_digraph(sd)
19912033
bitset_free(seen)
19922034
if UB == UINT32_MAX:
19932035
from sage.rings.infinity import Infinity
@@ -2041,6 +2083,19 @@ def wiener_index(G):
20412083
Traceback (most recent call last):
20422084
...
20432085
ValueError: Wiener index is not defined for the empty graph
2086+
2087+
TESTS:
2088+
2089+
Immutable graphs::
2090+
2091+
sage: G = graphs.RandomGNP(10, .5)
2092+
sage: G._backend
2093+
<sage.graphs.base.sparse_graph.SparseGraphBackend ...>
2094+
sage: H = Graph(G, immutable=True)
2095+
sage: H._backend
2096+
<sage.graphs.base.static_sparse_backend.StaticSparseBackend ...>
2097+
sage: G.wiener_index() == H.wiener_index()
2098+
True
20442099
"""
20452100
if not G:
20462101
raise ValueError("Wiener index is not defined for the empty graph")
@@ -2052,8 +2107,13 @@ def wiener_index(G):
20522107
# Copying the whole graph to obtain the list of neighbors quicker than by
20532108
# calling out_neighbors. This data structure is well documented in the
20542109
# module sage.graphs.base.static_sparse_graph
2110+
cdef StaticSparseCGraph cg
20552111
cdef short_digraph sd
2056-
init_short_digraph(sd, G, edge_labelled=False, vertex_list=list(G))
2112+
if isinstance(G, StaticSparseBackend):
2113+
cg = <StaticSparseCGraph> G._cg
2114+
sd = <short_digraph> cg.g
2115+
else:
2116+
init_short_digraph(sd, G, edge_labelled=False, vertex_list=list(G))
20572117

20582118
# allocated some data structures
20592119
cdef bitset_t seen
@@ -2074,7 +2134,8 @@ def wiener_index(G):
20742134
for v in range(0 if G.is_directed() else (u + 1), n):
20752135
s += distances[v]
20762136

2077-
free_short_digraph(sd)
2137+
if not isinstance(G, StaticSparseBackend):
2138+
free_short_digraph(sd)
20782139
bitset_free(seen)
20792140

20802141
if s == UINT64_MAX:
@@ -2342,6 +2403,18 @@ def szeged_index(G, algorithm=None):
23422403
Traceback (most recent call last):
23432404
...
23442405
ValueError: the 'low' algorithm cannot be used on digraphs
2406+
2407+
Immutable graphs::
2408+
2409+
sage: G = graphs.RandomGNP(10, .3)
2410+
sage: G.add_edges(graphs.RandomTree(10).edges())
2411+
sage: G._backend
2412+
<sage.graphs.base.sparse_graph.SparseGraphBackend ...>
2413+
sage: H = Graph(G, immutable=True)
2414+
sage: H._backend
2415+
<sage.graphs.base.static_sparse_backend.StaticSparseBackend ...>
2416+
sage: szeged_index(G) == szeged_index(H)
2417+
True
23452418
"""
23462419
if not G.is_connected():
23472420
raise ValueError("the Szeged index is defined for connected graphs only")
@@ -2364,16 +2437,23 @@ def szeged_index(G, algorithm=None):
23642437
if G.order() <= 1:
23652438
return 0
23662439

2440+
cdef StaticSparseCGraph cg
23672441
cdef short_digraph sd
2368-
init_short_digraph(sd, G, edge_labelled=False, vertex_list=list(G))
2442+
if isinstance(G, StaticSparseBackend):
2443+
cg = <StaticSparseCGraph> G._cg
2444+
sd = <short_digraph> cg.g
2445+
else:
2446+
init_short_digraph(sd, G, edge_labelled=False, vertex_list=list(G))
2447+
23692448
cdef uint64_t s
23702449

23712450
if algorithm == "low":
23722451
s = c_szeged_index_low_memory(sd)
23732452
else:
23742453
s = c_szeged_index_high_memory(sd)
23752454

2376-
free_short_digraph(sd)
2455+
if not isinstance(G, StaticSparseBackend):
2456+
free_short_digraph(sd)
23772457
return s
23782458

23792459

@@ -2441,13 +2521,31 @@ def distances_distribution(G):
24412521
sage: D = digraphs.DeBruijn(2,3) # needs sage.combinat
24422522
sage: D.distances_distribution() # needs sage.combinat
24432523
{1: 1/4, 2: 11/28, 3: 5/14}
2524+
2525+
TESTS:
2526+
2527+
Immutable graphs::
2528+
2529+
sage: G = graphs.RandomGNP(10, .5)
2530+
sage: G._backend
2531+
<sage.graphs.base.sparse_graph.SparseGraphBackend ...>
2532+
sage: H = Graph(G, immutable=True)
2533+
sage: H._backend
2534+
<sage.graphs.base.static_sparse_backend.StaticSparseBackend ...>
2535+
sage: G.distances_distribution() == H.distances_distribution()
2536+
True
24442537
"""
24452538
cdef size_t n = G.order()
24462539
if n <= 1:
24472540
return {}
24482541

2542+
cdef StaticSparseCGraph cg
24492543
cdef short_digraph sd
2450-
init_short_digraph(sd, G, edge_labelled=False, vertex_list=list(G))
2544+
if isinstance(G, StaticSparseBackend):
2545+
cg = <StaticSparseCGraph> G._cg
2546+
sd = <short_digraph> cg.g
2547+
else:
2548+
init_short_digraph(sd, G, edge_labelled=False, vertex_list=list(G))
24512549

24522550
cdef MemoryAllocator mem = MemoryAllocator()
24532551
cdef uint32_t * distances = <uint32_t *> mem.allocarray(2 * n, sizeof(uint32_t))
@@ -2470,7 +2568,8 @@ def distances_distribution(G):
24702568
for v in range(n):
24712569
count[distances[v]] += 1
24722570

2473-
free_short_digraph(sd)
2571+
if not isinstance(G, StaticSparseBackend):
2572+
free_short_digraph(sd)
24742573
bitset_free(seen)
24752574

24762575
from sage.rings.infinity import Infinity
@@ -2554,6 +2653,17 @@ def antipodal_graph(G):
25542653
Antipodal graph of Graph on 1 vertex: Looped graph on 1 vertex
25552654
sage: antipodal_graph(Graph(2)).edges(sort=True, labels=False)
25562655
[(0, 1)]
2656+
2657+
Immutable graphs::
2658+
2659+
sage: G = graphs.RandomGNP(10, .5)
2660+
sage: G._backend
2661+
<sage.graphs.base.sparse_graph.SparseGraphBackend ...>
2662+
sage: H = Graph(G, immutable=True)
2663+
sage: H._backend
2664+
<sage.graphs.base.static_sparse_backend.StaticSparseBackend ...>
2665+
sage: antipodal_graph(G).is_isomorphic(antipodal_graph(H))
2666+
True
25572667
"""
25582668
if not G:
25592669
raise ValueError("the antipodal graph of the empty graph is not defined")
@@ -2577,9 +2687,16 @@ def antipodal_graph(G):
25772687
A.add_edges(itertools.product(c1, c2))
25782688
return A
25792689

2580-
cdef list int_to_vertex = list(G)
2690+
cdef list int_to_vertex
2691+
cdef StaticSparseCGraph cg
25812692
cdef short_digraph sd
2582-
init_short_digraph(sd, G, edge_labelled=False, vertex_list=int_to_vertex)
2693+
if isinstance(G, StaticSparseBackend):
2694+
cg = <StaticSparseCGraph> G._cg
2695+
sd = <short_digraph> cg.g
2696+
int_to_vertex = cg._vertex_to_labels
2697+
else:
2698+
int_to_vertex = list(G)
2699+
init_short_digraph(sd, G, edge_labelled=False, vertex_list=int_to_vertex)
25832700

25842701
cdef MemoryAllocator mem = MemoryAllocator()
25852702
cdef uint32_t * distances = <uint32_t *> mem.allocarray(2 * n, sizeof(uint32_t))
@@ -2607,7 +2724,8 @@ def antipodal_graph(G):
26072724
A.add_edge(u, int_to_vertex[vj])
26082725
j -= 1
26092726

2610-
free_short_digraph(sd)
2727+
if not isinstance(G, StaticSparseBackend):
2728+
free_short_digraph(sd)
26112729
bitset_free(seen)
26122730

26132731
A.add_vertices(G)

0 commit comments

Comments
 (0)