passagemath-graphs 10.5.43__cp311-cp311-macosx_14_0_arm64.whl → 10.6.1rc2__cp311-cp311-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.
- {passagemath_graphs-10.5.43.dist-info → passagemath_graphs-10.6.1rc2.dist-info}/METADATA +5 -6
- {passagemath_graphs-10.5.43.dist-info → passagemath_graphs-10.6.1rc2.dist-info}/RECORD +132 -130
- sage/combinat/abstract_tree.py +188 -17
- sage/combinat/cluster_algebra_quiver/interact.py +1 -2
- sage/combinat/cluster_algebra_quiver/mutation_type.py +518 -519
- sage/combinat/cluster_algebra_quiver/quiver.py +233 -205
- sage/combinat/designs/covering_design.py +2 -6
- sage/combinat/designs/database.py +11 -10
- sage/combinat/designs/designs_pyx.cpython-311-darwin.so +0 -0
- sage/combinat/designs/designs_pyx.pyx +2 -2
- sage/combinat/designs/evenly_distributed_sets.cpython-311-darwin.so +0 -0
- sage/combinat/designs/evenly_distributed_sets.pyx +4 -4
- sage/combinat/designs/gen_quadrangles_with_spread.cpython-311-darwin.so +0 -0
- sage/combinat/designs/latin_squares.py +53 -20
- sage/combinat/designs/orthogonal_arrays.py +2 -1
- sage/combinat/designs/orthogonal_arrays_find_recursive.cpython-311-darwin.so +0 -0
- sage/combinat/designs/orthogonal_arrays_find_recursive.pyx +22 -21
- sage/combinat/designs/resolvable_bibd.py +191 -157
- sage/combinat/designs/subhypergraph_search.cpython-311-darwin.so +0 -0
- sage/combinat/designs/subhypergraph_search.pyx +4 -4
- sage/combinat/designs/twographs.py +2 -2
- sage/combinat/finite_state_machine.py +6 -6
- sage/combinat/posets/bubble_shuffle.py +247 -0
- sage/combinat/posets/d_complete.py +3 -3
- sage/combinat/posets/elements.py +3 -3
- sage/combinat/posets/hasse_cython.cpython-311-darwin.so +0 -0
- sage/combinat/posets/hasse_cython.pyx +1 -1
- sage/combinat/posets/hasse_diagram.py +16 -22
- sage/combinat/posets/hochschild_lattice.py +158 -0
- sage/combinat/posets/incidence_algebras.py +14 -16
- sage/combinat/posets/lattices.py +51 -53
- sage/combinat/posets/linear_extension_iterator.cpython-311-darwin.so +0 -0
- sage/combinat/posets/linear_extensions.py +10 -12
- sage/combinat/posets/moebius_algebra.py +4 -4
- sage/combinat/posets/poset_examples.py +70 -23
- sage/combinat/posets/posets.py +294 -103
- sage/databases/knotinfo_db.py +2 -1
- sage/graphs/asteroidal_triples.cpython-311-darwin.so +0 -0
- sage/graphs/asteroidal_triples.pyx +24 -3
- sage/graphs/base/boost_graph.cpython-311-darwin.so +0 -0
- sage/graphs/base/boost_graph.pxd +3 -3
- sage/graphs/base/c_graph.cpython-311-darwin.so +0 -0
- sage/graphs/base/c_graph.pyx +1 -1
- sage/graphs/base/dense_graph.cpython-311-darwin.so +0 -0
- sage/graphs/base/dense_graph.pxd +5 -3
- sage/graphs/base/dense_graph.pyx +44 -0
- sage/graphs/base/graph_backends.cpython-311-darwin.so +0 -0
- sage/graphs/base/sparse_graph.cpython-311-darwin.so +0 -0
- sage/graphs/base/static_dense_graph.cpython-311-darwin.so +0 -0
- sage/graphs/base/static_sparse_backend.cpython-311-darwin.so +0 -0
- sage/graphs/base/static_sparse_backend.pyx +8 -5
- sage/graphs/base/static_sparse_graph.cpython-311-darwin.so +0 -0
- sage/graphs/base/static_sparse_graph.pyx +86 -15
- sage/graphs/bipartite_graph.py +59 -36
- sage/graphs/centrality.cpython-311-darwin.so +0 -0
- sage/graphs/centrality.pyx +82 -9
- sage/graphs/cographs.py +1 -1
- sage/graphs/comparability.cpython-311-darwin.so +0 -0
- sage/graphs/comparability.pyx +64 -26
- sage/graphs/connectivity.cpython-311-darwin.so +0 -0
- sage/graphs/convexity_properties.cpython-311-darwin.so +0 -0
- sage/graphs/convexity_properties.pyx +52 -9
- sage/graphs/digraph.py +439 -95
- sage/graphs/digraph_generators.py +174 -102
- sage/graphs/distances_all_pairs.cpython-311-darwin.so +0 -0
- sage/graphs/dot2tex_utils.py +1 -1
- sage/graphs/edge_connectivity.cpython-311-darwin.so +0 -0
- sage/graphs/generators/basic.py +1 -1
- sage/graphs/generators/distance_regular.cpython-311-darwin.so +0 -0
- sage/graphs/generators/distance_regular.pyx +1 -1
- sage/graphs/generators/families.py +37 -27
- sage/graphs/generators/random.py +2 -2
- sage/graphs/generators/smallgraphs.py +3 -3
- sage/graphs/generic_graph.py +558 -86
- sage/graphs/generic_graph_pyx.cpython-311-darwin.so +0 -0
- sage/graphs/generic_graph_pyx.pyx +58 -11
- sage/graphs/genus.cpython-311-darwin.so +0 -0
- sage/graphs/genus.pyx +3 -4
- sage/graphs/graph.py +291 -8
- sage/graphs/graph_coloring.cpython-311-darwin.so +0 -0
- sage/graphs/graph_database.py +67 -12
- sage/graphs/graph_decompositions/bandwidth.cpython-311-darwin.so +0 -0
- sage/graphs/graph_decompositions/clique_separators.cpython-311-darwin.so +0 -0
- sage/graphs/graph_decompositions/clique_separators.pyx +24 -3
- sage/graphs/graph_decompositions/cutwidth.cpython-311-darwin.so +0 -0
- sage/graphs/graph_decompositions/fast_digraph.cpython-311-darwin.so +0 -0
- sage/graphs/graph_decompositions/fast_digraph.pyx +1 -1
- sage/graphs/graph_decompositions/graph_products.cpython-311-darwin.so +0 -0
- sage/graphs/graph_decompositions/graph_products.pyx +67 -21
- sage/graphs/graph_decompositions/modular_decomposition.cpython-311-darwin.so +0 -0
- sage/graphs/graph_decompositions/slice_decomposition.cpython-311-darwin.so +0 -0
- sage/graphs/graph_decompositions/slice_decomposition.pyx +34 -8
- sage/graphs/graph_decompositions/tree_decomposition.cpython-311-darwin.so +0 -0
- sage/graphs/graph_decompositions/vertex_separation.cpython-311-darwin.so +0 -0
- sage/graphs/graph_generators.py +45 -32
- sage/graphs/graph_generators_pyx.cpython-311-darwin.so +0 -0
- sage/graphs/graph_generators_pyx.pyx +15 -15
- sage/graphs/graph_latex.py +1 -1
- sage/graphs/graph_list.py +52 -9
- sage/graphs/graph_plot.py +7 -0
- sage/graphs/hyperbolicity.cpython-311-darwin.so +0 -0
- sage/graphs/hyperbolicity.pyx +2 -0
- sage/graphs/independent_sets.cpython-311-darwin.so +0 -0
- sage/graphs/isoperimetric_inequalities.cpython-311-darwin.so +0 -0
- sage/graphs/isoperimetric_inequalities.pyx +42 -6
- sage/graphs/line_graph.cpython-311-darwin.so +0 -0
- sage/graphs/line_graph.pyx +153 -37
- sage/graphs/matching_covered_graph.py +84 -60
- sage/graphs/orientations.py +3 -18
- sage/graphs/path_enumeration.cpython-311-darwin.so +0 -0
- sage/graphs/path_enumeration.pyx +2 -2
- sage/graphs/spanning_tree.cpython-311-darwin.so +0 -0
- sage/graphs/strongly_regular_db.cpython-311-darwin.so +0 -0
- sage/graphs/strongly_regular_db.pyx +15 -15
- sage/graphs/traversals.cpython-311-darwin.so +0 -0
- sage/graphs/traversals.pyx +13 -12
- sage/graphs/trees.cpython-311-darwin.so +0 -0
- sage/graphs/tutte_polynomial.py +1 -1
- sage/graphs/views.cpython-311-darwin.so +0 -0
- sage/graphs/weakly_chordal.cpython-311-darwin.so +0 -0
- sage/graphs/weakly_chordal.pyx +50 -8
- sage/groups/perm_gps/partn_ref/refinement_graphs.cpython-311-darwin.so +0 -0
- sage/knots/free_knotinfo_monoid.py +3 -3
- sage/knots/knotinfo.py +102 -82
- sage/knots/link.py +72 -39
- sage/topology/cubical_complex.py +4 -5
- sage/topology/delta_complex.py +4 -4
- sage/topology/simplicial_complex.py +0 -1
- sage/topology/simplicial_complex_catalog.py +6 -0
- sage/topology/simplicial_complex_examples.py +4 -16
- {passagemath_graphs-10.5.43.dist-info → passagemath_graphs-10.6.1rc2.dist-info}/WHEEL +0 -0
- {passagemath_graphs-10.5.43.dist-info → passagemath_graphs-10.6.1rc2.dist-info}/top_level.txt +0 -0
sage/databases/knotinfo_db.py
CHANGED
@@ -578,13 +578,14 @@ class KnotInfoDataBase(SageObject, UniqueRepresentation):
|
|
578
578
|
def _create_data_sobj(self, sobj_path=None):
|
579
579
|
r"""
|
580
580
|
Create ``sobj`` files containing the contents of the whole table.
|
581
|
+
|
581
582
|
To each column there is created one file containing a list of
|
582
583
|
strings giving the entries of the database table.
|
583
584
|
|
584
585
|
The length of these lists depends on the type of the corresponding
|
585
586
|
column. If a column is used in both tables
|
586
587
|
(``KnotInfoColumnTypes.KnotsAndLinks``) the list of proper links
|
587
|
-
is appended to the list of knots. In both other cases the
|
588
|
+
is appended to the list of knots. In both other cases the length
|
588
589
|
of the list corresponds to the number of listed knots and proper
|
589
590
|
links respectively.
|
590
591
|
|
Binary file
|
@@ -66,6 +66,8 @@ from cysignals.signals cimport sig_on, sig_off
|
|
66
66
|
from memory_allocator cimport MemoryAllocator
|
67
67
|
|
68
68
|
from sage.data_structures.bitset_base cimport *
|
69
|
+
from sage.graphs.base.static_sparse_backend cimport StaticSparseCGraph
|
70
|
+
from sage.graphs.base.static_sparse_backend cimport StaticSparseBackend
|
69
71
|
from sage.graphs.base.static_sparse_graph cimport short_digraph, init_short_digraph, free_short_digraph
|
70
72
|
|
71
73
|
|
@@ -125,6 +127,17 @@ def is_asteroidal_triple_free(G, certificate=False):
|
|
125
127
|
Traceback (most recent call last):
|
126
128
|
...
|
127
129
|
ValueError: The first parameter must be a Graph.
|
130
|
+
|
131
|
+
The method is valid for immutable graphs::
|
132
|
+
|
133
|
+
sage: G = graphs.RandomGNP(10, .7)
|
134
|
+
sage: G._backend
|
135
|
+
<sage.graphs.base.sparse_graph.SparseGraphBackend ...>
|
136
|
+
sage: H = Graph(G, immutable=True)
|
137
|
+
sage: H._backend
|
138
|
+
<sage.graphs.base.static_sparse_backend.StaticSparseBackend ...>
|
139
|
+
sage: G.is_asteroidal_triple_free() == H.is_asteroidal_triple_free()
|
140
|
+
True
|
128
141
|
"""
|
129
142
|
from sage.graphs.graph import Graph
|
130
143
|
if not isinstance(G, Graph):
|
@@ -146,9 +159,16 @@ def is_asteroidal_triple_free(G, certificate=False):
|
|
146
159
|
# Copying the whole graph to obtain the list of neighbors quicker than by
|
147
160
|
# calling out_neighbors. This data structure is well documented in the
|
148
161
|
# module sage.graphs.base.static_sparse_graph
|
149
|
-
cdef list int_to_vertex
|
162
|
+
cdef list int_to_vertex
|
163
|
+
cdef StaticSparseCGraph cg
|
150
164
|
cdef short_digraph sd
|
151
|
-
|
165
|
+
if isinstance(G, StaticSparseBackend):
|
166
|
+
cg = <StaticSparseCGraph> G._cg
|
167
|
+
sd = <short_digraph> cg.g
|
168
|
+
int_to_vertex = cg._vertex_to_labels
|
169
|
+
else:
|
170
|
+
int_to_vertex = list(G)
|
171
|
+
init_short_digraph(sd, G, edge_labelled=False, vertex_list=int_to_vertex)
|
152
172
|
|
153
173
|
cdef bitset_t seen
|
154
174
|
bitset_init(seen, n)
|
@@ -169,7 +189,8 @@ def is_asteroidal_triple_free(G, certificate=False):
|
|
169
189
|
finally:
|
170
190
|
# Release memory
|
171
191
|
bitset_free(seen)
|
172
|
-
|
192
|
+
if not isinstance(G, StaticSparseBackend):
|
193
|
+
free_short_digraph(sd)
|
173
194
|
|
174
195
|
# ==> We return the result
|
175
196
|
|
Binary file
|
sage/graphs/base/boost_graph.pxd
CHANGED
@@ -2,14 +2,14 @@
|
|
2
2
|
# distutils: language = c++
|
3
3
|
# distutils: extra_compile_args = -std=c++11
|
4
4
|
|
5
|
-
|
5
|
+
# ***************************************************************************
|
6
6
|
# Copyright (C) 2015 Michele Borassi michele.borassi@imtlucca.it
|
7
7
|
#
|
8
8
|
# Distributed under the terms of the GNU General Public License (GPL)
|
9
9
|
# as published by the Free Software Foundation; either version 2 of
|
10
10
|
# the License, or (at your option) any later version.
|
11
|
-
#
|
12
|
-
|
11
|
+
# https://www.gnu.org/licenses/
|
12
|
+
# ***************************************************************************
|
13
13
|
from libcpp.vector cimport vector
|
14
14
|
from libcpp.pair cimport pair
|
15
15
|
|
Binary file
|
sage/graphs/base/c_graph.pyx
CHANGED
@@ -954,7 +954,7 @@ cdef class CGraph:
|
|
954
954
|
self.check_vertex(u)
|
955
955
|
self.check_vertex(v)
|
956
956
|
if unlikely(self.in_degrees is NULL or self.out_degrees is NULL):
|
957
|
-
raise ValueError("`self.
|
957
|
+
raise ValueError("`self.in_degrees` or `self.out_degrees` not allocated")
|
958
958
|
if self.in_degrees[v] < self.out_degrees[u]:
|
959
959
|
size = self.in_degrees[v]
|
960
960
|
else:
|
Binary file
|
sage/graphs/base/dense_graph.pxd
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
# sage_setup: distribution = sagemath-graphs
|
2
|
-
|
2
|
+
# ***************************************************************************
|
3
3
|
# Copyright (C) 2008-2009 Robert L. Miller <rlmillster@gmail.com>
|
4
4
|
#
|
5
5
|
# This program is free software: you can redistribute it and/or modify
|
6
6
|
# it under the terms of the GNU General Public License as published by
|
7
7
|
# the Free Software Foundation, either version 2 of the License, or
|
8
8
|
# (at your option) any later version.
|
9
|
-
#
|
10
|
-
|
9
|
+
# https://www.gnu.org/licenses/
|
10
|
+
# ***************************************************************************
|
11
11
|
|
12
12
|
from sage.graphs.base.c_graph cimport CGraph, CGraphBackend
|
13
13
|
from sage.data_structures.binary_matrix cimport binary_matrix_t
|
@@ -17,6 +17,8 @@ cdef class DenseGraph(CGraph):
|
|
17
17
|
cdef binary_matrix_t edges
|
18
18
|
cdef inline int _add_arc_unsafe(self, int, int) except -1
|
19
19
|
cdef inline int _del_arc_unsafe(self, int u, int v) except -1
|
20
|
+
cpdef int out_degree(self, int u) noexcept
|
21
|
+
cpdef int in_degree(self, int u) noexcept
|
20
22
|
|
21
23
|
cdef int copy_dense_graph(DenseGraph dest, DenseGraph src) except -1
|
22
24
|
|
sage/graphs/base/dense_graph.pyx
CHANGED
@@ -453,6 +453,50 @@ cdef class DenseGraph(CGraph):
|
|
453
453
|
i = bitset_next(self.active_vertices, i + 1)
|
454
454
|
return -1
|
455
455
|
|
456
|
+
cpdef int out_degree(self, int u) noexcept:
|
457
|
+
"""
|
458
|
+
Return the out-degree of ``v``
|
459
|
+
|
460
|
+
INPUT:
|
461
|
+
|
462
|
+
- ``u`` -- integer
|
463
|
+
|
464
|
+
EXAMPLES::
|
465
|
+
|
466
|
+
sage: from sage.graphs.base.dense_graph import DenseGraph
|
467
|
+
sage: G = DenseGraph(5)
|
468
|
+
sage: G.add_arc(0,1)
|
469
|
+
sage: G.add_arc(1,2)
|
470
|
+
sage: G.add_arc(1,3)
|
471
|
+
sage: G.out_degree(0)
|
472
|
+
1
|
473
|
+
sage: G.out_degree(1)
|
474
|
+
2
|
475
|
+
"""
|
476
|
+
return self.out_degrees[u]
|
477
|
+
|
478
|
+
cpdef int in_degree(self, int v) noexcept:
|
479
|
+
"""
|
480
|
+
Return the in-degree of ``v``
|
481
|
+
|
482
|
+
INPUT:
|
483
|
+
|
484
|
+
- ``v`` -- integer
|
485
|
+
|
486
|
+
EXAMPLES::
|
487
|
+
|
488
|
+
sage: from sage.graphs.base.dense_graph import DenseGraph
|
489
|
+
sage: G = DenseGraph(5)
|
490
|
+
sage: G.add_arc(0,1)
|
491
|
+
sage: G.add_arc(1,2)
|
492
|
+
sage: G.add_arc(1,3)
|
493
|
+
sage: G.in_degree(0)
|
494
|
+
0
|
495
|
+
sage: G.in_degree(1)
|
496
|
+
1
|
497
|
+
"""
|
498
|
+
return self.in_degrees[v]
|
499
|
+
|
456
500
|
|
457
501
|
cdef int copy_dense_graph(DenseGraph dest, DenseGraph src) except -1:
|
458
502
|
r"""
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
@@ -36,6 +36,7 @@ Classes and methods
|
|
36
36
|
-------------------
|
37
37
|
"""
|
38
38
|
|
39
|
+
cimport cython
|
39
40
|
from cysignals.memory cimport check_calloc, sig_free
|
40
41
|
|
41
42
|
from sage.graphs.base.static_sparse_graph cimport (init_short_digraph,
|
@@ -125,6 +126,8 @@ cdef class StaticSparseCGraph(CGraph):
|
|
125
126
|
self.number_of_loops = <int *>check_calloc(self.g.n, sizeof(int))
|
126
127
|
except MemoryError:
|
127
128
|
free_short_digraph(self.g)
|
129
|
+
if self._directed:
|
130
|
+
free_short_digraph(self.g_rev)
|
128
131
|
raise
|
129
132
|
for i in range(self.g.n):
|
130
133
|
for tmp in range(out_degree(self.g, i)):
|
@@ -140,7 +143,7 @@ cdef class StaticSparseCGraph(CGraph):
|
|
140
143
|
bitset_set_first_n(self.active_vertices, self.g.n)
|
141
144
|
|
142
145
|
self.num_verts = self.g.n
|
143
|
-
self.num_arcs = self.g.m
|
146
|
+
self.num_arcs = self.g.m if self._directed else (2 * self.g.m)
|
144
147
|
|
145
148
|
def __dealloc__(self):
|
146
149
|
r"""
|
@@ -394,7 +397,7 @@ cdef class StaticSparseCGraph(CGraph):
|
|
394
397
|
if u < 0 or u >= self.g.n:
|
395
398
|
raise LookupError("the vertex does not belong to the graph")
|
396
399
|
|
397
|
-
return self.g
|
400
|
+
return out_degree(self.g, u)
|
398
401
|
|
399
402
|
cpdef int in_degree(self, int u) except -1:
|
400
403
|
r"""
|
@@ -419,9 +422,8 @@ cdef class StaticSparseCGraph(CGraph):
|
|
419
422
|
raise LookupError("the vertex does not belong to the graph")
|
420
423
|
|
421
424
|
if not self._directed:
|
422
|
-
return self.g
|
423
|
-
|
424
|
-
return self.g_rev.neighbors[u+1] - self.g_rev.neighbors[u]
|
425
|
+
return out_degree(self.g, u)
|
426
|
+
return out_degree(self.g_rev, u)
|
425
427
|
|
426
428
|
|
427
429
|
cdef class StaticSparseBackend(CGraphBackend):
|
@@ -1545,6 +1547,7 @@ cdef class StaticSparseBackend(CGraphBackend):
|
|
1545
1547
|
(<StaticSparseCGraph> self._cg).del_vertex(v)
|
1546
1548
|
|
1547
1549
|
|
1550
|
+
@cython.binding(True)
|
1548
1551
|
def _run_it_on_static_instead(f):
|
1549
1552
|
r"""
|
1550
1553
|
A decorator function to force the (Di)Graph functions to compute from a
|
Binary file
|
@@ -281,10 +281,9 @@ cdef int init_short_digraph(short_digraph g, G, edge_labelled=False,
|
|
281
281
|
g.m = G.size()
|
282
282
|
|
283
283
|
cdef int isdigraph = G.is_directed()
|
284
|
-
cdef uint32_t i,
|
284
|
+
cdef uint32_t i, j
|
285
285
|
cdef list vertices = vertex_list if vertex_list is not None else list(G)
|
286
286
|
cdef dict v_to_id = {v: i for i, v in enumerate(vertices)}
|
287
|
-
cdef list neighbor_label
|
288
287
|
cdef list edge_labels
|
289
288
|
# Loops are not stored twice for undirected graphs
|
290
289
|
cdef int n_edges = g.m if isdigraph else 2*g.m - G.number_of_loops()
|
@@ -803,21 +802,43 @@ def tarjan_strongly_connected_components(G):
|
|
803
802
|
....: s2 = Set(map(Set,scc2))
|
804
803
|
....: if s1 != s2:
|
805
804
|
....: print("Ooch !")
|
805
|
+
|
806
|
+
Immutable digraphs::
|
807
|
+
|
808
|
+
sage: from sage.graphs.base.static_sparse_graph import tarjan_strongly_connected_components
|
809
|
+
sage: G = digraphs.RandomDirectedGNP(10, .4)
|
810
|
+
sage: G._backend
|
811
|
+
<sage.graphs.base.sparse_graph.SparseGraphBackend ...>
|
812
|
+
sage: H = DiGraph(G, immutable=True)
|
813
|
+
sage: H._backend
|
814
|
+
<sage.graphs.base.static_sparse_backend.StaticSparseBackend ...>
|
815
|
+
sage: tarjan_strongly_connected_components(G) == tarjan_strongly_connected_components(H)
|
816
|
+
True
|
806
817
|
"""
|
807
818
|
from sage.graphs.digraph import DiGraph
|
808
819
|
|
809
820
|
if not isinstance(G, DiGraph):
|
810
821
|
raise ValueError("G must be a DiGraph.")
|
811
822
|
|
812
|
-
cdef
|
813
|
-
cdef
|
823
|
+
cdef list int_to_vertex
|
824
|
+
cdef StaticSparseCGraph cg
|
814
825
|
cdef short_digraph g
|
815
|
-
|
826
|
+
if isinstance(G, StaticSparseBackend):
|
827
|
+
cg = <StaticSparseCGraph> G._cg
|
828
|
+
g = <short_digraph> cg.g
|
829
|
+
int_to_vertex = cg._vertex_to_labels
|
830
|
+
else:
|
831
|
+
int_to_vertex = list(G)
|
832
|
+
init_short_digraph(g, G, edge_labelled=False, vertex_list=int_to_vertex)
|
833
|
+
|
834
|
+
cdef MemoryAllocator mem = MemoryAllocator()
|
816
835
|
cdef int * scc = <int*> mem.malloc(g.n * sizeof(int))
|
817
836
|
sig_on()
|
818
837
|
cdef int nscc = tarjan_strongly_connected_components_C(g, scc)
|
819
838
|
sig_off()
|
820
|
-
|
839
|
+
|
840
|
+
if not isinstance(G, StaticSparseBackend):
|
841
|
+
free_short_digraph(g)
|
821
842
|
|
822
843
|
cdef int i
|
823
844
|
cdef list output = [[] for i in range(nscc)]
|
@@ -873,6 +894,7 @@ cdef void strongly_connected_components_digraph_C(short_digraph g, int nscc, int
|
|
873
894
|
|
874
895
|
output.n = nscc
|
875
896
|
output.m = m
|
897
|
+
output.edge_labels = NULL
|
876
898
|
|
877
899
|
output.neighbors = <uint32_t **> check_allocarray((1+<int>output.n), sizeof(uint32_t *))
|
878
900
|
|
@@ -921,15 +943,37 @@ def strongly_connected_components_digraph(G):
|
|
921
943
|
....: for e in g.edges(sort=False):
|
922
944
|
....: assert(sccs[e[0]]==sccs[e[1]] or scc_digraph.has_edge(sccs[e[0]],sccs[e[1]]))
|
923
945
|
....: assert(sccs[e[0]] >= sccs[e[1]])
|
946
|
+
|
947
|
+
Immutable digraphs::
|
948
|
+
|
949
|
+
sage: from sage.graphs.base.static_sparse_graph import strongly_connected_components_digraph
|
950
|
+
sage: G = digraphs.RandomDirectedGNP(10, .4)
|
951
|
+
sage: G._backend
|
952
|
+
<sage.graphs.base.sparse_graph.SparseGraphBackend ...>
|
953
|
+
sage: H = DiGraph(G, immutable=True)
|
954
|
+
sage: H._backend
|
955
|
+
<sage.graphs.base.static_sparse_backend.StaticSparseBackend ...>
|
956
|
+
sage: A = strongly_connected_components_digraph(G)[0]
|
957
|
+
sage: B = strongly_connected_components_digraph(H)[0]
|
958
|
+
sage: A.is_isomorphic(B)
|
959
|
+
True
|
924
960
|
"""
|
925
961
|
from sage.graphs.digraph import DiGraph
|
926
962
|
if not isinstance(G, DiGraph):
|
927
963
|
raise ValueError("G must be a DiGraph.")
|
928
964
|
|
929
|
-
cdef
|
930
|
-
cdef
|
965
|
+
cdef list int_to_vertex
|
966
|
+
cdef StaticSparseCGraph cg
|
931
967
|
cdef short_digraph g, scc_g
|
932
|
-
|
968
|
+
if isinstance(G, StaticSparseBackend):
|
969
|
+
cg = <StaticSparseCGraph> G._cg
|
970
|
+
g = <short_digraph> cg.g
|
971
|
+
int_to_vertex = cg._vertex_to_labels
|
972
|
+
else:
|
973
|
+
int_to_vertex = list(G)
|
974
|
+
init_short_digraph(g, G, edge_labelled=False, vertex_list=int_to_vertex)
|
975
|
+
|
976
|
+
cdef MemoryAllocator mem = MemoryAllocator()
|
933
977
|
cdef int * scc = <int*> mem.malloc(g.n * sizeof(int))
|
934
978
|
cdef int i, j, nscc
|
935
979
|
cdef list edges = []
|
@@ -945,7 +989,11 @@ def strongly_connected_components_digraph(G):
|
|
945
989
|
edges.append((i, scc_g.neighbors[i][j]))
|
946
990
|
output.add_edges(edges)
|
947
991
|
sig_off()
|
948
|
-
|
992
|
+
|
993
|
+
if not isinstance(G, StaticSparseBackend):
|
994
|
+
free_short_digraph(g)
|
995
|
+
free_short_digraph(scc_g)
|
996
|
+
|
949
997
|
return output, {v: scc[i] for i, v in enumerate(int_to_vertex)}
|
950
998
|
|
951
999
|
|
@@ -969,7 +1017,8 @@ cdef void free_short_digraph(short_digraph g) noexcept:
|
|
969
1017
|
"""
|
970
1018
|
sig_free(g.edges)
|
971
1019
|
sig_free(g.neighbors)
|
972
|
-
|
1020
|
+
if g.edge_labels != NULL:
|
1021
|
+
cpython.Py_XDECREF(g.edge_labels)
|
973
1022
|
|
974
1023
|
|
975
1024
|
def triangles_count(G):
|
@@ -987,14 +1036,35 @@ def triangles_count(G):
|
|
987
1036
|
{0: 0, 1: 0, 2: 0, 3: 0, 4: 0, 5: 0, 6: 0, 7: 0, 8: 0, 9: 0}
|
988
1037
|
sage: sum(triangles_count(graphs.CompleteGraph(15)).values()) == 3*binomial(15,3) # needs sage.symbolic
|
989
1038
|
True
|
1039
|
+
|
1040
|
+
TESTS:
|
1041
|
+
|
1042
|
+
Immutable graphs::
|
1043
|
+
|
1044
|
+
sage: from sage.graphs.base.static_sparse_graph import triangles_count
|
1045
|
+
sage: G = graphs.RandomGNP(10, .7)
|
1046
|
+
sage: G._backend
|
1047
|
+
<sage.graphs.base.sparse_graph.SparseGraphBackend ...>
|
1048
|
+
sage: H = Graph(G, immutable=True)
|
1049
|
+
sage: H._backend
|
1050
|
+
<sage.graphs.base.static_sparse_backend.StaticSparseBackend ...>
|
1051
|
+
sage: triangles_count(G) == triangles_count(H)
|
1052
|
+
True
|
990
1053
|
"""
|
991
1054
|
from sage.rings.integer import Integer
|
992
1055
|
G._scream_if_not_simple()
|
993
1056
|
|
994
1057
|
# g is a copy of G. If G is internally a static sparse graph, we use it.
|
995
|
-
cdef list int_to_vertex
|
1058
|
+
cdef list int_to_vertex
|
1059
|
+
cdef StaticSparseCGraph cg
|
996
1060
|
cdef short_digraph g
|
997
|
-
|
1061
|
+
if isinstance(G, StaticSparseBackend):
|
1062
|
+
cg = <StaticSparseCGraph> G._cg
|
1063
|
+
g = <short_digraph> cg.g
|
1064
|
+
int_to_vertex = cg._vertex_to_labels
|
1065
|
+
else:
|
1066
|
+
int_to_vertex = list(G)
|
1067
|
+
init_short_digraph(g, G, edge_labelled=False, vertex_list=int_to_vertex)
|
998
1068
|
|
999
1069
|
cdef uint64_t * count = <uint64_t *> check_calloc(G.order(), sizeof(uint64_t))
|
1000
1070
|
|
@@ -1028,7 +1098,8 @@ def triangles_count(G):
|
|
1028
1098
|
|
1029
1099
|
ans = {w: Integer(count[i] // 2) for i, w in enumerate(int_to_vertex)}
|
1030
1100
|
|
1031
|
-
|
1101
|
+
if not isinstance(G, StaticSparseBackend):
|
1102
|
+
free_short_digraph(g)
|
1032
1103
|
sig_free(count)
|
1033
1104
|
return ans
|
1034
1105
|
|
@@ -1112,7 +1183,7 @@ def spectral_radius(G, prec=1e-10):
|
|
1112
1183
|
sage: while not G.is_strongly_connected():
|
1113
1184
|
....: shuffle(r)
|
1114
1185
|
....: G.add_edges(enumerate(r), loops=False)
|
1115
|
-
sage: spectral_radius(G, 1e-10) # random
|
1186
|
+
sage: spectral_radius(G, 1e-10) # random # long time
|
1116
1187
|
(1.9997956006500042, 1.9998043797692782)
|
1117
1188
|
|
1118
1189
|
The algorithm takes care of multiple edges::
|
sage/graphs/bipartite_graph.py
CHANGED
@@ -392,6 +392,17 @@ class BipartiteGraph(Graph):
|
|
392
392
|
Traceback (most recent call last):
|
393
393
|
...
|
394
394
|
LookupError: vertex (7) is not a vertex of the graph
|
395
|
+
|
396
|
+
Check that :issue:`39295` is fixed::
|
397
|
+
|
398
|
+
sage: # needs sage.modules
|
399
|
+
sage: B = BipartiteGraph(matrix([[1, 1], [1, 1]]), immutable=True)
|
400
|
+
sage: print(B.vertices(), B.edges())
|
401
|
+
[0, 1, 2, 3] [(0, 2, None), (0, 3, None), (1, 2, None), (1, 3, None)]
|
402
|
+
sage: B.add_vertices([4], left=True)
|
403
|
+
Traceback (most recent call last):
|
404
|
+
...
|
405
|
+
ValueError: graph is immutable; please change a copy instead (use function copy())
|
395
406
|
"""
|
396
407
|
if kwds is None:
|
397
408
|
kwds = {'loops': False}
|
@@ -468,32 +479,31 @@ class BipartiteGraph(Graph):
|
|
468
479
|
if kwds.get("multiedges", False) and kwds.get("weighted", False):
|
469
480
|
raise TypeError("weighted multi-edge bipartite graphs from "
|
470
481
|
"reduced adjacency matrix not supported")
|
471
|
-
Graph.__init__(self, *args, **kwds)
|
472
482
|
ncols = data.ncols()
|
473
483
|
nrows = data.nrows()
|
474
484
|
self.left = set(range(ncols))
|
475
485
|
self.right = set(range(ncols, nrows + ncols))
|
476
486
|
|
477
|
-
|
478
|
-
|
479
|
-
|
480
|
-
|
481
|
-
|
482
|
-
|
483
|
-
|
484
|
-
for
|
485
|
-
|
486
|
-
|
487
|
-
|
488
|
-
|
489
|
-
for
|
490
|
-
|
491
|
-
|
492
|
-
|
493
|
-
|
494
|
-
|
495
|
-
|
496
|
-
|
487
|
+
def edges():
|
488
|
+
if kwds.get("multiedges", False):
|
489
|
+
for ii in range(ncols):
|
490
|
+
for jj in range(nrows):
|
491
|
+
for _ in range(data[jj, ii]):
|
492
|
+
yield (ii, jj + ncols)
|
493
|
+
elif kwds.get("weighted", False):
|
494
|
+
for ii in range(ncols):
|
495
|
+
for jj in range(nrows):
|
496
|
+
if data[jj, ii]:
|
497
|
+
yield (ii, jj + ncols, data[jj, ii])
|
498
|
+
else:
|
499
|
+
for ii in range(ncols):
|
500
|
+
for jj in range(nrows):
|
501
|
+
if data[jj, ii]:
|
502
|
+
yield (ii, jj + ncols)
|
503
|
+
|
504
|
+
# ensure that construction works
|
505
|
+
# when immutable=True (issue #39295)
|
506
|
+
Graph.__init__(self, data=[range(nrows + ncols), edges()], format='vertices_and_edges', *args, **kwds)
|
497
507
|
else:
|
498
508
|
if partition is not None:
|
499
509
|
left, right = set(partition[0]), set(partition[1])
|
@@ -2457,12 +2467,8 @@ class BipartiteGraph(Graph):
|
|
2457
2467
|
|
2458
2468
|
B.add_edges(edges_to_keep)
|
2459
2469
|
|
2460
|
-
|
2461
|
-
|
2462
|
-
if hasattr(self, attr) and getattr(self, attr) is not None:
|
2463
|
-
d = getattr(self, attr)
|
2464
|
-
value = {v: d.get(v, None) for v in B}
|
2465
|
-
setattr(B, attr, value)
|
2470
|
+
B._copy_attribute_from(self, '_pos')
|
2471
|
+
B._copy_attribute_from(self, '_assoc')
|
2466
2472
|
|
2467
2473
|
return B
|
2468
2474
|
|
@@ -2521,12 +2527,8 @@ class BipartiteGraph(Graph):
|
|
2521
2527
|
else:
|
2522
2528
|
# We make a copy of the graph
|
2523
2529
|
B = BipartiteGraph(data=self.edges(sort=True), partition=[self.left, self.right])
|
2524
|
-
|
2525
|
-
|
2526
|
-
if hasattr(self, attr) and getattr(self, attr) is not None:
|
2527
|
-
d = getattr(self, attr)
|
2528
|
-
value = {v: d.get(v, None) for v in B}
|
2529
|
-
setattr(B, attr, value)
|
2530
|
+
B._copy_attribute_from(self, '_pos')
|
2531
|
+
B._copy_attribute_from(self, '_assoc')
|
2530
2532
|
B.name("Subgraph of ({})".format(self.name()))
|
2531
2533
|
|
2532
2534
|
vertices = set(vertices)
|
@@ -2551,7 +2553,8 @@ class BipartiteGraph(Graph):
|
|
2551
2553
|
return B
|
2552
2554
|
|
2553
2555
|
def canonical_label(self, partition=None, certificate=False,
|
2554
|
-
edge_labels=False, algorithm=None, return_graph=True
|
2556
|
+
edge_labels=False, algorithm=None, return_graph=True,
|
2557
|
+
immutable=None):
|
2555
2558
|
r"""
|
2556
2559
|
Return the canonical graph.
|
2557
2560
|
|
@@ -2592,6 +2595,10 @@ class BipartiteGraph(Graph):
|
|
2592
2595
|
instead of the canonical graph. Only available when ``'bliss'``
|
2593
2596
|
is explicitly set as algorithm.
|
2594
2597
|
|
2598
|
+
- ``immutable`` -- boolean (default: ``None``); whether to create a
|
2599
|
+
mutable/immutable (di)graph. ``immutable=None`` (default) means that
|
2600
|
+
the (di)graph and its canonical (di)graph will behave the same way.
|
2601
|
+
|
2595
2602
|
EXAMPLES::
|
2596
2603
|
|
2597
2604
|
sage: B = BipartiteGraph( [(0, 4), (0, 5), (0, 6), (0, 8), (1, 5),
|
@@ -2651,6 +2658,19 @@ class BipartiteGraph(Graph):
|
|
2651
2658
|
sage: B.canonical_label()
|
2652
2659
|
Bipartite multi-graph on 4 vertices
|
2653
2660
|
|
2661
|
+
Check the behavior for immutable graphs::
|
2662
|
+
|
2663
|
+
sage: G = BipartiteGraph(graphs.CycleGraph(4))
|
2664
|
+
sage: G.canonical_label().is_immutable()
|
2665
|
+
False
|
2666
|
+
sage: G.canonical_label(immutable=True).is_immutable()
|
2667
|
+
True
|
2668
|
+
sage: G = BipartiteGraph(graphs.CycleGraph(4), immutable=True)
|
2669
|
+
sage: G.canonical_label().is_immutable()
|
2670
|
+
True
|
2671
|
+
sage: G.canonical_label(immutable=False).is_immutable()
|
2672
|
+
False
|
2673
|
+
|
2654
2674
|
.. SEEALSO::
|
2655
2675
|
|
2656
2676
|
:meth:`~sage.graphs.generic_graph.GenericGraph.canonical_label()`
|
@@ -2660,7 +2680,8 @@ class BipartiteGraph(Graph):
|
|
2660
2680
|
certificate=certificate,
|
2661
2681
|
edge_labels=edge_labels,
|
2662
2682
|
algorithm=algorithm,
|
2663
|
-
return_graph=return_graph
|
2683
|
+
return_graph=return_graph,
|
2684
|
+
immutable=immutable)
|
2664
2685
|
|
2665
2686
|
else:
|
2666
2687
|
from sage.groups.perm_gps.partn_ref.refinement_graphs import search_tree
|
@@ -2699,7 +2720,9 @@ class BipartiteGraph(Graph):
|
|
2699
2720
|
a, b, c = search_tree(GC, partition, certificate=True, dig=False)
|
2700
2721
|
cert = {v: c[G_to[v]] for v in G_to}
|
2701
2722
|
|
2702
|
-
|
2723
|
+
if immutable is None:
|
2724
|
+
immutable = self.is_immutable()
|
2725
|
+
C = self.relabel(perm=cert, inplace=False, immutable=immutable)
|
2703
2726
|
|
2704
2727
|
C.left = {cert[v] for v in self.left}
|
2705
2728
|
C.right = {cert[v] for v in self.right}
|
Binary file
|