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.
- {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-312-darwin.so +0 -0
- sage/combinat/designs/designs_pyx.pyx +2 -2
- sage/combinat/designs/evenly_distributed_sets.cpython-312-darwin.so +0 -0
- sage/combinat/designs/evenly_distributed_sets.pyx +4 -4
- sage/combinat/designs/gen_quadrangles_with_spread.cpython-312-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-312-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-312-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-312-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-312-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-312-darwin.so +0 -0
- sage/graphs/asteroidal_triples.pyx +24 -3
- sage/graphs/base/boost_graph.cpython-312-darwin.so +0 -0
- sage/graphs/base/boost_graph.pxd +3 -3
- sage/graphs/base/c_graph.cpython-312-darwin.so +0 -0
- sage/graphs/base/c_graph.pyx +1 -1
- sage/graphs/base/dense_graph.cpython-312-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-312-darwin.so +0 -0
- sage/graphs/base/sparse_graph.cpython-312-darwin.so +0 -0
- sage/graphs/base/static_dense_graph.cpython-312-darwin.so +0 -0
- sage/graphs/base/static_sparse_backend.cpython-312-darwin.so +0 -0
- sage/graphs/base/static_sparse_backend.pyx +8 -5
- sage/graphs/base/static_sparse_graph.cpython-312-darwin.so +0 -0
- sage/graphs/base/static_sparse_graph.pyx +86 -15
- sage/graphs/bipartite_graph.py +59 -36
- sage/graphs/centrality.cpython-312-darwin.so +0 -0
- sage/graphs/centrality.pyx +82 -9
- sage/graphs/cographs.py +1 -1
- sage/graphs/comparability.cpython-312-darwin.so +0 -0
- sage/graphs/comparability.pyx +64 -26
- sage/graphs/connectivity.cpython-312-darwin.so +0 -0
- sage/graphs/convexity_properties.cpython-312-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-312-darwin.so +0 -0
- sage/graphs/dot2tex_utils.py +1 -1
- sage/graphs/edge_connectivity.cpython-312-darwin.so +0 -0
- sage/graphs/generators/basic.py +1 -1
- sage/graphs/generators/distance_regular.cpython-312-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-312-darwin.so +0 -0
- sage/graphs/generic_graph_pyx.pyx +58 -11
- sage/graphs/genus.cpython-312-darwin.so +0 -0
- sage/graphs/genus.pyx +3 -4
- sage/graphs/graph.py +291 -8
- sage/graphs/graph_coloring.cpython-312-darwin.so +0 -0
- sage/graphs/graph_database.py +67 -12
- sage/graphs/graph_decompositions/bandwidth.cpython-312-darwin.so +0 -0
- sage/graphs/graph_decompositions/clique_separators.cpython-312-darwin.so +0 -0
- sage/graphs/graph_decompositions/clique_separators.pyx +24 -3
- sage/graphs/graph_decompositions/cutwidth.cpython-312-darwin.so +0 -0
- sage/graphs/graph_decompositions/fast_digraph.cpython-312-darwin.so +0 -0
- sage/graphs/graph_decompositions/fast_digraph.pyx +1 -1
- sage/graphs/graph_decompositions/graph_products.cpython-312-darwin.so +0 -0
- sage/graphs/graph_decompositions/graph_products.pyx +67 -21
- sage/graphs/graph_decompositions/modular_decomposition.cpython-312-darwin.so +0 -0
- sage/graphs/graph_decompositions/slice_decomposition.cpython-312-darwin.so +0 -0
- sage/graphs/graph_decompositions/slice_decomposition.pyx +34 -8
- sage/graphs/graph_decompositions/tree_decomposition.cpython-312-darwin.so +0 -0
- sage/graphs/graph_decompositions/vertex_separation.cpython-312-darwin.so +0 -0
- sage/graphs/graph_generators.py +45 -32
- sage/graphs/graph_generators_pyx.cpython-312-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-312-darwin.so +0 -0
- sage/graphs/hyperbolicity.pyx +2 -0
- sage/graphs/independent_sets.cpython-312-darwin.so +0 -0
- sage/graphs/isoperimetric_inequalities.cpython-312-darwin.so +0 -0
- sage/graphs/isoperimetric_inequalities.pyx +42 -6
- sage/graphs/line_graph.cpython-312-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-312-darwin.so +0 -0
- sage/graphs/path_enumeration.pyx +2 -2
- sage/graphs/spanning_tree.cpython-312-darwin.so +0 -0
- sage/graphs/strongly_regular_db.cpython-312-darwin.so +0 -0
- sage/graphs/strongly_regular_db.pyx +15 -15
- sage/graphs/traversals.cpython-312-darwin.so +0 -0
- sage/graphs/traversals.pyx +13 -12
- sage/graphs/trees.cpython-312-darwin.so +0 -0
- sage/graphs/tutte_polynomial.py +1 -1
- sage/graphs/views.cpython-312-darwin.so +0 -0
- sage/graphs/weakly_chordal.cpython-312-darwin.so +0 -0
- sage/graphs/weakly_chordal.pyx +50 -8
- sage/groups/perm_gps/partn_ref/refinement_graphs.cpython-312-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
@@ -26,6 +26,8 @@ from libc.stdint cimport uint32_t
|
|
26
26
|
from cysignals.signals cimport sig_on, sig_off, sig_check
|
27
27
|
from memory_allocator cimport MemoryAllocator
|
28
28
|
|
29
|
+
from sage.graphs.base.static_sparse_backend cimport StaticSparseCGraph
|
30
|
+
from sage.graphs.base.static_sparse_backend cimport StaticSparseBackend
|
29
31
|
from sage.graphs.base.static_sparse_graph cimport short_digraph
|
30
32
|
from sage.graphs.base.static_sparse_graph cimport init_short_digraph
|
31
33
|
from sage.graphs.base.static_sparse_graph cimport free_short_digraph
|
@@ -414,6 +416,17 @@ def atoms_and_clique_separators(G, tree=False, rooted_tree=False, separators=Fal
|
|
414
416
|
{1} _{}_
|
415
417
|
/ /
|
416
418
|
{3} {2}
|
419
|
+
|
420
|
+
Immutable graphs::
|
421
|
+
|
422
|
+
sage: G = graphs.RandomGNP(10, .7)
|
423
|
+
sage: G._backend
|
424
|
+
<sage.graphs.base.sparse_graph.SparseGraphBackend ...>
|
425
|
+
sage: H = Graph(G, immutable=True)
|
426
|
+
sage: H._backend
|
427
|
+
<sage.graphs.base.static_sparse_backend.StaticSparseBackend ...>
|
428
|
+
sage: G.atoms_and_clique_separators() == H.atoms_and_clique_separators()
|
429
|
+
True
|
417
430
|
"""
|
418
431
|
cdef list A = [] # atoms
|
419
432
|
cdef list Sh = [] # separators
|
@@ -453,13 +466,20 @@ def atoms_and_clique_separators(G, tree=False, rooted_tree=False, separators=Fal
|
|
453
466
|
return A, Sc
|
454
467
|
|
455
468
|
cdef int N = G.order()
|
456
|
-
cdef list int_to_vertex = list(G)
|
457
469
|
|
458
470
|
# Copying the whole graph to obtain the list of neighbors quicker than by
|
459
471
|
# calling out_neighbors. This data structure is well documented in the
|
460
472
|
# module sage.graphs.base.static_sparse_graph
|
473
|
+
cdef list int_to_vertex
|
474
|
+
cdef StaticSparseCGraph cg
|
461
475
|
cdef short_digraph sd
|
462
|
-
|
476
|
+
if isinstance(G, StaticSparseBackend):
|
477
|
+
cg = <StaticSparseCGraph> G._cg
|
478
|
+
sd = <short_digraph> cg.g
|
479
|
+
int_to_vertex = cg._vertex_to_labels
|
480
|
+
else:
|
481
|
+
int_to_vertex = list(G)
|
482
|
+
init_short_digraph(sd, G, edge_labelled=False, vertex_list=int_to_vertex)
|
463
483
|
|
464
484
|
# variables for the manipulation of the short digraph
|
465
485
|
cdef uint32_t** p_vertices = sd.neighbors
|
@@ -575,7 +595,8 @@ def atoms_and_clique_separators(G, tree=False, rooted_tree=False, separators=Fal
|
|
575
595
|
for u in Cint:
|
576
596
|
active[u] = False
|
577
597
|
|
578
|
-
|
598
|
+
if not isinstance(G, StaticSparseBackend):
|
599
|
+
free_short_digraph(sd)
|
579
600
|
H.clear()
|
580
601
|
|
581
602
|
# We add the last atom
|
Binary file
|
Binary file
|
Binary file
|
@@ -132,7 +132,7 @@ Methods
|
|
132
132
|
# ****************************************************************************
|
133
133
|
|
134
134
|
|
135
|
-
def is_cartesian_product(g, certificate=False, relabeling=False):
|
135
|
+
def is_cartesian_product(g, certificate=False, relabeling=False, immutable=None):
|
136
136
|
r"""
|
137
137
|
Test whether the graph is a Cartesian product.
|
138
138
|
|
@@ -149,6 +149,10 @@ def is_cartesian_product(g, certificate=False, relabeling=False):
|
|
149
149
|
product graph. If `g` is not a Cartesian product, ``None`` is returned
|
150
150
|
instead.
|
151
151
|
|
152
|
+
- ``immutable`` -- boolean (default: ``None``); whether to create a
|
153
|
+
mutable/immutable graph. ``immutable=None`` (default) means that the
|
154
|
+
graph and its factors will behave the same way.
|
155
|
+
|
152
156
|
.. SEEALSO::
|
153
157
|
|
154
158
|
- :meth:`sage.graphs.generic_graph.GenericGraph.cartesian_product`
|
@@ -217,6 +221,19 @@ def is_cartesian_product(g, certificate=False, relabeling=False):
|
|
217
221
|
False
|
218
222
|
sage: Graph({0:[]}).is_cartesian_product()
|
219
223
|
False
|
224
|
+
|
225
|
+
Check the behaviour of parameter ``immutable``::
|
226
|
+
|
227
|
+
sage: G = graphs.Grid2dGraph(3, 3)
|
228
|
+
sage: any(f.is_immutable() for f in G.is_cartesian_product(certificate=True))
|
229
|
+
False
|
230
|
+
sage: all(f.is_immutable() for f in G.is_cartesian_product(certificate=True, immutable=True))
|
231
|
+
True
|
232
|
+
sage: G = G.copy(immutable=True)
|
233
|
+
sage: all(f.is_immutable() for f in G.is_cartesian_product(certificate=True))
|
234
|
+
True
|
235
|
+
sage: any(f.is_immutable() for f in G.is_cartesian_product(certificate=True, immutable=False))
|
236
|
+
False
|
220
237
|
"""
|
221
238
|
g._scream_if_not_simple()
|
222
239
|
if g.is_directed():
|
@@ -316,11 +333,13 @@ def is_cartesian_product(g, certificate=False, relabeling=False):
|
|
316
333
|
if len(edges) == 1:
|
317
334
|
return (False, None) if relabeling else False
|
318
335
|
|
336
|
+
if immutable is None:
|
337
|
+
immutable = g.is_immutable()
|
338
|
+
|
319
339
|
# Building the list of factors
|
320
340
|
cdef list factors = []
|
321
341
|
for cc in edges:
|
322
|
-
tmp = Graph()
|
323
|
-
tmp.add_edges(cc)
|
342
|
+
tmp = Graph(cc, format='list_of_edges', immutable=immutable)
|
324
343
|
factors.append(tmp.subgraph(vertices=tmp.connected_components(sort=False)[0]))
|
325
344
|
|
326
345
|
# Computing the product of these graphs
|
@@ -338,11 +357,10 @@ def is_cartesian_product(g, certificate=False, relabeling=False):
|
|
338
357
|
return isiso, dictt
|
339
358
|
if certificate:
|
340
359
|
return factors
|
341
|
-
|
342
|
-
return True
|
360
|
+
return True
|
343
361
|
|
344
362
|
|
345
|
-
def rooted_product(G, H, root=None):
|
363
|
+
def rooted_product(G, H, root=None, immutable=None):
|
346
364
|
r"""
|
347
365
|
Return the rooted product of `G` and `H`.
|
348
366
|
|
@@ -369,6 +387,15 @@ def rooted_product(G, H, root=None):
|
|
369
387
|
- :mod:`~sage.graphs.graph_decompositions.graph_products`
|
370
388
|
-- a module on graph products
|
371
389
|
|
390
|
+
INPUT:
|
391
|
+
|
392
|
+
- ``G, H`` -- two (di)graphs
|
393
|
+
|
394
|
+
- ``immutable`` -- boolean (default: ``None``); whether to create a
|
395
|
+
mutable/immutable (di)graph. When ``immutable=None`` (default) the rooted
|
396
|
+
product will be mutable if one of ``G`` or ``H`` is mutable and immutable
|
397
|
+
otherwise.
|
398
|
+
|
372
399
|
EXAMPLES:
|
373
400
|
|
374
401
|
The rooted product of two trees is a tree::
|
@@ -433,30 +460,49 @@ def rooted_product(G, H, root=None):
|
|
433
460
|
Traceback (most recent call last):
|
434
461
|
...
|
435
462
|
TypeError: the graphs should be both directed or both undirected
|
463
|
+
|
464
|
+
Check the behaviour of parameter ``immutable``::
|
465
|
+
|
466
|
+
sage: G = graphs.CycleGraph(4)
|
467
|
+
sage: H = graphs.PathGraph(3)
|
468
|
+
sage: G.rooted_product(H).is_immutable()
|
469
|
+
False
|
470
|
+
sage: G.rooted_product(H, immutable=True).is_immutable()
|
471
|
+
True
|
472
|
+
sage: G = G.copy(immutable=True)
|
473
|
+
sage: G.rooted_product(H).is_immutable()
|
474
|
+
False
|
475
|
+
sage: G.rooted_product(H, immutable=True).is_immutable()
|
476
|
+
True
|
477
|
+
sage: H = H.copy(immutable=True)
|
478
|
+
sage: G.rooted_product(H).is_immutable()
|
479
|
+
True
|
480
|
+
sage: G.rooted_product(H, immutable=False).is_immutable()
|
481
|
+
False
|
436
482
|
"""
|
437
483
|
G._scream_if_not_simple(allow_loops=True)
|
438
|
-
if G._directed
|
439
|
-
from sage.graphs.digraph import DiGraph
|
440
|
-
R = DiGraph(loops=(G.has_loops() or H.has_loops()))
|
441
|
-
elif (not G._directed) and (not H._directed):
|
442
|
-
from sage.graphs.graph import Graph
|
443
|
-
R = Graph(loops=(G.has_loops() or H.has_loops()))
|
444
|
-
else:
|
484
|
+
if G._directed is not H._directed:
|
445
485
|
raise TypeError('the graphs should be both directed or both undirected')
|
446
486
|
|
447
|
-
|
487
|
+
loops = G.has_loops() or H.has_loops()
|
488
|
+
name = f'Rooted product of {G} and {H}'
|
489
|
+
if immutable is None:
|
490
|
+
immutable = G.is_immutable() and H.is_immutable()
|
448
491
|
|
449
492
|
if not G or not H:
|
450
|
-
return
|
493
|
+
return G.parent()(loops=loops, name=name, immutable=immutable)
|
451
494
|
if root is None:
|
452
495
|
root = next(H.vertex_iterator())
|
453
496
|
elif root not in H:
|
454
497
|
raise ValueError("the specified root is not a vertex of H")
|
455
498
|
|
456
|
-
|
457
|
-
|
458
|
-
|
459
|
-
|
460
|
-
|
499
|
+
vertices = ((u, x) for u in G for x in H)
|
500
|
+
|
501
|
+
def edges():
|
502
|
+
for u, v in G.edge_iterator(labels=False):
|
503
|
+
yield ((u, root), (v, root))
|
504
|
+
for x, y in H.edge_iterator(labels=False):
|
505
|
+
yield from (((u, x), (u, y)) for u in G)
|
461
506
|
|
462
|
-
return
|
507
|
+
return G.parent()([vertices, edges()], format='vertices_and_edges',
|
508
|
+
name=name, loops=loops, immutable=immutable)
|
Binary file
|
Binary file
|
@@ -28,6 +28,7 @@ AUTHORS:
|
|
28
28
|
# ****************************************************************************
|
29
29
|
|
30
30
|
from libcpp.algorithm cimport swap
|
31
|
+
from cysignals.signals cimport sig_on, sig_off
|
31
32
|
from cython.operator cimport dereference as deref
|
32
33
|
|
33
34
|
from sage.graphs.base.c_graph cimport CGraphBackend
|
@@ -156,6 +157,19 @@ cdef void extended_lex_BFS(
|
|
156
157
|
[0[1[2]] [3] [4]]
|
157
158
|
sage: G.lex_BFS(algorithm="fast")
|
158
159
|
[0, 1, 2, 3, 4]
|
160
|
+
|
161
|
+
Check that :issue:`39934` is fixed::
|
162
|
+
|
163
|
+
sage: G = Graph(graphs.HouseGraph(), immutable=True)
|
164
|
+
sage: G.slice_decomposition()
|
165
|
+
[0[1[2]] [3] [4]]
|
166
|
+
sage: G.lex_BFS(algorithm="fast")
|
167
|
+
[0, 1, 2, 3, 4]
|
168
|
+
sage: G = Graph(graphs.HouseGraph(), sparse=False)
|
169
|
+
sage: G.slice_decomposition()
|
170
|
+
[0[1[2]] [3] [4]]
|
171
|
+
sage: G.lex_BFS(algorithm="fast")
|
172
|
+
[0, 1, 2, 3, 4]
|
159
173
|
"""
|
160
174
|
cdef int n = <int> cg.num_verts
|
161
175
|
# Variables for the partition refinement algorithm
|
@@ -182,6 +196,7 @@ cdef void extended_lex_BFS(
|
|
182
196
|
deref(xslice_len).resize(n)
|
183
197
|
part_len.resize(max_nparts)
|
184
198
|
if lex_label != NULL:
|
199
|
+
deref(lex_label).clear()
|
185
200
|
deref(lex_label).resize(n)
|
186
201
|
|
187
202
|
# Initialize the position of vertices in sigma (and compute max_degree)
|
@@ -197,7 +212,7 @@ cdef void extended_lex_BFS(
|
|
197
212
|
sigma[i] = v_int
|
198
213
|
deref(sigma_inv)[v_int] = i
|
199
214
|
i = i + 1
|
200
|
-
max_degree = max(max_degree, cg.
|
215
|
+
max_degree = max(max_degree, cg.out_degree(v_int))
|
201
216
|
|
202
217
|
# Variables needed to iterate over neighbors of a vertex
|
203
218
|
cdef int nneighbors
|
@@ -226,7 +241,7 @@ cdef void extended_lex_BFS(
|
|
226
241
|
v_int = sigma[i]
|
227
242
|
|
228
243
|
# Iterate over the neighbors of v
|
229
|
-
nneighbors = cg.out_neighbors_unsafe
|
244
|
+
nneighbors = cg.out_neighbors_unsafe(v_int, neighbors.data(), max_degree)
|
230
245
|
for k in range(nneighbors):
|
231
246
|
u_int = neighbors[k]
|
232
247
|
j = deref(sigma_inv)[u_int] # get the position of u
|
@@ -234,7 +249,7 @@ cdef void extended_lex_BFS(
|
|
234
249
|
continue # already taken care of
|
235
250
|
|
236
251
|
if lex_label != NULL:
|
237
|
-
deref(lex_label)[j].push_back
|
252
|
+
deref(lex_label)[j].push_back(v_int)
|
238
253
|
|
239
254
|
p = part_of[j] # get the part of u
|
240
255
|
l = part_head[p] # get the beginning of the part containing u
|
@@ -339,6 +354,14 @@ def slice_decomposition(G, initial_vertex=None):
|
|
339
354
|
Traceback (most recent call last):
|
340
355
|
...
|
341
356
|
ValueError: parameter G must be an undirected graph
|
357
|
+
|
358
|
+
TESTS:
|
359
|
+
|
360
|
+
Check that :issue:`39934` is fixed::
|
361
|
+
|
362
|
+
sage: G = Graph(graphs.HouseGraph(), immutable=True)
|
363
|
+
sage: G.slice_decomposition()
|
364
|
+
[0[1[2]] [3] [4]]
|
342
365
|
"""
|
343
366
|
return SliceDecomposition(G, initial_vertex=initial_vertex)
|
344
367
|
|
@@ -410,14 +433,17 @@ cdef class SliceDecomposition(SageObject):
|
|
410
433
|
cdef vector[vector[int]] lex_label
|
411
434
|
|
412
435
|
# Compute the slice decomposition using the extended lexBFS algorithm
|
436
|
+
sig_on()
|
413
437
|
extended_lex_BFS(cg, sigma, NULL, initial_v_int, NULL,
|
414
438
|
&(self.xslice_len), &lex_label)
|
439
|
+
sig_off()
|
415
440
|
|
416
441
|
# Translate the results with the actual vertices of the graph
|
417
442
|
self.sigma = tuple(Gbackend.vertex_label(v_int) for v_int in sigma)
|
418
|
-
self.sigma_inv = {v: i
|
419
|
-
self.lex_label = {i: tuple(Gbackend.vertex_label(v_int)
|
420
|
-
|
443
|
+
self.sigma_inv = {v: i for i, v in enumerate(self.sigma)}
|
444
|
+
self.lex_label = {i: tuple(Gbackend.vertex_label(v_int)
|
445
|
+
for v_int in lli)
|
446
|
+
for i, lli in enumerate(lex_label)}
|
421
447
|
|
422
448
|
def __eq__(self, other):
|
423
449
|
"""
|
@@ -480,7 +506,7 @@ cdef class SliceDecomposition(SageObject):
|
|
480
506
|
|
481
507
|
OUTPUT:
|
482
508
|
|
483
|
-
A
|
509
|
+
A dictionary with the keys:
|
484
510
|
|
485
511
|
* ``"pivot"`` -- the vertex `v` given as parameter
|
486
512
|
|
@@ -523,7 +549,7 @@ cdef class SliceDecomposition(SageObject):
|
|
523
549
|
'sequence': [['u'], ['y', 'z']],
|
524
550
|
'slice': ['u', 'y', 'z']}
|
525
551
|
|
526
|
-
Some values of the returned
|
552
|
+
Some values of the returned dictionary can be obtained via other
|
527
553
|
methods (:meth:`~slice`, :meth:`~xslice_sequence`,
|
528
554
|
:meth:`~active_edges`, :meth:`~lexicographic_label`)::
|
529
555
|
|
Binary file
|
Binary file
|
sage/graphs/graph_generators.py
CHANGED
@@ -36,11 +36,11 @@ def __append_to_doc(methods):
|
|
36
36
|
" :widths: 33, 33, 33\n"
|
37
37
|
" :delim: |\n\n")
|
38
38
|
|
39
|
-
h = (len(methods)+2)//3
|
39
|
+
h = (len(methods) + 2) // 3
|
40
40
|
# Reorders the list of methods for horizontal reading, the only one Sphinx understands
|
41
|
-
reordered_methods = [0]*3*h
|
41
|
+
reordered_methods = [0] * (3 * h)
|
42
42
|
for i, m in enumerate(methods):
|
43
|
-
reordered_methods[3*(i % h) + (i//h)] = m
|
43
|
+
reordered_methods[3 * (i % h) + (i // h)] = m
|
44
44
|
methods = reordered_methods
|
45
45
|
|
46
46
|
# Adding the list to the __doc__ string
|
@@ -845,7 +845,7 @@ class GraphGenerators:
|
|
845
845
|
if vertices is None:
|
846
846
|
raise NotImplementedError
|
847
847
|
if (len(degree_sequence) != vertices or sum(degree_sequence) % 2
|
848
|
-
or sum(degree_sequence) > vertices*(vertices - 1)):
|
848
|
+
or sum(degree_sequence) > vertices * (vertices - 1)):
|
849
849
|
raise ValueError("Invalid degree sequence.")
|
850
850
|
degree_sequence = sorted(degree_sequence)
|
851
851
|
if augment == 'edges':
|
@@ -1126,7 +1126,7 @@ class GraphGenerators:
|
|
1126
1126
|
|
1127
1127
|
EXAMPLES:
|
1128
1128
|
|
1129
|
-
The generator can be used to construct
|
1129
|
+
The generator can be used to construct bipartite graphs for testing,
|
1130
1130
|
one at a time (usually inside a loop). Or it can be used to
|
1131
1131
|
create an entire list all at once if there is sufficient memory
|
1132
1132
|
to contain it::
|
@@ -1510,7 +1510,7 @@ class GraphGenerators:
|
|
1510
1510
|
def _read_planar_code(self, code_input, immutable=False):
|
1511
1511
|
r"""
|
1512
1512
|
Return a generator for the plane graphs in planar code format in
|
1513
|
-
the file code_input (see [BM2016]_).
|
1513
|
+
the binary file ``code_input`` (see [BM2016]_).
|
1514
1514
|
|
1515
1515
|
A file with planar code starts with a header ``>>planar_code<<``.
|
1516
1516
|
After the header each graph is stored in the following way :
|
@@ -1524,7 +1524,7 @@ class GraphGenerators:
|
|
1524
1524
|
|
1525
1525
|
INPUT:
|
1526
1526
|
|
1527
|
-
- ``code_input`` -- a file containing valid planar code data
|
1527
|
+
- ``code_input`` -- a binary file containing valid planar code data
|
1528
1528
|
|
1529
1529
|
- ``immutable`` -- boolean (default: ``False``); whether to return
|
1530
1530
|
immutable or mutable graphs
|
@@ -1544,18 +1544,17 @@ class GraphGenerators:
|
|
1544
1544
|
|
1545
1545
|
EXAMPLES:
|
1546
1546
|
|
1547
|
-
The following example creates a small planar code
|
1548
|
-
reads it using the ``_read_planar_code`` method::
|
1547
|
+
The following example creates a small planar code binary
|
1548
|
+
file in memory and reads it using the ``_read_planar_code`` method::
|
1549
1549
|
|
1550
|
-
sage: from io import
|
1551
|
-
sage: code_input =
|
1552
|
-
sage:
|
1550
|
+
sage: from io import BytesIO
|
1551
|
+
sage: code_input = BytesIO()
|
1552
|
+
sage: n = code_input.write(b'>>planar_code<<')
|
1553
1553
|
sage: for c in [4,2,3,4,0,1,4,3,0,1,2,4,0,1,3,2,0]:
|
1554
|
-
....:
|
1555
|
-
sage:
|
1554
|
+
....: n = code_input.write(bytes('{:c}'.format(c),'ascii'))
|
1555
|
+
sage: n = code_input.seek(0)
|
1556
1556
|
sage: gen = graphs._read_planar_code(code_input)
|
1557
|
-
sage: l = list(gen)
|
1558
|
-
sage: l
|
1557
|
+
sage: l = list(gen); l
|
1559
1558
|
[Graph on 4 vertices]
|
1560
1559
|
sage: l[0].is_isomorphic(graphs.CompleteGraph(4))
|
1561
1560
|
True
|
@@ -1564,10 +1563,33 @@ class GraphGenerators:
|
|
1564
1563
|
2: [1, 4, 3],
|
1565
1564
|
3: [1, 2, 4],
|
1566
1565
|
4: [1, 3, 2]}
|
1566
|
+
|
1567
|
+
TESTS::
|
1568
|
+
|
1569
|
+
sage: from io import StringIO
|
1570
|
+
sage: code_input = StringIO()
|
1571
|
+
sage: n = code_input.write('>>planar_code<<')
|
1572
|
+
sage: n = code_input.seek(0)
|
1573
|
+
sage: list(graphs._read_planar_code(code_input))
|
1574
|
+
Traceback (most recent call last):
|
1575
|
+
...
|
1576
|
+
TypeError: not a binary file
|
1577
|
+
|
1578
|
+
sage: from io import BytesIO
|
1579
|
+
sage: code_input = BytesIO()
|
1580
|
+
sage: n = code_input.write(b'>>wrong header<<')
|
1581
|
+
sage: n = code_input.seek(0)
|
1582
|
+
sage: list(graphs._read_planar_code(code_input))
|
1583
|
+
Traceback (most recent call last):
|
1584
|
+
...
|
1585
|
+
TypeError: file has no valid planar code header
|
1567
1586
|
"""
|
1568
1587
|
# start of code to read planar code
|
1569
1588
|
header = code_input.read(15)
|
1570
|
-
|
1589
|
+
if not isinstance(header, bytes):
|
1590
|
+
raise TypeError('not a binary file')
|
1591
|
+
if header != b'>>planar_code<<':
|
1592
|
+
raise TypeError('file has no valid planar code header')
|
1571
1593
|
|
1572
1594
|
# read graph per graph
|
1573
1595
|
while True:
|
@@ -1720,10 +1742,7 @@ class GraphGenerators:
|
|
1720
1742
|
|
1721
1743
|
sp = subprocess.Popen(command, shell=True,
|
1722
1744
|
stdin=subprocess.PIPE, stdout=subprocess.PIPE,
|
1723
|
-
stderr=subprocess.PIPE, close_fds=True
|
1724
|
-
encoding='latin-1')
|
1725
|
-
|
1726
|
-
sp.stdout.reconfigure(newline='')
|
1745
|
+
stderr=subprocess.PIPE, close_fds=True)
|
1727
1746
|
|
1728
1747
|
yield from graphs._read_planar_code(sp.stdout, immutable=immutable)
|
1729
1748
|
|
@@ -1811,10 +1830,7 @@ class GraphGenerators:
|
|
1811
1830
|
|
1812
1831
|
sp = subprocess.Popen(command, shell=True,
|
1813
1832
|
stdin=subprocess.PIPE, stdout=subprocess.PIPE,
|
1814
|
-
stderr=subprocess.PIPE, close_fds=True
|
1815
|
-
encoding='latin-1')
|
1816
|
-
|
1817
|
-
sp.stdout.reconfigure(newline='')
|
1833
|
+
stderr=subprocess.PIPE, close_fds=True)
|
1818
1834
|
|
1819
1835
|
yield from graphs._read_planar_code(sp.stdout, immutable=immutable)
|
1820
1836
|
|
@@ -1999,14 +2015,11 @@ class GraphGenerators:
|
|
1999
2015
|
options)
|
2000
2016
|
sp = subprocess.Popen(command, shell=True,
|
2001
2017
|
stdin=subprocess.PIPE, stdout=subprocess.PIPE,
|
2002
|
-
stderr=subprocess.PIPE, close_fds=True
|
2003
|
-
encoding='latin-1')
|
2004
|
-
|
2005
|
-
sp.stdout.reconfigure(newline='')
|
2018
|
+
stderr=subprocess.PIPE, close_fds=True)
|
2006
2019
|
|
2007
2020
|
try:
|
2008
2021
|
yield from graphs._read_planar_code(sp.stdout, immutable=immutable)
|
2009
|
-
except AssertionError:
|
2022
|
+
except (TypeError, AssertionError):
|
2010
2023
|
raise AttributeError("invalid options '{}'".format(options))
|
2011
2024
|
|
2012
2025
|
def planar_graphs(self, order, minimum_degree=None,
|
@@ -2209,7 +2222,7 @@ class GraphGenerators:
|
|
2209
2222
|
raise ValueError("the number of edges cannot be less than order - 1")
|
2210
2223
|
edges = '-e:{}'.format(maximum_edges)
|
2211
2224
|
else:
|
2212
|
-
if minimum_edges > 3*order - 6:
|
2225
|
+
if minimum_edges > 3 * order - 6:
|
2213
2226
|
raise ValueError("the number of edges cannot be more than 3*order - 6")
|
2214
2227
|
if maximum_edges is None:
|
2215
2228
|
edges = '-e{}:'.format(minimum_edges)
|
@@ -2970,7 +2983,7 @@ def canaug_traverse_vert(g, aut_gens, max_verts, property, dig=False, loops=Fals
|
|
2970
2983
|
# in the case of graphs, there are n possibilities,
|
2971
2984
|
# and in the case of digraphs, there are 2*n.
|
2972
2985
|
if dig:
|
2973
|
-
possibilities = 2*n
|
2986
|
+
possibilities = 2 * n
|
2974
2987
|
else:
|
2975
2988
|
possibilities = n
|
2976
2989
|
num_roots = 2**possibilities
|
Binary file
|
@@ -18,7 +18,8 @@ from sage.misc.randstate cimport random
|
|
18
18
|
from sage.misc.randstate import set_random_seed
|
19
19
|
|
20
20
|
|
21
|
-
def RandomGNP(n, p, bint directed=False, bint loops=False, seed=None
|
21
|
+
def RandomGNP(n, p, bint directed=False, bint loops=False, seed=None,
|
22
|
+
immutable=False):
|
22
23
|
r"""
|
23
24
|
Return a random graph or a digraph on `n` nodes.
|
24
25
|
|
@@ -39,6 +40,9 @@ def RandomGNP(n, p, bint directed=False, bint loops=False, seed=None):
|
|
39
40
|
- ``seed`` -- a ``random.Random`` seed or a Python ``int`` for the random
|
40
41
|
number generator (default: ``None``)
|
41
42
|
|
43
|
+
- ``immutable`` -- boolean (default: ``False``); whether to return an
|
44
|
+
immutable or mutable (di)graph.
|
45
|
+
|
42
46
|
REFERENCES:
|
43
47
|
|
44
48
|
- [ER1959]_
|
@@ -52,7 +56,8 @@ def RandomGNP(n, p, bint directed=False, bint loops=False, seed=None):
|
|
52
56
|
sage: D.num_verts()
|
53
57
|
10
|
54
58
|
sage: D.edges(sort=True, labels=False)
|
55
|
-
[(0,
|
59
|
+
[(0, 3), (0, 6), (1, 7), (1, 9), (4, 6), (4, 7), (5, 4), (5, 6),
|
60
|
+
(5, 8), (5, 9), (6, 3), (7, 2), (7, 9), (8, 5), (9, 1), (9, 5)]
|
56
61
|
|
57
62
|
TESTS::
|
58
63
|
|
@@ -73,23 +78,18 @@ def RandomGNP(n, p, bint directed=False, bint loops=False, seed=None):
|
|
73
78
|
cdef int pp = int(round(float(p * RAND_MAX_f)))
|
74
79
|
|
75
80
|
if directed:
|
76
|
-
from sage.graphs.digraph import DiGraph
|
77
|
-
G = DiGraph(loops=loops)
|
81
|
+
from sage.graphs.digraph import DiGraph as GT
|
78
82
|
else:
|
79
|
-
from sage.graphs.graph import Graph
|
80
|
-
G = Graph()
|
81
83
|
if loops:
|
82
84
|
raise ValueError("parameter 'loops' can be set to True only when 'directed' is True")
|
83
|
-
|
85
|
+
from sage.graphs.graph import Graph as GT
|
84
86
|
|
85
|
-
|
87
|
+
name = 'Random' + ('Directed' if directed else '') + 'GNP(%s,%s)' % (n, p)
|
86
88
|
|
87
|
-
# Standard random GNP generator for Graph and DiGraph
|
88
89
|
cdef int i, j
|
89
|
-
for i in range(n)
|
90
|
-
|
91
|
-
|
92
|
-
if i != j or loops:
|
93
|
-
G.add_edge(i, j)
|
90
|
+
edges = ((i, j) for i in range(n)
|
91
|
+
for j in range((0 if directed else i + 1), n)
|
92
|
+
if (i != j or loops) and random() < pp)
|
94
93
|
|
95
|
-
return
|
94
|
+
return GT([range(n), edges], format='vertices_and_edges',
|
95
|
+
loops=directed and loops, name=name, immutable=immutable)
|
sage/graphs/graph_latex.py
CHANGED
@@ -430,7 +430,7 @@ Visit 'https://www.ctan.org/pkg/tkz-berge'.
|
|
430
430
|
""")
|
431
431
|
|
432
432
|
|
433
|
-
def have_tkz_graph():
|
433
|
+
def have_tkz_graph() -> bool:
|
434
434
|
r"""
|
435
435
|
Return ``True`` if the proper LaTeX packages for the ``tikzpicture``
|
436
436
|
environment are installed in the user's environment, namely ``tikz``,
|