passagemath-graphs 10.5.10__cp39-cp39-macosx_14_0_arm64.whl → 10.5.43__cp39-cp39-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.10.dist-info → passagemath_graphs-10.5.43.dist-info}/METADATA +126 -30
- passagemath_graphs-10.5.43.dist-info/RECORD +256 -0
- {passagemath_graphs-10.5.10.dist-info → passagemath_graphs-10.5.43.dist-info}/WHEEL +2 -1
- passagemath_graphs.dylibs/libgmp.10.dylib +0 -0
- sage/all__sagemath_graphs.py +5 -0
- sage/combinat/abstract_tree.py +1 -1
- sage/combinat/binary_tree.py +1 -1
- sage/combinat/cluster_algebra_quiver/all.py +1 -1
- sage/combinat/cluster_algebra_quiver/cluster_seed.py +28 -24
- sage/combinat/cluster_algebra_quiver/interact.py +4 -0
- sage/combinat/designs/MOLS_handbook_data.py +5 -5
- sage/combinat/designs/bibd.py +10 -9
- sage/combinat/designs/covering_array.py +3 -3
- sage/combinat/designs/covering_design.py +2 -1
- sage/combinat/designs/database.py +11 -10
- sage/combinat/designs/designs_pyx.cpython-39-darwin.so +0 -0
- sage/combinat/designs/designs_pyx.pyx +13 -45
- sage/combinat/designs/difference_family.py +6 -6
- sage/combinat/designs/difference_matrices.py +1 -1
- sage/combinat/designs/evenly_distributed_sets.cpython-39-darwin.so +0 -0
- sage/combinat/designs/evenly_distributed_sets.pyx +15 -22
- sage/combinat/designs/ext_rep.py +9 -14
- sage/combinat/designs/gen_quadrangles_with_spread.cpython-39-darwin.so +0 -0
- sage/combinat/designs/gen_quadrangles_with_spread.pyx +1 -1
- sage/combinat/designs/group_divisible_designs.py +1 -1
- sage/combinat/designs/incidence_structures.py +8 -8
- sage/combinat/designs/latin_squares.py +1 -1
- sage/combinat/designs/orthogonal_arrays_build_recursive.py +8 -7
- sage/combinat/designs/orthogonal_arrays_find_recursive.cpython-39-darwin.so +0 -0
- sage/combinat/designs/resolvable_bibd.py +1 -1
- sage/combinat/designs/steiner_quadruple_systems.py +1 -1
- sage/combinat/designs/subhypergraph_search.cpython-39-darwin.so +0 -0
- sage/combinat/designs/subhypergraph_search.pyx +9 -9
- sage/combinat/finite_state_machine_generators.py +2 -2
- sage/combinat/graph_path.py +3 -3
- sage/combinat/interval_posets.py +10 -10
- sage/combinat/ordered_tree.py +1 -1
- sage/combinat/posets/cartesian_product.py +1 -1
- sage/combinat/posets/d_complete.py +1 -1
- sage/combinat/posets/forest.py +1 -1
- sage/combinat/posets/hasse_cython.cpython-39-darwin.so +0 -0
- sage/combinat/posets/hasse_diagram.py +8 -6
- sage/combinat/posets/incidence_algebras.py +8 -8
- sage/combinat/posets/lattices.py +28 -4
- sage/combinat/posets/linear_extension_iterator.cpython-39-darwin.so +0 -0
- sage/combinat/posets/linear_extension_iterator.pyx +2 -0
- sage/combinat/posets/linear_extensions.py +7 -16
- sage/combinat/posets/moebius_algebra.py +1 -1
- sage/combinat/posets/poset_examples.py +1 -1
- sage/combinat/posets/posets.py +54 -56
- sage/combinat/rooted_tree.py +3 -3
- sage/combinat/tamari_lattices.py +1 -1
- sage/ext_data/kenzo/CP2.txt +45 -0
- sage/ext_data/kenzo/CP3.txt +349 -0
- sage/ext_data/kenzo/CP4.txt +4774 -0
- sage/ext_data/kenzo/README.txt +49 -0
- sage/ext_data/kenzo/S4.txt +20 -0
- sage/graphs/asteroidal_triples.cpython-39-darwin.so +0 -0
- sage/graphs/base/boost_graph.cpython-39-darwin.so +0 -0
- sage/graphs/base/boost_graph.pxd +1 -1
- sage/graphs/base/boost_graph.pyx +1 -1
- sage/graphs/base/c_graph.cpython-39-darwin.so +0 -0
- sage/graphs/base/c_graph.pxd +4 -4
- sage/graphs/base/c_graph.pyx +270 -184
- sage/graphs/base/dense_graph.cpython-39-darwin.so +0 -0
- sage/graphs/base/graph_backends.cpython-39-darwin.so +0 -0
- sage/graphs/base/sparse_graph.cpython-39-darwin.so +0 -0
- sage/graphs/base/static_dense_graph.cpython-39-darwin.so +0 -0
- sage/graphs/base/static_sparse_backend.cpython-39-darwin.so +0 -0
- sage/graphs/base/static_sparse_backend.pyx +93 -6
- sage/graphs/base/static_sparse_graph.cpython-39-darwin.so +0 -0
- sage/graphs/base/static_sparse_graph.pyx +1 -1
- sage/graphs/bipartite_graph.py +0 -1
- sage/graphs/centrality.cpython-39-darwin.so +0 -0
- sage/graphs/centrality.pyx +0 -0
- sage/graphs/comparability.cpython-39-darwin.so +0 -0
- sage/graphs/comparability.pyx +172 -138
- sage/graphs/connectivity.cpython-39-darwin.so +0 -0
- sage/graphs/connectivity.pyx +194 -18
- sage/graphs/convexity_properties.cpython-39-darwin.so +0 -0
- sage/graphs/digraph_generators.py +118 -74
- sage/graphs/distances_all_pairs.cpython-39-darwin.so +0 -0
- sage/graphs/distances_all_pairs.pyx +145 -27
- sage/graphs/edge_connectivity.cpython-39-darwin.so +0 -0
- sage/graphs/generators/basic.py +471 -130
- sage/graphs/generators/distance_regular.cpython-39-darwin.so +0 -0
- sage/graphs/generators/distance_regular.pyx +12 -12
- sage/graphs/generators/families.py +2 -2
- sage/graphs/generators/random.py +8 -13
- sage/graphs/generators/smallgraphs.py +12 -11
- sage/graphs/generic_graph.py +687 -265
- sage/graphs/generic_graph_pyx.cpython-39-darwin.so +0 -0
- sage/graphs/genus.cpython-39-darwin.so +0 -0
- sage/graphs/graph.py +12 -46
- sage/graphs/graph_coloring.cpython-39-darwin.so +0 -0
- sage/graphs/graph_database.py +1 -1
- sage/graphs/graph_decompositions/bandwidth.cpython-39-darwin.so +0 -0
- sage/graphs/graph_decompositions/clique_separators.cpython-39-darwin.so +0 -0
- sage/graphs/graph_decompositions/cutwidth.cpython-39-darwin.so +0 -0
- sage/graphs/graph_decompositions/fast_digraph.cpython-39-darwin.so +0 -0
- sage/graphs/graph_decompositions/graph_products.cpython-39-darwin.so +0 -0
- sage/graphs/graph_decompositions/modular_decomposition.cpython-39-darwin.so +0 -0
- sage/graphs/graph_decompositions/slice_decomposition.cpython-39-darwin.so +0 -0
- sage/graphs/graph_decompositions/tree_decomposition.cpython-39-darwin.so +0 -0
- sage/graphs/graph_decompositions/vertex_separation.cpython-39-darwin.so +0 -0
- sage/graphs/graph_generators.py +110 -55
- sage/graphs/graph_generators_pyx.cpython-39-darwin.so +0 -0
- sage/graphs/graph_latex.py +1 -1
- sage/graphs/graph_list.py +2 -3
- sage/graphs/graph_plot.py +225 -30
- sage/graphs/hyperbolicity.cpython-39-darwin.so +0 -0
- sage/graphs/independent_sets.cpython-39-darwin.so +0 -0
- sage/graphs/isgci.py +3 -8
- sage/graphs/isoperimetric_inequalities.cpython-39-darwin.so +0 -0
- sage/graphs/line_graph.cpython-39-darwin.so +0 -0
- sage/graphs/matching.py +14 -25
- sage/graphs/matching_covered_graph.py +871 -60
- sage/graphs/orientations.py +190 -134
- sage/graphs/path_enumeration.cpython-39-darwin.so +0 -0
- sage/graphs/path_enumeration.pyx +25 -25
- sage/graphs/spanning_tree.cpython-39-darwin.so +0 -0
- sage/graphs/strongly_regular_db.cpython-39-darwin.so +0 -0
- sage/graphs/strongly_regular_db.pyx +54 -52
- sage/graphs/traversals.cpython-39-darwin.so +0 -0
- sage/graphs/traversals.pyx +114 -46
- sage/graphs/trees.cpython-39-darwin.so +0 -0
- sage/graphs/views.cpython-39-darwin.so +0 -0
- sage/graphs/weakly_chordal.cpython-39-darwin.so +0 -0
- sage/groups/perm_gps/partn_ref/refinement_graphs.cpython-39-darwin.so +0 -0
- sage/knots/free_knotinfo_monoid.py +2 -3
- sage/knots/knot.py +1 -1
- sage/knots/knotinfo.py +4 -4
- sage/knots/link.py +58 -57
- sage/sandpiles/sandpile.py +2 -3
- sage/topology/cell_complex.py +1 -1
- sage/topology/cubical_complex.py +7 -7
- sage/topology/delta_complex.py +4 -4
- sage/topology/simplicial_complex.py +7 -22
- passagemath_graphs-10.5.10.dist-info/RECORD +0 -251
- {passagemath_graphs-10.5.10.dist-info → passagemath_graphs-10.5.43.dist-info}/top_level.txt +0 -0
sage/graphs/generators/basic.py
CHANGED
@@ -21,13 +21,18 @@ from sage.graphs.graph import Graph
|
|
21
21
|
from math import sin, cos, pi
|
22
22
|
|
23
23
|
|
24
|
-
def BullGraph():
|
24
|
+
def BullGraph(immutable=False):
|
25
25
|
r"""
|
26
26
|
Return a bull graph with 5 nodes.
|
27
27
|
|
28
28
|
A bull graph is named for its shape. It's a triangle with horns.
|
29
29
|
See the :wikipedia:`Bull_graph` for more information.
|
30
30
|
|
31
|
+
INPUT:
|
32
|
+
|
33
|
+
- ``immutable`` -- boolean (default: ``False``); whether to return an
|
34
|
+
immutable or a mutable graph
|
35
|
+
|
31
36
|
PLOTTING:
|
32
37
|
|
33
38
|
Upon construction, the position dictionary is filled to override the
|
@@ -85,13 +90,21 @@ def BullGraph():
|
|
85
90
|
True
|
86
91
|
sage: x * (x^2 - x - 3) * (x^2 + x - 1) == charpoly
|
87
92
|
True
|
93
|
+
|
94
|
+
TESTS:
|
95
|
+
|
96
|
+
Check the behavior of parameter ``immutable``::
|
97
|
+
|
98
|
+
sage: graphs.BullGraph(immutable=True).is_immutable()
|
99
|
+
True
|
88
100
|
"""
|
89
101
|
edge_list = [(0, 1), (0, 2), (1, 2), (1, 3), (2, 4)]
|
90
102
|
pos_dict = {0: (0, 0), 1: (-1, 1), 2: (1, 1), 3: (-2, 2), 4: (2, 2)}
|
91
|
-
return Graph(edge_list,
|
103
|
+
return Graph([range(5), edge_list], format='vertices_and_edges',
|
104
|
+
immutable=immutable, pos=pos_dict, name="Bull graph")
|
92
105
|
|
93
106
|
|
94
|
-
def ButterflyGraph():
|
107
|
+
def ButterflyGraph(immutable=False):
|
95
108
|
r"""
|
96
109
|
Return the butterfly graph.
|
97
110
|
|
@@ -104,6 +117,11 @@ def ButterflyGraph():
|
|
104
117
|
|
105
118
|
- :meth:`~sage.graphs.graph_generators.GraphGenerators.FriendshipGraph`
|
106
119
|
|
120
|
+
INPUT:
|
121
|
+
|
122
|
+
- ``immutable`` -- boolean (default: ``False``); whether to return an
|
123
|
+
immutable or a mutable graph
|
124
|
+
|
107
125
|
EXAMPLES:
|
108
126
|
|
109
127
|
The butterfly graph is a planar graph on 5 vertices and having 6 edges::
|
@@ -133,6 +151,13 @@ def ButterflyGraph():
|
|
133
151
|
True
|
134
152
|
sage: G.chromatic_number() # needs cliquer
|
135
153
|
3
|
154
|
+
|
155
|
+
TESTS:
|
156
|
+
|
157
|
+
Check the behavior of parameter ``immutable``::
|
158
|
+
|
159
|
+
sage: graphs.ButterflyGraph(immutable=True).is_immutable()
|
160
|
+
True
|
136
161
|
"""
|
137
162
|
edge_dict = {
|
138
163
|
0: [3, 4],
|
@@ -145,10 +170,11 @@ def ButterflyGraph():
|
|
145
170
|
2: [1, -1],
|
146
171
|
3: [-1, -1],
|
147
172
|
4: [0, 0]}
|
148
|
-
return Graph(edge_dict,
|
173
|
+
return Graph(edge_dict, format='dict_of_lists',
|
174
|
+
immutable=immutable, pos=pos_dict, name="Butterfly graph")
|
149
175
|
|
150
176
|
|
151
|
-
def CircularLadderGraph(n):
|
177
|
+
def CircularLadderGraph(n, immutable=False):
|
152
178
|
r"""
|
153
179
|
Return a circular ladder graph with `2 * n` nodes.
|
154
180
|
|
@@ -167,6 +193,13 @@ def CircularLadderGraph(n):
|
|
167
193
|
that all edges are visible (otherwise the 4 vertices of the graph would be
|
168
194
|
placed on a single line).
|
169
195
|
|
196
|
+
INPUT:
|
197
|
+
|
198
|
+
- ``n`` -- nonnegative integer
|
199
|
+
|
200
|
+
- ``immutable`` -- boolean (default: ``False``); whether to return an
|
201
|
+
immutable or a mutable graph
|
202
|
+
|
170
203
|
EXAMPLES:
|
171
204
|
|
172
205
|
Construct and show a circular ladder graph with 26 nodes::
|
@@ -188,20 +221,29 @@ def CircularLadderGraph(n):
|
|
188
221
|
....: j.append(n)
|
189
222
|
sage: G = graphics_array(j) # needs sage.plot
|
190
223
|
sage: G.show() # long time # needs sage.plot
|
224
|
+
|
225
|
+
TESTS::
|
226
|
+
|
227
|
+
sage: G = graphs.CircularLadderGraph(4, immutable=True)
|
228
|
+
sage: G.is_immutable()
|
229
|
+
True
|
191
230
|
"""
|
192
|
-
|
231
|
+
from itertools import chain
|
232
|
+
edges_1 = zip(range(n), chain(range(1, n), (0,)))
|
233
|
+
edges_2 = zip(range(n, 2 * n), chain(range(n + 1, 2 * n), (n,)))
|
234
|
+
edges_3 = ((i, i + n) for i in range(n))
|
235
|
+
G = Graph([range(2 * n), chain(edges_1, edges_2, edges_3)],
|
236
|
+
format='vertices_and_edges', immutable=immutable,
|
237
|
+
name="Circular Ladder graph")
|
193
238
|
G._circle_embedding(list(range(n)), radius=1, angle=pi/2)
|
194
239
|
if n == 2:
|
195
240
|
G._circle_embedding(list(range(4)), radius=1, angle=pi/2 + pi/8)
|
196
241
|
else:
|
197
242
|
G._circle_embedding(list(range(n, 2*n)), radius=2, angle=pi/2)
|
198
|
-
G.add_cycle(list(range(n)))
|
199
|
-
G.add_cycle(list(range(n, 2 * n)))
|
200
|
-
G.add_edges((i, i + n) for i in range(n))
|
201
243
|
return G
|
202
244
|
|
203
245
|
|
204
|
-
def ClawGraph():
|
246
|
+
def ClawGraph(immutable=False):
|
205
247
|
"""
|
206
248
|
Return a claw graph.
|
207
249
|
|
@@ -210,6 +252,11 @@ def ClawGraph():
|
|
210
252
|
|
211
253
|
PLOTTING: See :meth:`CompleteBipartiteGraph`.
|
212
254
|
|
255
|
+
INPUT:
|
256
|
+
|
257
|
+
- ``immutable`` -- boolean (default: ``False``); whether to return an
|
258
|
+
immutable or a mutable graph
|
259
|
+
|
213
260
|
EXAMPLES:
|
214
261
|
|
215
262
|
Show a Claw graph::
|
@@ -221,19 +268,34 @@ def ClawGraph():
|
|
221
268
|
sage: G = graphs.ClawGraph()
|
222
269
|
sage: G
|
223
270
|
Claw graph: Graph on 4 vertices
|
271
|
+
|
272
|
+
TESTS:
|
273
|
+
|
274
|
+
Check the behavior of parameter ``immutable``::
|
275
|
+
|
276
|
+
sage: graphs.ClawGraph(immutable=True).is_immutable()
|
277
|
+
True
|
224
278
|
"""
|
225
279
|
edge_list = [(0, 1), (0, 2), (0, 3)]
|
226
280
|
pos_dict = {0: (0, 1), 1: (-1, 0), 2: (0, 0), 3: (1, 0)}
|
227
|
-
return Graph(edge_list,
|
281
|
+
return Graph([range(4), edge_list], format='vertices_and_edges',
|
282
|
+
immutable=immutable, pos=pos_dict, name="Claw graph")
|
228
283
|
|
229
284
|
|
230
|
-
def CycleGraph(n):
|
285
|
+
def CycleGraph(n, immutable=False):
|
231
286
|
r"""
|
232
287
|
Return a cycle graph with `n` nodes.
|
233
288
|
|
234
289
|
A cycle graph is a basic structure which is also typically called an
|
235
290
|
`n`-gon.
|
236
291
|
|
292
|
+
INPUT:
|
293
|
+
|
294
|
+
- ``n`` -- nonnegative integer; the number of vertices of the cycle graph
|
295
|
+
|
296
|
+
- ``immutable`` -- boolean (default: ``False``); whether to return an
|
297
|
+
immutable or a mutable graph
|
298
|
+
|
237
299
|
PLOTTING: Upon construction, the position dictionary is filled to override
|
238
300
|
the spring-layout algorithm. By convention, each cycle graph will be
|
239
301
|
displayed with the first (0) node at the top, with the rest following in a
|
@@ -300,26 +362,40 @@ def CycleGraph(n):
|
|
300
362
|
Traceback (most recent call last):
|
301
363
|
...
|
302
364
|
ValueError: parameter n must be a positive integer
|
365
|
+
|
366
|
+
Check the behavior of parameter ``immutable``::
|
367
|
+
|
368
|
+
sage: graphs.CycleGraph(4, immutable=True).is_immutable()
|
369
|
+
True
|
303
370
|
"""
|
304
371
|
if n < 0:
|
305
372
|
raise ValueError("parameter n must be a positive integer")
|
306
373
|
|
307
|
-
|
374
|
+
from itertools import chain
|
375
|
+
edges = zip(range(n), chain(range(1, n), (0,))) if n > 1 else []
|
376
|
+
G = Graph([range(n), edges], format='vertices_and_edges',
|
377
|
+
immutable=immutable, name="Cycle graph")
|
308
378
|
if n == 1:
|
309
379
|
G.set_pos({0: (0, 0)})
|
310
380
|
else:
|
311
381
|
G._circle_embedding(list(range(n)), angle=pi/2)
|
312
|
-
G.add_cycle(list(range(n)))
|
313
382
|
return G
|
314
383
|
|
315
384
|
|
316
|
-
def CompleteGraph(n):
|
385
|
+
def CompleteGraph(n, immutable=False):
|
317
386
|
r"""
|
318
387
|
Return a complete graph on `n` nodes.
|
319
388
|
|
320
389
|
A Complete Graph is a graph in which all nodes are connected to all
|
321
390
|
other nodes.
|
322
391
|
|
392
|
+
INPUT:
|
393
|
+
|
394
|
+
- ``n`` -- nonnegative integer; the number of vertices of the complete graph
|
395
|
+
|
396
|
+
- ``immutable`` -- boolean (default: ``False``); whether to return an
|
397
|
+
immutable or a mutable graph
|
398
|
+
|
323
399
|
PLOTTING: Upon construction, the position dictionary is filled to
|
324
400
|
override the spring-layout algorithm. By convention, each complete
|
325
401
|
graph will be displayed with the first (0) node at the top, with
|
@@ -393,17 +469,26 @@ def CompleteGraph(n):
|
|
393
469
|
sage: posdict23 = graphs.CompleteGraph(23)
|
394
470
|
sage: spring23.show() # long time # needs sage.plot
|
395
471
|
sage: posdict23.show() # long time # needs sage.plot
|
472
|
+
|
473
|
+
TESTS:
|
474
|
+
|
475
|
+
Check the behavior of parameter ``immutable``::
|
476
|
+
|
477
|
+
sage: graphs.CompleteGraph(4, immutable=True).is_immutable()
|
478
|
+
True
|
396
479
|
"""
|
397
|
-
|
480
|
+
from itertools import combinations
|
481
|
+
G = Graph([range(n), combinations(range(n), 2)],
|
482
|
+
format='vertices_and_edges', immutable=immutable,
|
483
|
+
name="Complete graph")
|
398
484
|
if n == 1:
|
399
485
|
G.set_pos({0: (0, 0)})
|
400
486
|
else:
|
401
487
|
G._circle_embedding(list(range(n)), angle=pi/2)
|
402
|
-
G.add_edges((i, j) for i in range(n) for j in range(i + 1, n))
|
403
488
|
return G
|
404
489
|
|
405
490
|
|
406
|
-
def CorrelationGraph(seqs, alpha, include_anticorrelation):
|
491
|
+
def CorrelationGraph(seqs, alpha, include_anticorrelation, immutable=False):
|
407
492
|
r"""
|
408
493
|
Return a correlation graph with a node per sequence in ``seqs``.
|
409
494
|
|
@@ -423,6 +508,9 @@ def CorrelationGraph(seqs, alpha, include_anticorrelation):
|
|
423
508
|
- ``include_anticorrelation`` -- boolean; whether to add edges between nodes
|
424
509
|
with correlation coefficient less than ``-alpha`` or not
|
425
510
|
|
511
|
+
- ``immutable`` -- boolean (default: ``False``); whether to return an
|
512
|
+
immutable or a mutable graph
|
513
|
+
|
426
514
|
EXAMPLES::
|
427
515
|
|
428
516
|
sage: # needs numpy
|
@@ -437,6 +525,17 @@ def CorrelationGraph(seqs, alpha, include_anticorrelation):
|
|
437
525
|
[(0, 0, None), (0, 1, None), (1, 1, None), (2, 2, None)]
|
438
526
|
sage: CG3.edges(sort=False)
|
439
527
|
[(0, 0, None), (0, 1, None), (0, 2, None), (1, 1, None), (1, 2, None), (2, 2, None)]
|
528
|
+
|
529
|
+
TESTS:
|
530
|
+
|
531
|
+
Check the behavior of parameter ``immutable``::
|
532
|
+
|
533
|
+
sage: # needs numpy
|
534
|
+
sage: from sage.graphs.generators.basic import CorrelationGraph
|
535
|
+
sage: CorrelationGraph(data, 0.9, False, immutable=True).is_immutable()
|
536
|
+
True
|
537
|
+
sage: CorrelationGraph(data, 0.9, True, immutable=True).is_immutable()
|
538
|
+
True
|
440
539
|
"""
|
441
540
|
from numpy import corrcoef
|
442
541
|
from sage.matrix.constructor import Matrix
|
@@ -453,10 +552,11 @@ def CorrelationGraph(seqs, alpha, include_anticorrelation):
|
|
453
552
|
adjacency_matrix = Matrix(boolean_adjacency_matrix.astype(int))
|
454
553
|
|
455
554
|
# call graph constructor
|
456
|
-
return Graph(adjacency_matrix, format='adjacency_matrix',
|
555
|
+
return Graph(adjacency_matrix, format='adjacency_matrix',
|
556
|
+
immutable=immutable, name="Correlation Graph")
|
457
557
|
|
458
558
|
|
459
|
-
def CompleteBipartiteGraph(p, q, set_position=True):
|
559
|
+
def CompleteBipartiteGraph(p, q, set_position=True, immutable=False, name=None):
|
460
560
|
r"""
|
461
561
|
Return a Complete Bipartite Graph on `p + q` vertices.
|
462
562
|
|
@@ -472,6 +572,12 @@ def CompleteBipartiteGraph(p, q, set_position=True):
|
|
472
572
|
assign positions to the vertices so that the set of cardinality `p` is
|
473
573
|
on the line `y=1` and the set of cardinality `q` is on the line `y=0`.
|
474
574
|
|
575
|
+
- ``immutable`` -- boolean (default: ``False``); whether to return an
|
576
|
+
immutable or a mutable graph
|
577
|
+
|
578
|
+
- ``name`` -- string (default: ``None``); used as the name of the returned
|
579
|
+
graph when set
|
580
|
+
|
475
581
|
PLOTTING: Upon construction, the position dictionary is filled to override
|
476
582
|
the spring-layout algorithm. By convention, each complete bipartite graph
|
477
583
|
will be displayed with the first `p` nodes on the top row (at `y=1`) from
|
@@ -567,12 +673,24 @@ def CompleteBipartiteGraph(p, q, set_position=True):
|
|
567
673
|
Traceback (most recent call last):
|
568
674
|
...
|
569
675
|
ValueError: the arguments p(=1) and q(=-1) must be positive integers
|
676
|
+
|
677
|
+
Check the behavior of parameter ``immutable``::
|
678
|
+
|
679
|
+
sage: graphs.CompleteBipartiteGraph(1, 2, immutable=True).is_immutable()
|
680
|
+
True
|
681
|
+
|
682
|
+
Check the behavior of parameter ``name``::
|
683
|
+
|
684
|
+
sage: graphs.CompleteBipartiteGraph(1, 2, name='foo')
|
685
|
+
foo: Graph on 3 vertices
|
570
686
|
"""
|
571
687
|
if p < 0 or q < 0:
|
572
688
|
raise ValueError('the arguments p(={}) and q(={}) must be positive integers'.format(p, q))
|
573
689
|
|
574
|
-
|
575
|
-
|
690
|
+
name = f"Complete bipartite graph of order {p}+{q}" if name is None else name
|
691
|
+
edges = ((i, j) for i in range(p) for j in range(p, p + q))
|
692
|
+
G = Graph([range(p + q), edges], format='vertices_and_edges',
|
693
|
+
immutable=immutable, name=name)
|
576
694
|
|
577
695
|
# We now assign positions to vertices:
|
578
696
|
# - vertices 0,..,p-1 are placed on the line (0, 1) to (max(p, q), 1)
|
@@ -586,7 +704,7 @@ def CompleteBipartiteGraph(p, q, set_position=True):
|
|
586
704
|
return G
|
587
705
|
|
588
706
|
|
589
|
-
def CompleteMultipartiteGraph(L):
|
707
|
+
def CompleteMultipartiteGraph(L, immutable=False):
|
590
708
|
r"""
|
591
709
|
Return a complete multipartite graph.
|
592
710
|
|
@@ -594,6 +712,9 @@ def CompleteMultipartiteGraph(L):
|
|
594
712
|
|
595
713
|
- ``L`` -- list of integers; the respective sizes of the components
|
596
714
|
|
715
|
+
- ``immutable`` -- boolean (default: ``False``); whether to return an
|
716
|
+
immutable or a mutable graph
|
717
|
+
|
597
718
|
PLOTTING: Produce a layout of the vertices so that vertices in the same
|
598
719
|
vertex set are adjacent and clearly separated from vertices in other vertex
|
599
720
|
sets.
|
@@ -617,53 +738,74 @@ def CompleteMultipartiteGraph(L):
|
|
617
738
|
|
618
739
|
sage: g.chromatic_number() # needs cliquer
|
619
740
|
3
|
741
|
+
|
742
|
+
TESTS:
|
743
|
+
|
744
|
+
Prevent negative dimensions::
|
745
|
+
|
746
|
+
sage: graphs.CompleteMultipartiteGraph([1, -1, 2])
|
747
|
+
Traceback (most recent call last):
|
748
|
+
...
|
749
|
+
ValueError: the sizes of the components must be positive integers
|
750
|
+
|
751
|
+
Check the bahavior of parameter ``immutable``::
|
752
|
+
|
753
|
+
sage: graphs.CompleteMultipartiteGraph([1], immutable=True).is_immutable()
|
754
|
+
True
|
755
|
+
sage: graphs.CompleteMultipartiteGraph([1, 2], immutable=True).is_immutable()
|
756
|
+
True
|
757
|
+
sage: graphs.CompleteMultipartiteGraph([1, 2, 3], immutable=True).is_immutable()
|
758
|
+
True
|
620
759
|
"""
|
760
|
+
if any(p < 0 for p in L):
|
761
|
+
raise ValueError("the sizes of the components must be positive integers")
|
762
|
+
|
621
763
|
r = len(L) # getting the number of partitions
|
622
764
|
name = "Multipartite Graph with set sizes {}".format(L)
|
623
765
|
|
624
766
|
if not r:
|
625
|
-
|
626
|
-
|
627
|
-
g = Graph(L[0])
|
767
|
+
return Graph(name=name, immutable=immutable)
|
768
|
+
if r == 1:
|
769
|
+
g = Graph(L[0], immutable=immutable, name=name)
|
628
770
|
g._line_embedding(range(L[0]), first=(0, 0), last=(L[0], 0))
|
629
|
-
|
630
|
-
|
631
|
-
|
632
|
-
|
633
|
-
|
634
|
-
|
635
|
-
|
636
|
-
|
637
|
-
|
638
|
-
|
639
|
-
|
640
|
-
|
641
|
-
|
642
|
-
|
643
|
-
|
644
|
-
|
645
|
-
|
646
|
-
|
647
|
-
|
648
|
-
|
649
|
-
s = 0
|
650
|
-
for i in L:
|
651
|
-
g.add_clique(range(s, s + i))
|
652
|
-
s += i
|
653
|
-
|
654
|
-
g = g.complement()
|
655
|
-
g.set_pos(positions)
|
771
|
+
return g
|
772
|
+
if r == 2:
|
773
|
+
return CompleteBipartiteGraph(L[0], L[1], immutable=immutable, name=name)
|
774
|
+
|
775
|
+
# This position code gives bad results on bipartite or isolated graphs
|
776
|
+
points = [(cos(2 * pi * i / r), sin(2 * pi * i / r)) for i in range(r)]
|
777
|
+
slopes = [(points[(i + 1) % r][0] - points[i % r][0],
|
778
|
+
points[(i + 1) % r][1] - points[i % r][1]) for i in range(r)]
|
779
|
+
|
780
|
+
counter = 0
|
781
|
+
parts = []
|
782
|
+
positions = {}
|
783
|
+
for i, size in enumerate(L):
|
784
|
+
parts.append(list(range(counter, counter + size)))
|
785
|
+
vertex_set_size = size + 1
|
786
|
+
for j in range(1, vertex_set_size):
|
787
|
+
x = points[i][0] + slopes[i][0] * j / vertex_set_size
|
788
|
+
y = points[i][1] + slopes[i][1] * j / vertex_set_size
|
789
|
+
positions[counter] = (x, y)
|
790
|
+
counter += 1
|
656
791
|
|
657
|
-
|
658
|
-
|
792
|
+
from itertools import combinations
|
793
|
+
edges = ((a, b) for A, B in combinations(parts, 2) for a in A for b in B)
|
794
|
+
return Graph([range(counter), edges], format='vertices_and_edges',
|
795
|
+
immutable=immutable, pos=positions, name=name)
|
659
796
|
|
660
797
|
|
661
|
-
def DiamondGraph():
|
798
|
+
def DiamondGraph(immutable=False):
|
662
799
|
"""
|
663
800
|
Return a diamond graph with 4 nodes.
|
664
801
|
|
665
802
|
A diamond graph is a square with one pair of diagonal nodes connected.
|
666
803
|
|
804
|
+
INPUT:
|
805
|
+
|
806
|
+
- ``immutable`` -- boolean (default: ``False``); whether to return an
|
807
|
+
immutable or a mutable graph
|
808
|
+
|
667
809
|
PLOTTING: Upon construction, the position dictionary is filled to override
|
668
810
|
the spring-layout algorithm. By convention, the diamond graph is drawn as a
|
669
811
|
diamond, with the first node on top, second on the left, third on the right,
|
@@ -675,18 +817,31 @@ def DiamondGraph():
|
|
675
817
|
|
676
818
|
sage: g = graphs.DiamondGraph()
|
677
819
|
sage: g.show() # long time # needs sage.plot
|
820
|
+
|
821
|
+
TESTS:
|
822
|
+
|
823
|
+
Check the behavior of parameter ``immutable``::
|
824
|
+
|
825
|
+
sage: graphs.DiamondGraph(immutable=True).is_immutable()
|
826
|
+
True
|
678
827
|
"""
|
679
828
|
pos_dict = {0: (0, 1), 1: (-1, 0), 2: (1, 0), 3: (0, -1)}
|
680
829
|
edges = [(0, 1), (0, 2), (1, 2), (1, 3), (2, 3)]
|
681
|
-
return Graph(edges,
|
830
|
+
return Graph([range(4), edges], format='vertices_and_edges',
|
831
|
+
immutable=immutable, pos=pos_dict, name="Diamond Graph")
|
682
832
|
|
683
833
|
|
684
|
-
def GemGraph():
|
834
|
+
def GemGraph(immutable=False):
|
685
835
|
"""
|
686
836
|
Return a gem graph with 5 nodes.
|
687
837
|
|
688
838
|
A gem graph is a fan graph (4,1).
|
689
839
|
|
840
|
+
INPUT:
|
841
|
+
|
842
|
+
- ``immutable`` -- boolean (default: ``False``); whether to return an
|
843
|
+
immutable or a mutable graph
|
844
|
+
|
690
845
|
PLOTTING: Upon construction, the position dictionary is filled to override
|
691
846
|
the spring-layout algorithm. By convention, the gem graph is drawn as a gem,
|
692
847
|
with the sharp part on the bottom.
|
@@ -697,18 +852,31 @@ def GemGraph():
|
|
697
852
|
|
698
853
|
sage: g = graphs.GemGraph()
|
699
854
|
sage: g.show() # long time # needs sage.plot
|
855
|
+
|
856
|
+
TESTS:
|
857
|
+
|
858
|
+
Check the behavior of parameter ``immutable``::
|
859
|
+
|
860
|
+
sage: graphs.GemGraph(immutable=True).is_immutable()
|
861
|
+
True
|
700
862
|
"""
|
701
863
|
pos_dict = {0: (0.5, 0), 1: (0, 0.75), 2: (0.25, 1), 3: (0.75, 1), 4: (1, 0.75)}
|
702
864
|
edges = [(0, 1), (0, 2), (0, 3), (0, 4), (1, 2), (2, 3), (3, 4)]
|
703
|
-
return Graph(edges,
|
865
|
+
return Graph([range(5), edges], format='vertices_and_edges',
|
866
|
+
immutable=immutable, pos=pos_dict, name="Gem Graph")
|
704
867
|
|
705
868
|
|
706
|
-
def ForkGraph():
|
869
|
+
def ForkGraph(immutable=False):
|
707
870
|
"""
|
708
871
|
Return a fork graph with 5 nodes.
|
709
872
|
|
710
873
|
A fork graph, sometimes also called chair graph, is 5 vertex tree.
|
711
874
|
|
875
|
+
INPUT:
|
876
|
+
|
877
|
+
- ``immutable`` -- boolean (default: ``False``); whether to return an
|
878
|
+
immutable or a mutable graph
|
879
|
+
|
712
880
|
PLOTTING: Upon construction, the position dictionary is filled to override
|
713
881
|
the spring-layout algorithm. By convention, the fork graph is drawn as a
|
714
882
|
fork, with the sharp part on the bottom.
|
@@ -719,16 +887,29 @@ def ForkGraph():
|
|
719
887
|
|
720
888
|
sage: g = graphs.ForkGraph()
|
721
889
|
sage: g.show() # long time # needs sage.plot
|
890
|
+
|
891
|
+
TESTS:
|
892
|
+
|
893
|
+
Check the behavior of parameter ``immutable``::
|
894
|
+
|
895
|
+
sage: graphs.ForkGraph(immutable=True).is_immutable()
|
896
|
+
True
|
722
897
|
"""
|
723
898
|
pos_dict = {0: (0, 0), 1: (1, 0), 2: (0, 1), 3: (1, 1), 4: (0, 2)}
|
724
899
|
edges = [(0, 2), (2, 3), (3, 1), (2, 4)]
|
725
|
-
return Graph(edges,
|
900
|
+
return Graph([range(5), edges], format='vertices_and_edges',
|
901
|
+
immutable=immutable, pos=pos_dict, name="Fork Graph")
|
726
902
|
|
727
903
|
|
728
|
-
def DartGraph():
|
904
|
+
def DartGraph(immutable=False):
|
729
905
|
"""
|
730
906
|
Return a dart graph with 5 nodes.
|
731
907
|
|
908
|
+
INPUT:
|
909
|
+
|
910
|
+
- ``immutable`` -- boolean (default: ``False``); whether to return an
|
911
|
+
immutable or a mutable graph
|
912
|
+
|
732
913
|
PLOTTING: Upon construction, the position dictionary is filled to override
|
733
914
|
the spring-layout algorithm. By convention, the dart graph is drawn as a
|
734
915
|
dart, with the sharp part on the bottom.
|
@@ -739,19 +920,32 @@ def DartGraph():
|
|
739
920
|
|
740
921
|
sage: g = graphs.DartGraph()
|
741
922
|
sage: g.show() # long time # needs sage.plot
|
923
|
+
|
924
|
+
TESTS:
|
925
|
+
|
926
|
+
Check the behavior of parameter ``immutable``::
|
927
|
+
|
928
|
+
sage: graphs.DartGraph(immutable=True).is_immutable()
|
929
|
+
True
|
742
930
|
"""
|
743
931
|
pos_dict = {0: (0, 1), 1: (-1, 0), 2: (1, 0), 3: (0, -1), 4: (0, 0)}
|
744
932
|
edges = [(0, 1), (0, 2), (1, 4), (2, 4), (0, 4), (3, 4)]
|
745
|
-
return Graph(edges,
|
933
|
+
return Graph([range(5), edges], format='vertices_and_edges',
|
934
|
+
immutable=immutable, pos=pos_dict, name="Dart Graph")
|
746
935
|
|
747
936
|
|
748
|
-
def EmptyGraph():
|
937
|
+
def EmptyGraph(immutable=False):
|
749
938
|
"""
|
750
939
|
Return an empty graph (0 nodes and 0 edges).
|
751
940
|
|
752
941
|
This is useful for constructing graphs by adding edges and vertices
|
753
942
|
individually or in a loop.
|
754
943
|
|
944
|
+
INPUT:
|
945
|
+
|
946
|
+
- ``immutable`` -- boolean (default: ``False``); whether to return an
|
947
|
+
immutable or a mutable graph
|
948
|
+
|
755
949
|
PLOTTING: When plotting, this graph will use the default
|
756
950
|
spring-layout algorithm, unless a position dictionary is
|
757
951
|
specified.
|
@@ -780,11 +974,18 @@ def EmptyGraph():
|
|
780
974
|
sage: for i in range(1, 4):
|
781
975
|
....: empty2.add_edge(4,i) # add edges {[1:4],[2:4],[3:4]}
|
782
976
|
sage: empty2.show() # long time # needs sage.plot
|
977
|
+
|
978
|
+
TESTS:
|
979
|
+
|
980
|
+
Check the behavior of parameter ``immutable``::
|
981
|
+
|
982
|
+
sage: graphs.EmptyGraph(immutable=True).is_immutable()
|
983
|
+
True
|
783
984
|
"""
|
784
|
-
return Graph(sparse=True)
|
985
|
+
return Graph(sparse=True, immutable=immutable)
|
785
986
|
|
786
987
|
|
787
|
-
def ToroidalGrid2dGraph(p, q):
|
988
|
+
def ToroidalGrid2dGraph(p, q, immutable=False):
|
788
989
|
r"""
|
789
990
|
Return a toroidal 2-dimensional grid graph with `p \times q` nodes (`p` rows
|
790
991
|
and `q` columns).
|
@@ -793,6 +994,13 @@ def ToroidalGrid2dGraph(p, q):
|
|
793
994
|
grid graph with identical parameters to which are added the edges
|
794
995
|
`((i, 0), (i, q - 1))` and `((0, i), (p - 1, i))`.
|
795
996
|
|
997
|
+
INPUT:
|
998
|
+
|
999
|
+
- ``p, q`` -- nonnegative integers; the sides of the toroidal grid
|
1000
|
+
|
1001
|
+
- ``immutable`` -- boolean (default: ``False``); whether to return an
|
1002
|
+
immutable or a mutable graph
|
1003
|
+
|
796
1004
|
EXAMPLES:
|
797
1005
|
|
798
1006
|
The toroidal 2-dimensional grid is a regular graph, while the usual
|
@@ -806,14 +1014,21 @@ def ToroidalGrid2dGraph(p, q):
|
|
806
1014
|
False
|
807
1015
|
sage: tgrid.is_regular()
|
808
1016
|
True
|
1017
|
+
|
1018
|
+
TESTS:
|
1019
|
+
|
1020
|
+
Check the behavior of parameter ``immutable``::
|
1021
|
+
|
1022
|
+
sage: graphs.ToroidalGrid2dGraph(2, 3, immutable=True).is_immutable()
|
1023
|
+
True
|
809
1024
|
"""
|
810
|
-
|
1025
|
+
name = f"Toroidal 2D Grid Graph with parameters {p},{q}"
|
1026
|
+
g = Grid2dGraph(p, q, set_positions=True, immutable=False)
|
1027
|
+
g.name(name)
|
811
1028
|
|
812
1029
|
g.add_edges([((i, 0), (i, q - 1)) for i in range(p)])
|
813
1030
|
g.add_edges([((0, i), (p - 1, i)) for i in range(q)])
|
814
1031
|
|
815
|
-
g.name("Toroidal 2D Grid Graph with parameters {},{}".format(p, q))
|
816
|
-
|
817
1032
|
pos = g._pos
|
818
1033
|
p += 0.
|
819
1034
|
q += 0.
|
@@ -825,10 +1040,12 @@ def ToroidalGrid2dGraph(p, q):
|
|
825
1040
|
y += 0.25 * (1.0 + v * (v - q + 1) / vf)
|
826
1041
|
pos[u, v] = (x, y)
|
827
1042
|
|
1043
|
+
if immutable:
|
1044
|
+
return Graph(g, immutable=True, pos=g.get_pos(), name=name)
|
828
1045
|
return g
|
829
1046
|
|
830
1047
|
|
831
|
-
def Toroidal6RegularGrid2dGraph(p, q):
|
1048
|
+
def Toroidal6RegularGrid2dGraph(p, q, immutable=False):
|
832
1049
|
r"""
|
833
1050
|
Return a toroidal 6-regular grid.
|
834
1051
|
|
@@ -843,6 +1060,9 @@ def Toroidal6RegularGrid2dGraph(p, q):
|
|
843
1060
|
|
844
1061
|
- ``p``, ``q`` -- integers
|
845
1062
|
|
1063
|
+
- ``immutable`` -- boolean (default: ``False``); whether to return an
|
1064
|
+
immutable or a mutable graph
|
1065
|
+
|
846
1066
|
EXAMPLES:
|
847
1067
|
|
848
1068
|
The toroidal 6-regular grid on `25` elements::
|
@@ -871,19 +1091,27 @@ def Toroidal6RegularGrid2dGraph(p, q):
|
|
871
1091
|
Traceback (most recent call last):
|
872
1092
|
...
|
873
1093
|
ValueError: parameters p and q must be integers larger than 3
|
1094
|
+
|
1095
|
+
Check the behavior of parameter ``immutable``::
|
1096
|
+
|
1097
|
+
sage: graphs.Toroidal6RegularGrid2dGraph(4, 4, immutable=True).is_immutable()
|
1098
|
+
True
|
874
1099
|
"""
|
875
1100
|
if p <= 3 or q <= 3:
|
876
1101
|
raise ValueError("parameters p and q must be integers larger than 3")
|
877
1102
|
|
878
|
-
g = ToroidalGrid2dGraph(p, q)
|
1103
|
+
g = ToroidalGrid2dGraph(p, q, immutable=False)
|
879
1104
|
for u, v in g:
|
880
1105
|
g.add_edge((u, v), ((u + 1) % p, (v + 1) % q))
|
881
1106
|
|
882
|
-
|
1107
|
+
name = f"Toroidal Hexagonal Grid graph on {p}x{q} elements"
|
1108
|
+
if immutable:
|
1109
|
+
return Graph(g, immutable=True, pos=g.get_pos(), name=name)
|
1110
|
+
g.name(name)
|
883
1111
|
return g
|
884
1112
|
|
885
1113
|
|
886
|
-
def Grid2dGraph(p, q, set_positions=True):
|
1114
|
+
def Grid2dGraph(p, q, set_positions=True, immutable=False, name=None):
|
887
1115
|
r"""
|
888
1116
|
Return a `2`-dimensional grid graph with `p \times q` nodes (`p` rows and
|
889
1117
|
`q` columns).
|
@@ -899,6 +1127,12 @@ def Grid2dGraph(p, q, set_positions=True):
|
|
899
1127
|
- ``set_positions`` -- boolean (default: ``True``); whether to set the
|
900
1128
|
position of the nodes
|
901
1129
|
|
1130
|
+
- ``immutable`` -- boolean (default: ``False``); whether to return an
|
1131
|
+
immutable or a mutable graph
|
1132
|
+
|
1133
|
+
- ``name`` -- string (default: ``None``); used as the name of the returned
|
1134
|
+
graph when set
|
1135
|
+
|
902
1136
|
PLOTTING: Upon construction, the position dictionary is filled to override
|
903
1137
|
the spring-layout algorithm. By convention, nodes are labelled in (row,
|
904
1138
|
column) pairs with `(0, 0)` in the top left corner. Edges will always be
|
@@ -930,26 +1164,33 @@ def Grid2dGraph(p, q, set_positions=True):
|
|
930
1164
|
sage: g = graphs.Grid2dGraph(5,7)
|
931
1165
|
sage: g.name()
|
932
1166
|
'2D Grid Graph for [5, 7]'
|
1167
|
+
|
1168
|
+
Check the behavior of parameter ``ìmmutable``::
|
1169
|
+
|
1170
|
+
sage: graphs.Grid2dGraph(2, 3, immutable=True).is_immutable()
|
1171
|
+
True
|
1172
|
+
|
1173
|
+
Check the behavior of parameter ``name``::
|
1174
|
+
|
1175
|
+
sage: graphs.Grid2dGraph(2, 3, name='foo')
|
1176
|
+
foo: Graph on 6 vertices
|
933
1177
|
"""
|
934
1178
|
if p <= 0 or q <= 0:
|
935
1179
|
raise ValueError("parameters p and q must be positive integers")
|
936
1180
|
|
937
|
-
|
1181
|
+
vertices = ((i, j) for i in range(p) for j in range(q))
|
1182
|
+
from itertools import chain
|
1183
|
+
edges = chain((((i, j), (i + 1, j)) for i in range(p - 1) for j in range(q)),
|
1184
|
+
(((i, j), (i, j + 1)) for i in range(p) for j in range(q - 1)))
|
1185
|
+
pos_dict = None
|
938
1186
|
if set_positions:
|
939
|
-
for i in range(p)
|
940
|
-
|
941
|
-
|
942
|
-
|
943
|
-
pos_dict[i, j] = (x, y)
|
1187
|
+
pos_dict = {(i, j): (j, -i) for i in range(p) for j in range(q)}
|
1188
|
+
return Graph([vertices, edges], format='vertices_and_edges',
|
1189
|
+
immutable=immutable, pos=pos_dict,
|
1190
|
+
name=f"2D Grid Graph for [{p}, {q}]" if name is None else name)
|
944
1191
|
|
945
|
-
G = Graph(pos=pos_dict, name="2D Grid Graph for [{}, {}]".format(p, q))
|
946
|
-
G.add_vertices((i, j) for i in range(p) for j in range(q))
|
947
|
-
G.add_edges(((i, j), (i + 1, j)) for i in range(p - 1) for j in range(q))
|
948
|
-
G.add_edges(((i, j), (i, j + 1)) for i in range(p) for j in range(q - 1))
|
949
|
-
return G
|
950
1192
|
|
951
|
-
|
952
|
-
def GridGraph(dim_list):
|
1193
|
+
def GridGraph(dim_list, immutable=False):
|
953
1194
|
r"""
|
954
1195
|
Return an `n`-dimensional grid graph.
|
955
1196
|
|
@@ -958,6 +1199,9 @@ def GridGraph(dim_list):
|
|
958
1199
|
- ``dim_list`` -- list of integers representing the number of nodes to
|
959
1200
|
extend in each dimension
|
960
1201
|
|
1202
|
+
- ``immutable`` -- boolean (default: ``False``); whether to return an
|
1203
|
+
immutable or a mutable graph
|
1204
|
+
|
961
1205
|
PLOTTING: When plotting, this graph will use the default spring-layout
|
962
1206
|
algorithm, unless a position dictionary is specified.
|
963
1207
|
|
@@ -1029,36 +1273,52 @@ def GridGraph(dim_list):
|
|
1029
1273
|
Traceback (most recent call last):
|
1030
1274
|
...
|
1031
1275
|
ValueError: all dimensions must be positive integers
|
1276
|
+
|
1277
|
+
Check the behavior of parameter ``ìmmutable``::
|
1278
|
+
|
1279
|
+
sage: graphs.GridGraph([], immutable=True).is_immutable()
|
1280
|
+
True
|
1281
|
+
sage: graphs.GridGraph([2], immutable=True).is_immutable()
|
1282
|
+
True
|
1283
|
+
sage: graphs.GridGraph([2, 2], immutable=True).is_immutable()
|
1284
|
+
True
|
1285
|
+
sage: graphs.GridGraph([2, 2, 2], immutable=True).is_immutable()
|
1286
|
+
True
|
1032
1287
|
"""
|
1033
1288
|
dim = [int(a) for a in dim_list]
|
1034
1289
|
if any(a <= 0 for a in dim):
|
1035
1290
|
raise ValueError("all dimensions must be positive integers")
|
1036
1291
|
|
1037
|
-
|
1292
|
+
name = "Grid Graph for {}".format(dim)
|
1038
1293
|
n_dim = len(dim)
|
1294
|
+
if not n_dim:
|
1295
|
+
return Graph(name=name, immutable=immutable)
|
1039
1296
|
if n_dim == 1:
|
1040
1297
|
# Vertices are labeled from 0 to dim[0]-1
|
1041
|
-
|
1042
|
-
|
1298
|
+
return PathGraph(dim[0], immutable=immutable, name=name)
|
1299
|
+
if n_dim == 2:
|
1043
1300
|
# We use the Grid2dGraph generator to also get the positions
|
1044
|
-
|
1045
|
-
|
1046
|
-
|
1047
|
-
|
1048
|
-
|
1049
|
-
|
1050
|
-
|
1301
|
+
return Grid2dGraph(*dim, immutable=immutable, name=name)
|
1302
|
+
|
1303
|
+
# Now, n_dim > 2 and we don't set positions
|
1304
|
+
# Vertices are tuples of dimension n_dim, and the graph contains at
|
1305
|
+
# least vertex (0, 0, ..., 0)
|
1306
|
+
V = [tuple([0] * n_dim)]
|
1307
|
+
|
1308
|
+
def edges():
|
1309
|
+
from itertools import product
|
1310
|
+
for u in product(*[range(d) for d in dim]):
|
1051
1311
|
for i in range(n_dim):
|
1052
1312
|
if u[i] + 1 < dim[i]:
|
1053
1313
|
v = list(u)
|
1054
1314
|
v[i] = u[i] + 1
|
1055
|
-
|
1315
|
+
yield (u, tuple(v))
|
1056
1316
|
|
1057
|
-
|
1058
|
-
|
1317
|
+
return Graph([V, edges()], format='vertices_and_edges',
|
1318
|
+
immutable=immutable, name=name)
|
1059
1319
|
|
1060
1320
|
|
1061
|
-
def HouseGraph():
|
1321
|
+
def HouseGraph(immutable=False):
|
1062
1322
|
"""
|
1063
1323
|
Return a house graph with 5 nodes.
|
1064
1324
|
|
@@ -1073,19 +1333,32 @@ def HouseGraph():
|
|
1073
1333
|
connecting the roof to the wall. The fifth node is the top of the roof,
|
1074
1334
|
connected only to the third and fourth.
|
1075
1335
|
|
1336
|
+
INPUT:
|
1337
|
+
|
1338
|
+
- ``immutable`` -- boolean (default: ``False``); whether to return an
|
1339
|
+
immutable or a mutable graph
|
1340
|
+
|
1076
1341
|
EXAMPLES:
|
1077
1342
|
|
1078
1343
|
Construct and show a house graph::
|
1079
1344
|
|
1080
1345
|
sage: g = graphs.HouseGraph()
|
1081
1346
|
sage: g.show() # long time # needs sage.plot
|
1347
|
+
|
1348
|
+
TESTS:
|
1349
|
+
|
1350
|
+
Check the behavior of parameter ``immutable``::
|
1351
|
+
|
1352
|
+
sage: graphs.HouseGraph(immutable=True).is_immutable()
|
1353
|
+
True
|
1082
1354
|
"""
|
1083
1355
|
pos_dict = {0: (-1, 0), 1: (1, 0), 2: (-1, 1), 3: (1, 1), 4: (0, 2)}
|
1084
1356
|
edges = [(0, 1), (0, 2), (1, 3), (2, 3), (2, 4), (3, 4)]
|
1085
|
-
return Graph(edges,
|
1357
|
+
return Graph([range(5), edges], format='vertices_and_edges',
|
1358
|
+
immutable=immutable, pos=pos_dict, name="House Graph")
|
1086
1359
|
|
1087
1360
|
|
1088
|
-
def HouseXGraph():
|
1361
|
+
def HouseXGraph(immutable=False):
|
1089
1362
|
"""
|
1090
1363
|
Return a house X graph with 5 nodes.
|
1091
1364
|
|
@@ -1101,19 +1374,32 @@ def HouseXGraph():
|
|
1101
1374
|
connecting the roof to the wall. The fifth node is the top of the roof,
|
1102
1375
|
connected only to the third and fourth.
|
1103
1376
|
|
1377
|
+
INPUT:
|
1378
|
+
|
1379
|
+
- ``immutable`` -- boolean (default: ``False``); whether to return an
|
1380
|
+
immutable or a mutable graph
|
1381
|
+
|
1104
1382
|
EXAMPLES:
|
1105
1383
|
|
1106
1384
|
Construct and show a house X graph::
|
1107
1385
|
|
1108
1386
|
sage: g = graphs.HouseXGraph()
|
1109
1387
|
sage: g.show() # long time # needs sage.plot
|
1388
|
+
|
1389
|
+
TESTS:
|
1390
|
+
|
1391
|
+
Check the behavior of parameter ``immutable``::
|
1392
|
+
|
1393
|
+
sage: graphs.HouseXGraph(immutable=True).is_immutable()
|
1394
|
+
True
|
1110
1395
|
"""
|
1111
1396
|
pos_dict = {0: (-1, 0), 1: (1, 0), 2: (-1, 1), 3: (1, 1), 4: (0, 2)}
|
1112
1397
|
edges = [(0, 1), (0, 2), (0, 3), (1, 2), (1, 3), (2, 3), (2, 4), (3, 4)]
|
1113
|
-
return Graph(edges,
|
1398
|
+
return Graph([range(5), edges], format='vertices_and_edges',
|
1399
|
+
immutable=immutable, pos=pos_dict, name="House Graph")
|
1114
1400
|
|
1115
1401
|
|
1116
|
-
def LadderGraph(n):
|
1402
|
+
def LadderGraph(n, immutable=False):
|
1117
1403
|
r"""
|
1118
1404
|
Return a ladder graph with `2 * n` nodes.
|
1119
1405
|
|
@@ -1125,6 +1411,13 @@ def LadderGraph(n):
|
|
1125
1411
|
displayed horizontally, with the first n nodes displayed left to right on
|
1126
1412
|
the top horizontal line.
|
1127
1413
|
|
1414
|
+
INPUT:
|
1415
|
+
|
1416
|
+
- ``n`` -- a nonnegative integer; number of nodes is `2n`
|
1417
|
+
|
1418
|
+
- ``immutable`` -- boolean (default: ``False``); whether to return an
|
1419
|
+
immutable or a mutable graph
|
1420
|
+
|
1128
1421
|
EXAMPLES:
|
1129
1422
|
|
1130
1423
|
Construct and show a ladder graph with 14 nodes::
|
@@ -1147,21 +1440,28 @@ def LadderGraph(n):
|
|
1147
1440
|
....: j.append(n)
|
1148
1441
|
sage: G = graphics_array(j)
|
1149
1442
|
sage: G.show() # long time
|
1443
|
+
|
1444
|
+
TESTS:
|
1445
|
+
|
1446
|
+
Check the behavior of parameter ``immutable``::
|
1447
|
+
|
1448
|
+
sage: graphs.LadderGraph(4, immutable=True).is_immutable()
|
1449
|
+
True
|
1150
1450
|
"""
|
1151
|
-
pos_dict = {}
|
1152
|
-
for i in range(n):
|
1153
|
-
pos_dict[i] = (i, 1)
|
1451
|
+
pos_dict = {i: (i, 1) for i in range(n)}
|
1154
1452
|
for i in range(n, 2 * n):
|
1155
1453
|
x = i - n
|
1156
1454
|
pos_dict[i] = (x, 0)
|
1157
|
-
|
1158
|
-
|
1159
|
-
|
1160
|
-
|
1161
|
-
return
|
1455
|
+
from itertools import chain
|
1456
|
+
edges_1 = zip(range(n), range(1, n))
|
1457
|
+
edges_2 = zip(range(n, 2 * n), range(n + 1, 2 * n))
|
1458
|
+
edges_3 = ((i, i + n) for i in range(n))
|
1459
|
+
return Graph([range(2 * n), chain(edges_1, edges_2, edges_3)],
|
1460
|
+
format='vertices_and_edges', immutable=immutable,
|
1461
|
+
pos=pos_dict, name="Ladder graph")
|
1162
1462
|
|
1163
1463
|
|
1164
|
-
def MoebiusLadderGraph(n):
|
1464
|
+
def MoebiusLadderGraph(n, immutable=False):
|
1165
1465
|
r"""
|
1166
1466
|
Return a Möbius ladder graph with `2n` nodes
|
1167
1467
|
|
@@ -1185,6 +1485,9 @@ def MoebiusLadderGraph(n):
|
|
1185
1485
|
|
1186
1486
|
- ``n`` -- a nonnegative integer; number of nodes is `2n`
|
1187
1487
|
|
1488
|
+
- ``immutable`` -- boolean (default: ``False``); whether to return an
|
1489
|
+
immutable or a mutable graph
|
1490
|
+
|
1188
1491
|
OUTPUT:
|
1189
1492
|
|
1190
1493
|
- ``G`` -- a Möbius ladder graph of order `2n`; note that a
|
@@ -1222,6 +1525,11 @@ def MoebiusLadderGraph(n):
|
|
1222
1525
|
...
|
1223
1526
|
ValueError: parameter n must be a nonnegative integer
|
1224
1527
|
|
1528
|
+
Check the behavior of parameter ``immutable``::
|
1529
|
+
|
1530
|
+
sage: graphs.MoebiusLadderGraph(4, immutable=True).is_immutable()
|
1531
|
+
True
|
1532
|
+
|
1225
1533
|
REFERENCES:
|
1226
1534
|
|
1227
1535
|
- :wikipedia:`Möbius_ladder`
|
@@ -1238,14 +1546,17 @@ def MoebiusLadderGraph(n):
|
|
1238
1546
|
if n < 0:
|
1239
1547
|
raise ValueError("parameter n must be a nonnegative integer")
|
1240
1548
|
|
1241
|
-
|
1549
|
+
from itertools import chain
|
1550
|
+
edges_1 = zip(range(2 * n), chain(range(1, 2 * n), (0,)))
|
1551
|
+
edges_2 = ((i, i + n) for i in range(n))
|
1552
|
+
G = Graph([range(2 * n), chain(edges_1, edges_2)],
|
1553
|
+
format='vertices_and_edges', immutable=immutable,
|
1554
|
+
name="Moebius ladder graph")
|
1242
1555
|
G._circle_embedding(list(range(2 * n)), angle=pi/2)
|
1243
|
-
G.add_cycle(list(range(2 * n)))
|
1244
|
-
G.add_edges((i, i + n) for i in range(n))
|
1245
1556
|
return G
|
1246
1557
|
|
1247
1558
|
|
1248
|
-
def PathGraph(n, pos=None):
|
1559
|
+
def PathGraph(n, pos=None, immutable=False, name=None):
|
1249
1560
|
r"""
|
1250
1561
|
Return a path graph with `n` nodes.
|
1251
1562
|
|
@@ -1255,12 +1566,18 @@ def PathGraph(n, pos=None):
|
|
1255
1566
|
|
1256
1567
|
INPUT:
|
1257
1568
|
|
1258
|
-
- ``n`` -- number of nodes of the path graph
|
1569
|
+
- ``n`` -- nonnegative integer; number of nodes of the path graph
|
1259
1570
|
|
1260
1571
|
- ``pos`` -- string (default: ``None``); indicates the embedding to use
|
1261
1572
|
between 'circle', 'line' or the default algorithm. See the plotting
|
1262
1573
|
section below for more detail.
|
1263
1574
|
|
1575
|
+
- ``immutable`` -- boolean (default: ``False``); whether to return an
|
1576
|
+
immutable or a mutable graph
|
1577
|
+
|
1578
|
+
- ``name`` -- string (default: ``None``); used as the name of the returned
|
1579
|
+
graph when set
|
1580
|
+
|
1264
1581
|
PLOTTING: Upon construction, the position dictionary is filled to override
|
1265
1582
|
the spring-layout algorithm. By convention, the graph may be drawn in one of
|
1266
1583
|
two ways: The 'line' argument will draw the graph in a horizontal line (left
|
@@ -1272,23 +1589,19 @@ def PathGraph(n, pos=None):
|
|
1272
1589
|
argument) the graph will be drawn as a 'circle' if `10 < n < 41` and as a
|
1273
1590
|
'line' for all other `n`.
|
1274
1591
|
|
1275
|
-
EXAMPLES:
|
1592
|
+
EXAMPLES:
|
1276
1593
|
|
1277
|
-
|
1594
|
+
Show default drawing by size: 'line': `n \leq 10`::
|
1278
1595
|
|
1279
1596
|
sage: p = graphs.PathGraph(10)
|
1280
1597
|
sage: p.show() # long time # needs sage.plot
|
1281
1598
|
|
1282
|
-
'circle': `10 < n < 41
|
1283
|
-
|
1284
|
-
::
|
1599
|
+
'circle': `10 < n < 41`::
|
1285
1600
|
|
1286
1601
|
sage: q = graphs.PathGraph(25)
|
1287
1602
|
sage: q.show() # long time # needs sage.plot
|
1288
1603
|
|
1289
|
-
'line': `n \geq 41
|
1290
|
-
|
1291
|
-
::
|
1604
|
+
'line': `n \geq 41`::
|
1292
1605
|
|
1293
1606
|
sage: r = graphs.PathGraph(55)
|
1294
1607
|
sage: r.show() # long time # needs sage.plot
|
@@ -1297,8 +1610,22 @@ def PathGraph(n, pos=None):
|
|
1297
1610
|
|
1298
1611
|
sage: s = graphs.PathGraph(5,'circle')
|
1299
1612
|
sage: s.show() # long time # needs sage.plot
|
1613
|
+
|
1614
|
+
TESTS:
|
1615
|
+
|
1616
|
+
Check the behavior of parameter ``immutable``::
|
1617
|
+
|
1618
|
+
sage: graphs.PathGraph(4, immutable=True).is_immutable()
|
1619
|
+
True
|
1620
|
+
|
1621
|
+
Check the behavior of parameter ``name``::
|
1622
|
+
|
1623
|
+
sage: graphs.PathGraph(4, name='foo')
|
1624
|
+
foo: Graph on 4 vertices
|
1300
1625
|
"""
|
1301
|
-
|
1626
|
+
edges = ((i, i + 1) for i in range(n - 1))
|
1627
|
+
G = Graph([range(n), edges], format='vertices_and_edges',
|
1628
|
+
immutable=immutable, name="Path graph" if name is None else name)
|
1302
1629
|
|
1303
1630
|
pos_dict = {}
|
1304
1631
|
|
@@ -1348,17 +1675,23 @@ def PathGraph(n, pos=None):
|
|
1348
1675
|
counter += 1
|
1349
1676
|
G.set_pos(pos_dict)
|
1350
1677
|
|
1351
|
-
G.add_edges((i, i + 1) for i in range(n - 1))
|
1352
1678
|
return G
|
1353
1679
|
|
1354
1680
|
|
1355
|
-
def StarGraph(n):
|
1681
|
+
def StarGraph(n, immutable=False):
|
1356
1682
|
r"""
|
1357
1683
|
Return a star graph with `n + 1` nodes.
|
1358
1684
|
|
1359
1685
|
A Star graph is a basic structure where one node is connected to all other
|
1360
1686
|
nodes.
|
1361
1687
|
|
1688
|
+
INPUT:
|
1689
|
+
|
1690
|
+
- ``n`` -- a nonnegative integer; number of nodes is `n + 1`
|
1691
|
+
|
1692
|
+
- ``immutable`` -- boolean (default: ``False``); whether to return an
|
1693
|
+
immutable or a mutable graph
|
1694
|
+
|
1362
1695
|
PLOTTING: Upon construction, the position dictionary is filled to override
|
1363
1696
|
the spring-layout algorithm. By convention, each star graph will be
|
1364
1697
|
displayed with the first (0) node in the center, the second node (1) at the
|
@@ -1421,8 +1754,16 @@ def StarGraph(n):
|
|
1421
1754
|
....: j.append(n)
|
1422
1755
|
sage: G = graphics_array(j)
|
1423
1756
|
sage: G.show() # long time
|
1757
|
+
|
1758
|
+
TESTS:
|
1759
|
+
|
1760
|
+
Check the behavior of parameter ``immutable``::
|
1761
|
+
|
1762
|
+
sage: graphs.StarGraph(4, immutable=True).is_immutable()
|
1763
|
+
True
|
1424
1764
|
"""
|
1425
|
-
G = Graph({0: list(range(1, n + 1))},
|
1765
|
+
G = Graph({0: list(range(1, n + 1))}, format='dict_of_lists',
|
1766
|
+
immutable=immutable, name="Star graph")
|
1426
1767
|
G.set_pos({0: (0, 0)})
|
1427
1768
|
G._circle_embedding(list(range(1, n + 1)), angle=pi/2)
|
1428
1769
|
return G
|