@@ -122,17 +122,18 @@ Functions
122
122
# https://www.gnu.org/licenses/
123
123
# ****************************************************************************
124
124
125
- from sage.data_structures.binary_matrix cimport *
126
125
from libc.string cimport memset
127
126
from libc.stdint cimport uint64_t, UINT64_MAX
128
127
from libc.stdint cimport uint32_t, INT32_MAX, UINT32_MAX
129
128
from cysignals.memory cimport sig_malloc, sig_calloc, sig_free
130
129
from cysignals.signals cimport sig_on, sig_off
131
130
from memory_allocator cimport MemoryAllocator
132
131
132
+ from sage.data_structures.binary_matrix cimport *
133
133
from sage.graphs.base.c_graph cimport CGraphBackend
134
134
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
136
137
from sage.graphs.base.static_sparse_graph cimport (short_digraph,
137
138
init_short_digraph,
138
139
init_reverse,
@@ -446,15 +447,15 @@ def distances_all_pairs(G):
446
447
sage: g = graphs. PetersenGraph( )
447
448
sage: distances_all_pairs( g)
448
449
{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}}
458
459
"""
459
460
from sage.rings.infinity import Infinity
460
461
@@ -1806,6 +1807,17 @@ def diameter(G, algorithm=None, source=None):
1806
1807
sage: G = graphs. PathGraph( 1)
1807
1808
sage: diameter( G, algorithm='iFUB')
1808
1809
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
1809
1821
"""
1810
1822
cdef uint32_t n = G.order()
1811
1823
if n <= 1 :
@@ -1832,9 +1844,16 @@ def diameter(G, algorithm=None, source=None):
1832
1844
# Copying the whole graph to obtain the list of neighbors quicker than by
1833
1845
# calling out_neighbors. This data structure is well documented in the
1834
1846
# 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
1836
1849
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)
1838
1857
cdef short_digraph rev_sd # to store copy of sd with edges reversed
1839
1858
1840
1859
# and we map the source to an int in [0,n-1]
@@ -1849,7 +1868,8 @@ def diameter(G, algorithm=None, source=None):
1849
1868
bitset_init(seen, n)
1850
1869
tab = < uint32_t* > sig_malloc(2 * n * sizeof(uint32_t))
1851
1870
if not tab:
1852
- free_short_digraph(sd)
1871
+ if not isinstance (G, StaticSparseBackend):
1872
+ free_short_digraph(sd)
1853
1873
bitset_free(seen)
1854
1874
raise MemoryError ()
1855
1875
@@ -1875,7 +1895,8 @@ def diameter(G, algorithm=None, source=None):
1875
1895
else : # algorithm == 'iFUB'
1876
1896
LB = diameter_iFUB(sd, isource)
1877
1897
1878
- free_short_digraph(sd)
1898
+ if not isinstance (G, StaticSparseBackend):
1899
+ free_short_digraph(sd)
1879
1900
1880
1901
if LB < 0 or LB > n:
1881
1902
from sage.rings.infinity import Infinity
@@ -1926,6 +1947,17 @@ def radius_DHV(G):
1926
1947
Traceback ( most recent call last) :
1927
1948
...
1928
1949
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
1929
1961
"""
1930
1962
if G.is_directed():
1931
1963
raise TypeError (" this method works for unweighted undirected graphs only" )
@@ -1934,9 +1966,16 @@ def radius_DHV(G):
1934
1966
if n <= 1 :
1935
1967
return 0
1936
1968
1937
- cdef list int_to_vertex = list (G)
1969
+ cdef list int_to_vertex
1970
+ cdef StaticSparseCGraph cg
1938
1971
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)
1940
1979
1941
1980
cdef uint32_t source, ecc_source
1942
1981
cdef uint32_t antipode, ecc_antipode
@@ -1946,6 +1985,8 @@ def radius_DHV(G):
1946
1985
cdef MemoryAllocator mem = MemoryAllocator()
1947
1986
cdef uint32_t * distances = < uint32_t * > mem.malloc(3 * n * sizeof(uint32_t))
1948
1987
if not distances:
1988
+ if not isinstance (G, StaticSparseBackend):
1989
+ free_short_digraph(sd)
1949
1990
raise MemoryError ()
1950
1991
1951
1992
cdef uint32_t * waiting_list = distances + n
@@ -1987,7 +2028,8 @@ def radius_DHV(G):
1987
2028
LB = ecc_lower_bound[v]
1988
2029
source = v # vertex with minimum eccentricity lower bound
1989
2030
1990
- free_short_digraph(sd)
2031
+ if not isinstance (G, StaticSparseBackend):
2032
+ free_short_digraph(sd)
1991
2033
bitset_free(seen)
1992
2034
if UB == UINT32_MAX:
1993
2035
from sage.rings.infinity import Infinity
@@ -2041,6 +2083,19 @@ def wiener_index(G):
2041
2083
Traceback ( most recent call last) :
2042
2084
...
2043
2085
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
2044
2099
"""
2045
2100
if not G:
2046
2101
raise ValueError (" Wiener index is not defined for the empty graph" )
@@ -2052,8 +2107,13 @@ def wiener_index(G):
2052
2107
# Copying the whole graph to obtain the list of neighbors quicker than by
2053
2108
# calling out_neighbors. This data structure is well documented in the
2054
2109
# module sage.graphs.base.static_sparse_graph
2110
+ cdef StaticSparseCGraph cg
2055
2111
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))
2057
2117
2058
2118
# allocated some data structures
2059
2119
cdef bitset_t seen
@@ -2074,7 +2134,8 @@ def wiener_index(G):
2074
2134
for v in range (0 if G.is_directed() else (u + 1 ), n):
2075
2135
s += distances[v]
2076
2136
2077
- free_short_digraph(sd)
2137
+ if not isinstance (G, StaticSparseBackend):
2138
+ free_short_digraph(sd)
2078
2139
bitset_free(seen)
2079
2140
2080
2141
if s == UINT64_MAX:
@@ -2342,6 +2403,18 @@ def szeged_index(G, algorithm=None):
2342
2403
Traceback ( most recent call last) :
2343
2404
...
2344
2405
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
2345
2418
"""
2346
2419
if not G.is_connected():
2347
2420
raise ValueError (" the Szeged index is defined for connected graphs only" )
@@ -2364,16 +2437,23 @@ def szeged_index(G, algorithm=None):
2364
2437
if G.order() <= 1 :
2365
2438
return 0
2366
2439
2440
+ cdef StaticSparseCGraph cg
2367
2441
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
+
2369
2448
cdef uint64_t s
2370
2449
2371
2450
if algorithm == " low" :
2372
2451
s = c_szeged_index_low_memory(sd)
2373
2452
else :
2374
2453
s = c_szeged_index_high_memory(sd)
2375
2454
2376
- free_short_digraph(sd)
2455
+ if not isinstance (G, StaticSparseBackend):
2456
+ free_short_digraph(sd)
2377
2457
return s
2378
2458
2379
2459
@@ -2441,13 +2521,31 @@ def distances_distribution(G):
2441
2521
sage: D = digraphs. DeBruijn( 2,3) # needs sage. combinat
2442
2522
sage: D. distances_distribution( ) # needs sage. combinat
2443
2523
{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
2444
2537
"""
2445
2538
cdef size_t n = G.order()
2446
2539
if n <= 1 :
2447
2540
return {}
2448
2541
2542
+ cdef StaticSparseCGraph cg
2449
2543
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))
2451
2549
2452
2550
cdef MemoryAllocator mem = MemoryAllocator()
2453
2551
cdef uint32_t * distances = < uint32_t * > mem.allocarray(2 * n, sizeof(uint32_t))
@@ -2470,7 +2568,8 @@ def distances_distribution(G):
2470
2568
for v in range (n):
2471
2569
count[distances[v]] += 1
2472
2570
2473
- free_short_digraph(sd)
2571
+ if not isinstance (G, StaticSparseBackend):
2572
+ free_short_digraph(sd)
2474
2573
bitset_free(seen)
2475
2574
2476
2575
from sage.rings.infinity import Infinity
@@ -2554,6 +2653,17 @@ def antipodal_graph(G):
2554
2653
Antipodal graph of Graph on 1 vertex: Looped graph on 1 vertex
2555
2654
sage: antipodal_graph( Graph( 2)) . edges( sort=True, labels=False)
2556
2655
[(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
2557
2667
"""
2558
2668
if not G:
2559
2669
raise ValueError (" the antipodal graph of the empty graph is not defined" )
@@ -2577,9 +2687,16 @@ def antipodal_graph(G):
2577
2687
A.add_edges(itertools.product(c1, c2))
2578
2688
return A
2579
2689
2580
- cdef list int_to_vertex = list (G)
2690
+ cdef list int_to_vertex
2691
+ cdef StaticSparseCGraph cg
2581
2692
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)
2583
2700
2584
2701
cdef MemoryAllocator mem = MemoryAllocator()
2585
2702
cdef uint32_t * distances = < uint32_t * > mem.allocarray(2 * n, sizeof(uint32_t))
@@ -2607,7 +2724,8 @@ def antipodal_graph(G):
2607
2724
A.add_edge(u, int_to_vertex[vj])
2608
2725
j -= 1
2609
2726
2610
- free_short_digraph(sd)
2727
+ if not isinstance (G, StaticSparseBackend):
2728
+ free_short_digraph(sd)
2611
2729
bitset_free(seen)
2612
2730
2613
2731
A.add_vertices(G)
0 commit comments