passagemath-graphs 10.6.1rc1__cp310-cp310-musllinux_1_2_aarch64.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.
Files changed (260) hide show
  1. passagemath_graphs-10.6.1rc1.dist-info/METADATA +292 -0
  2. passagemath_graphs-10.6.1rc1.dist-info/RECORD +260 -0
  3. passagemath_graphs-10.6.1rc1.dist-info/WHEEL +5 -0
  4. passagemath_graphs-10.6.1rc1.dist-info/top_level.txt +2 -0
  5. passagemath_graphs.libs/libgcc_s-69c45f16.so.1 +0 -0
  6. passagemath_graphs.libs/libgmp-8e78bd9b.so.10.5.0 +0 -0
  7. passagemath_graphs.libs/libstdc++-1f1a71be.so.6.0.33 +0 -0
  8. sage/all__sagemath_graphs.py +39 -0
  9. sage/combinat/abstract_tree.py +2723 -0
  10. sage/combinat/all__sagemath_graphs.py +34 -0
  11. sage/combinat/binary_tree.py +5306 -0
  12. sage/combinat/cluster_algebra_quiver/all.py +22 -0
  13. sage/combinat/cluster_algebra_quiver/cluster_seed.py +5208 -0
  14. sage/combinat/cluster_algebra_quiver/interact.py +124 -0
  15. sage/combinat/cluster_algebra_quiver/mutation_class.py +625 -0
  16. sage/combinat/cluster_algebra_quiver/mutation_type.py +1555 -0
  17. sage/combinat/cluster_algebra_quiver/quiver.py +2290 -0
  18. sage/combinat/cluster_algebra_quiver/quiver_mutation_type.py +2468 -0
  19. sage/combinat/designs/MOLS_handbook_data.py +570 -0
  20. sage/combinat/designs/all.py +58 -0
  21. sage/combinat/designs/bibd.py +1655 -0
  22. sage/combinat/designs/block_design.py +1071 -0
  23. sage/combinat/designs/covering_array.py +269 -0
  24. sage/combinat/designs/covering_design.py +530 -0
  25. sage/combinat/designs/database.py +5615 -0
  26. sage/combinat/designs/design_catalog.py +122 -0
  27. sage/combinat/designs/designs_pyx.cpython-310-aarch64-linux-gnu.so +0 -0
  28. sage/combinat/designs/designs_pyx.pxd +21 -0
  29. sage/combinat/designs/designs_pyx.pyx +993 -0
  30. sage/combinat/designs/difference_family.py +3951 -0
  31. sage/combinat/designs/difference_matrices.py +279 -0
  32. sage/combinat/designs/evenly_distributed_sets.cpython-310-aarch64-linux-gnu.so +0 -0
  33. sage/combinat/designs/evenly_distributed_sets.pyx +661 -0
  34. sage/combinat/designs/ext_rep.py +1064 -0
  35. sage/combinat/designs/gen_quadrangles_with_spread.cpython-310-aarch64-linux-gnu.so +0 -0
  36. sage/combinat/designs/gen_quadrangles_with_spread.pyx +339 -0
  37. sage/combinat/designs/group_divisible_designs.py +361 -0
  38. sage/combinat/designs/incidence_structures.py +2357 -0
  39. sage/combinat/designs/latin_squares.py +581 -0
  40. sage/combinat/designs/orthogonal_arrays.py +2244 -0
  41. sage/combinat/designs/orthogonal_arrays_build_recursive.py +1780 -0
  42. sage/combinat/designs/orthogonal_arrays_find_recursive.cpython-310-aarch64-linux-gnu.so +0 -0
  43. sage/combinat/designs/orthogonal_arrays_find_recursive.pyx +967 -0
  44. sage/combinat/designs/resolvable_bibd.py +815 -0
  45. sage/combinat/designs/steiner_quadruple_systems.py +1306 -0
  46. sage/combinat/designs/subhypergraph_search.cpython-310-aarch64-linux-gnu.so +0 -0
  47. sage/combinat/designs/subhypergraph_search.pyx +530 -0
  48. sage/combinat/designs/twographs.py +306 -0
  49. sage/combinat/finite_state_machine.py +14874 -0
  50. sage/combinat/finite_state_machine_generators.py +2006 -0
  51. sage/combinat/graph_path.py +448 -0
  52. sage/combinat/interval_posets.py +3908 -0
  53. sage/combinat/nu_tamari_lattice.py +269 -0
  54. sage/combinat/ordered_tree.py +1446 -0
  55. sage/combinat/posets/all.py +46 -0
  56. sage/combinat/posets/bubble_shuffle.py +247 -0
  57. sage/combinat/posets/cartesian_product.py +493 -0
  58. sage/combinat/posets/d_complete.py +182 -0
  59. sage/combinat/posets/elements.py +273 -0
  60. sage/combinat/posets/forest.py +30 -0
  61. sage/combinat/posets/hasse_cython.cpython-310-aarch64-linux-gnu.so +0 -0
  62. sage/combinat/posets/hasse_cython.pyx +174 -0
  63. sage/combinat/posets/hasse_diagram.py +3672 -0
  64. sage/combinat/posets/hochschild_lattice.py +158 -0
  65. sage/combinat/posets/incidence_algebras.py +794 -0
  66. sage/combinat/posets/lattices.py +5117 -0
  67. sage/combinat/posets/linear_extension_iterator.cpython-310-aarch64-linux-gnu.so +0 -0
  68. sage/combinat/posets/linear_extension_iterator.pyx +292 -0
  69. sage/combinat/posets/linear_extensions.py +1037 -0
  70. sage/combinat/posets/mobile.py +275 -0
  71. sage/combinat/posets/moebius_algebra.py +776 -0
  72. sage/combinat/posets/poset_examples.py +2178 -0
  73. sage/combinat/posets/posets.py +9360 -0
  74. sage/combinat/rooted_tree.py +1070 -0
  75. sage/combinat/shard_order.py +239 -0
  76. sage/combinat/tamari_lattices.py +384 -0
  77. sage/combinat/yang_baxter_graph.py +923 -0
  78. sage/databases/all__sagemath_graphs.py +1 -0
  79. sage/databases/knotinfo_db.py +1231 -0
  80. sage/ext_data/all__sagemath_graphs.py +1 -0
  81. sage/ext_data/graphs/graph_plot_js.html +330 -0
  82. sage/ext_data/kenzo/CP2.txt +45 -0
  83. sage/ext_data/kenzo/CP3.txt +349 -0
  84. sage/ext_data/kenzo/CP4.txt +4774 -0
  85. sage/ext_data/kenzo/README.txt +49 -0
  86. sage/ext_data/kenzo/S4.txt +20 -0
  87. sage/graphs/all.py +42 -0
  88. sage/graphs/asteroidal_triples.cpython-310-aarch64-linux-gnu.so +0 -0
  89. sage/graphs/asteroidal_triples.pyx +320 -0
  90. sage/graphs/base/all.py +1 -0
  91. sage/graphs/base/boost_graph.cpython-310-aarch64-linux-gnu.so +0 -0
  92. sage/graphs/base/boost_graph.pxd +106 -0
  93. sage/graphs/base/boost_graph.pyx +3045 -0
  94. sage/graphs/base/c_graph.cpython-310-aarch64-linux-gnu.so +0 -0
  95. sage/graphs/base/c_graph.pxd +106 -0
  96. sage/graphs/base/c_graph.pyx +5096 -0
  97. sage/graphs/base/dense_graph.cpython-310-aarch64-linux-gnu.so +0 -0
  98. sage/graphs/base/dense_graph.pxd +28 -0
  99. sage/graphs/base/dense_graph.pyx +801 -0
  100. sage/graphs/base/graph_backends.cpython-310-aarch64-linux-gnu.so +0 -0
  101. sage/graphs/base/graph_backends.pxd +5 -0
  102. sage/graphs/base/graph_backends.pyx +797 -0
  103. sage/graphs/base/overview.py +85 -0
  104. sage/graphs/base/sparse_graph.cpython-310-aarch64-linux-gnu.so +0 -0
  105. sage/graphs/base/sparse_graph.pxd +90 -0
  106. sage/graphs/base/sparse_graph.pyx +1653 -0
  107. sage/graphs/base/static_dense_graph.cpython-310-aarch64-linux-gnu.so +0 -0
  108. sage/graphs/base/static_dense_graph.pxd +5 -0
  109. sage/graphs/base/static_dense_graph.pyx +1032 -0
  110. sage/graphs/base/static_sparse_backend.cpython-310-aarch64-linux-gnu.so +0 -0
  111. sage/graphs/base/static_sparse_backend.pxd +27 -0
  112. sage/graphs/base/static_sparse_backend.pyx +1583 -0
  113. sage/graphs/base/static_sparse_graph.cpython-310-aarch64-linux-gnu.so +0 -0
  114. sage/graphs/base/static_sparse_graph.pxd +37 -0
  115. sage/graphs/base/static_sparse_graph.pyx +1375 -0
  116. sage/graphs/bipartite_graph.py +2732 -0
  117. sage/graphs/centrality.cpython-310-aarch64-linux-gnu.so +0 -0
  118. sage/graphs/centrality.pyx +1038 -0
  119. sage/graphs/cographs.py +519 -0
  120. sage/graphs/comparability.cpython-310-aarch64-linux-gnu.so +0 -0
  121. sage/graphs/comparability.pyx +851 -0
  122. sage/graphs/connectivity.cpython-310-aarch64-linux-gnu.so +0 -0
  123. sage/graphs/connectivity.pxd +157 -0
  124. sage/graphs/connectivity.pyx +4813 -0
  125. sage/graphs/convexity_properties.cpython-310-aarch64-linux-gnu.so +0 -0
  126. sage/graphs/convexity_properties.pxd +16 -0
  127. sage/graphs/convexity_properties.pyx +870 -0
  128. sage/graphs/digraph.py +4754 -0
  129. sage/graphs/digraph_generators.py +1993 -0
  130. sage/graphs/distances_all_pairs.cpython-310-aarch64-linux-gnu.so +0 -0
  131. sage/graphs/distances_all_pairs.pxd +12 -0
  132. sage/graphs/distances_all_pairs.pyx +2938 -0
  133. sage/graphs/domination.py +1363 -0
  134. sage/graphs/dot2tex_utils.py +100 -0
  135. sage/graphs/edge_connectivity.cpython-310-aarch64-linux-gnu.so +0 -0
  136. sage/graphs/edge_connectivity.pyx +1215 -0
  137. sage/graphs/generators/all.py +1 -0
  138. sage/graphs/generators/basic.py +1769 -0
  139. sage/graphs/generators/chessboard.py +538 -0
  140. sage/graphs/generators/classical_geometries.py +1611 -0
  141. sage/graphs/generators/degree_sequence.py +235 -0
  142. sage/graphs/generators/distance_regular.cpython-310-aarch64-linux-gnu.so +0 -0
  143. sage/graphs/generators/distance_regular.pyx +2846 -0
  144. sage/graphs/generators/families.py +4759 -0
  145. sage/graphs/generators/intersection.py +565 -0
  146. sage/graphs/generators/platonic_solids.py +262 -0
  147. sage/graphs/generators/random.py +2623 -0
  148. sage/graphs/generators/smallgraphs.py +5741 -0
  149. sage/graphs/generators/world_map.py +724 -0
  150. sage/graphs/generic_graph.py +26867 -0
  151. sage/graphs/generic_graph_pyx.cpython-310-aarch64-linux-gnu.so +0 -0
  152. sage/graphs/generic_graph_pyx.pxd +34 -0
  153. sage/graphs/generic_graph_pyx.pyx +1673 -0
  154. sage/graphs/genus.cpython-310-aarch64-linux-gnu.so +0 -0
  155. sage/graphs/genus.pyx +622 -0
  156. sage/graphs/graph.py +9645 -0
  157. sage/graphs/graph_coloring.cpython-310-aarch64-linux-gnu.so +0 -0
  158. sage/graphs/graph_coloring.pyx +2284 -0
  159. sage/graphs/graph_database.py +1177 -0
  160. sage/graphs/graph_decompositions/all.py +1 -0
  161. sage/graphs/graph_decompositions/bandwidth.cpython-310-aarch64-linux-gnu.so +0 -0
  162. sage/graphs/graph_decompositions/bandwidth.pyx +428 -0
  163. sage/graphs/graph_decompositions/clique_separators.cpython-310-aarch64-linux-gnu.so +0 -0
  164. sage/graphs/graph_decompositions/clique_separators.pyx +616 -0
  165. sage/graphs/graph_decompositions/cutwidth.cpython-310-aarch64-linux-gnu.so +0 -0
  166. sage/graphs/graph_decompositions/cutwidth.pyx +753 -0
  167. sage/graphs/graph_decompositions/fast_digraph.cpython-310-aarch64-linux-gnu.so +0 -0
  168. sage/graphs/graph_decompositions/fast_digraph.pxd +13 -0
  169. sage/graphs/graph_decompositions/fast_digraph.pyx +212 -0
  170. sage/graphs/graph_decompositions/graph_products.cpython-310-aarch64-linux-gnu.so +0 -0
  171. sage/graphs/graph_decompositions/graph_products.pyx +508 -0
  172. sage/graphs/graph_decompositions/modular_decomposition.cpython-310-aarch64-linux-gnu.so +0 -0
  173. sage/graphs/graph_decompositions/modular_decomposition.pxd +27 -0
  174. sage/graphs/graph_decompositions/modular_decomposition.pyx +1536 -0
  175. sage/graphs/graph_decompositions/slice_decomposition.cpython-310-aarch64-linux-gnu.so +0 -0
  176. sage/graphs/graph_decompositions/slice_decomposition.pxd +18 -0
  177. sage/graphs/graph_decompositions/slice_decomposition.pyx +1106 -0
  178. sage/graphs/graph_decompositions/tree_decomposition.cpython-310-aarch64-linux-gnu.so +0 -0
  179. sage/graphs/graph_decompositions/tree_decomposition.pxd +17 -0
  180. sage/graphs/graph_decompositions/tree_decomposition.pyx +1996 -0
  181. sage/graphs/graph_decompositions/vertex_separation.cpython-310-aarch64-linux-gnu.so +0 -0
  182. sage/graphs/graph_decompositions/vertex_separation.pxd +5 -0
  183. sage/graphs/graph_decompositions/vertex_separation.pyx +1963 -0
  184. sage/graphs/graph_editor.py +82 -0
  185. sage/graphs/graph_generators.py +3314 -0
  186. sage/graphs/graph_generators_pyx.cpython-310-aarch64-linux-gnu.so +0 -0
  187. sage/graphs/graph_generators_pyx.pyx +95 -0
  188. sage/graphs/graph_input.py +812 -0
  189. sage/graphs/graph_latex.py +2064 -0
  190. sage/graphs/graph_list.py +410 -0
  191. sage/graphs/graph_plot.py +1756 -0
  192. sage/graphs/graph_plot_js.py +338 -0
  193. sage/graphs/hyperbolicity.cpython-310-aarch64-linux-gnu.so +0 -0
  194. sage/graphs/hyperbolicity.pyx +1704 -0
  195. sage/graphs/hypergraph_generators.py +364 -0
  196. sage/graphs/independent_sets.cpython-310-aarch64-linux-gnu.so +0 -0
  197. sage/graphs/independent_sets.pxd +13 -0
  198. sage/graphs/independent_sets.pyx +402 -0
  199. sage/graphs/isgci.py +1033 -0
  200. sage/graphs/isoperimetric_inequalities.cpython-310-aarch64-linux-gnu.so +0 -0
  201. sage/graphs/isoperimetric_inequalities.pyx +489 -0
  202. sage/graphs/line_graph.cpython-310-aarch64-linux-gnu.so +0 -0
  203. sage/graphs/line_graph.pyx +743 -0
  204. sage/graphs/lovasz_theta.py +77 -0
  205. sage/graphs/matching.py +1633 -0
  206. sage/graphs/matching_covered_graph.py +3590 -0
  207. sage/graphs/orientations.py +1489 -0
  208. sage/graphs/partial_cube.py +459 -0
  209. sage/graphs/path_enumeration.cpython-310-aarch64-linux-gnu.so +0 -0
  210. sage/graphs/path_enumeration.pyx +2040 -0
  211. sage/graphs/pq_trees.py +1129 -0
  212. sage/graphs/print_graphs.py +201 -0
  213. sage/graphs/schnyder.py +865 -0
  214. sage/graphs/spanning_tree.cpython-310-aarch64-linux-gnu.so +0 -0
  215. sage/graphs/spanning_tree.pyx +1457 -0
  216. sage/graphs/strongly_regular_db.cpython-310-aarch64-linux-gnu.so +0 -0
  217. sage/graphs/strongly_regular_db.pyx +3340 -0
  218. sage/graphs/traversals.cpython-310-aarch64-linux-gnu.so +0 -0
  219. sage/graphs/traversals.pxd +9 -0
  220. sage/graphs/traversals.pyx +1872 -0
  221. sage/graphs/trees.cpython-310-aarch64-linux-gnu.so +0 -0
  222. sage/graphs/trees.pxd +15 -0
  223. sage/graphs/trees.pyx +310 -0
  224. sage/graphs/tutte_polynomial.py +713 -0
  225. sage/graphs/views.cpython-310-aarch64-linux-gnu.so +0 -0
  226. sage/graphs/views.pyx +794 -0
  227. sage/graphs/weakly_chordal.cpython-310-aarch64-linux-gnu.so +0 -0
  228. sage/graphs/weakly_chordal.pyx +604 -0
  229. sage/groups/all__sagemath_graphs.py +1 -0
  230. sage/groups/perm_gps/all__sagemath_graphs.py +1 -0
  231. sage/groups/perm_gps/partn_ref/all__sagemath_graphs.py +1 -0
  232. sage/groups/perm_gps/partn_ref/refinement_graphs.cpython-310-aarch64-linux-gnu.so +0 -0
  233. sage/groups/perm_gps/partn_ref/refinement_graphs.pxd +38 -0
  234. sage/groups/perm_gps/partn_ref/refinement_graphs.pyx +1666 -0
  235. sage/knots/all.py +6 -0
  236. sage/knots/free_knotinfo_monoid.py +507 -0
  237. sage/knots/gauss_code.py +291 -0
  238. sage/knots/knot.py +682 -0
  239. sage/knots/knot_table.py +284 -0
  240. sage/knots/knotinfo.py +2900 -0
  241. sage/knots/link.py +4715 -0
  242. sage/sandpiles/all.py +13 -0
  243. sage/sandpiles/examples.py +225 -0
  244. sage/sandpiles/sandpile.py +6365 -0
  245. sage/topology/all.py +22 -0
  246. sage/topology/cell_complex.py +1214 -0
  247. sage/topology/cubical_complex.py +1976 -0
  248. sage/topology/delta_complex.py +1806 -0
  249. sage/topology/filtered_simplicial_complex.py +744 -0
  250. sage/topology/moment_angle_complex.py +823 -0
  251. sage/topology/simplicial_complex.py +5160 -0
  252. sage/topology/simplicial_complex_catalog.py +92 -0
  253. sage/topology/simplicial_complex_examples.py +1680 -0
  254. sage/topology/simplicial_complex_homset.py +205 -0
  255. sage/topology/simplicial_complex_morphism.py +836 -0
  256. sage/topology/simplicial_set.py +4102 -0
  257. sage/topology/simplicial_set_catalog.py +55 -0
  258. sage/topology/simplicial_set_constructions.py +2954 -0
  259. sage/topology/simplicial_set_examples.py +865 -0
  260. sage/topology/simplicial_set_morphism.py +1464 -0
sage/graphs/views.pyx ADDED
@@ -0,0 +1,794 @@
1
+ # sage_setup: distribution = sagemath-graphs
2
+ r"""
3
+ View classes
4
+
5
+ This module implements views for (di)graphs. A view is a read-only iterable
6
+ container enabling operations like ``for e in E`` and ``e in E``. It is updated
7
+ as the graph is updated. Hence, the graph should not be updated while iterating
8
+ through a view. Views can be iterated multiple times.
9
+
10
+ .. TODO::
11
+
12
+ - View of neighborhood to get open/close neighborhood of a vertex/set of
13
+ vertices
14
+
15
+ Classes
16
+ -------
17
+ """
18
+ # ****************************************************************************
19
+ # Copyright (C) 2019 David Coudert <david.coudert@inria.fr>
20
+ #
21
+ # This program is free software: you can redistribute it and/or modify
22
+ # it under the terms of the GNU General Public License as published by
23
+ # the Free Software Foundation, either version 2 of the License, or
24
+ # (at your option) any later version.
25
+ # https://www.gnu.org/licenses/
26
+ # ****************************************************************************
27
+
28
+
29
+ from itertools import islice
30
+ from sys import maxsize as sys_maxsize
31
+ from sage.graphs.generic_graph_pyx cimport GenericGraph_pyx
32
+
33
+ cdef class EdgesView:
34
+ r"""
35
+ EdgesView class.
36
+
37
+ This class implements a read-only iterable container of edges enabling
38
+ operations like ``for e in E`` and ``e in E``. An :class:`EdgesView` can be
39
+ iterated multiple times, and checking membership is done in constant
40
+ time. It avoids the construction of edge lists and so consumes little
41
+ memory. It is updated as the graph is updated. Hence, the graph should not
42
+ be updated while iterating through an :class:`EdgesView`.
43
+
44
+ INPUT:
45
+
46
+ - ``G`` -- a (di)graph
47
+
48
+ - ``vertices`` -- list (default: ``None``); an iterable container of
49
+ vertices or ``None``. When set, consider only edges incident to specified
50
+ vertices.
51
+
52
+ - ``vertices2`` -- list (default: ``None``); an iterable container of
53
+ vertices or ``None``. When set, consider only edges incident to specified
54
+ vertices. More precisely:
55
+
56
+ - When both ``vertices`` and ``vertices2`` are set, consider only edges
57
+ ``(u, v, l)`` with ``u`` in ``vertices`` and ``v`` in ``vertices2``.
58
+
59
+ - When ``vertices`` is ``None`` and ``vertices2`` is set, consider only
60
+ edges ``(u, v, l)`` with ``v`` in ``vertices2``.
61
+
62
+ - ``labels`` -- boolean (default: ``True``); if ``False``, each edge is
63
+ simply a pair ``(u, v)`` of vertices
64
+
65
+ - ``ignore_direction`` -- boolean (default: ``False``); only applies to
66
+ directed graphs. If ``True``, searches across edges in either direction.
67
+
68
+ - ``sort`` -- boolean (default: ``False``); whether to sort edges according
69
+ the ordering specified with parameter ``key``. If ``False`` (default),
70
+ edges are not sorted. This is the fastest and less memory consuming method
71
+ for iterating over edges.
72
+
73
+ - ``key`` -- a function (default: ``None``); a function that takes an edge
74
+ (a pair or a triple, according to the ``labels`` keyword) as its one
75
+ argument and returns a value that can be used for comparisons in the
76
+ sorting algorithm. This parameter is ignored when ``sort = False``.
77
+
78
+ - ``sort_vertices`` -- boolean (default: ``True``); whether to sort the
79
+ ends of the edges; not sorting the ends is faster;
80
+ only applicable to undirected graphs when ``sort`` is ``False``
81
+
82
+ .. WARNING::
83
+
84
+ Since any object may be a vertex, there is no guarantee that any two
85
+ vertices will be comparable, and thus no guarantee how two edges may
86
+ compare. With default objects for vertices (all integers), or when all
87
+ the vertices are of the same simple type, then there should not be a
88
+ problem with how the vertices will be sorted. However, if you need to
89
+ guarantee a total order for the sorting of the edges, use the ``key``
90
+ argument, as illustrated in the examples below.
91
+
92
+ EXAMPLES::
93
+
94
+ sage: from sage.graphs.views import EdgesView
95
+ sage: G = Graph([(0, 1, 'C'), (0, 2, 'A'), (1, 2, 'B')])
96
+ sage: E = EdgesView(G, sort=True); E
97
+ [(0, 1, 'C'), (0, 2, 'A'), (1, 2, 'B')]
98
+ sage: (1, 2) in E
99
+ False
100
+ sage: (1, 2, 'B') in E
101
+ True
102
+ sage: E = EdgesView(G, labels=False, sort=True); E
103
+ [(0, 1), (0, 2), (1, 2)]
104
+ sage: (1, 2) in E
105
+ True
106
+ sage: (1, 2, 'B') in E
107
+ False
108
+ sage: [e for e in E]
109
+ [(0, 1), (0, 2), (1, 2)]
110
+
111
+ An :class:`EdgesView` can be iterated multiple times::
112
+
113
+ sage: G = graphs.CycleGraph(3)
114
+ sage: print(E)
115
+ [(0, 1), (0, 2), (1, 2)]
116
+ sage: print(E)
117
+ [(0, 1), (0, 2), (1, 2)]
118
+ sage: for e in E:
119
+ ....: for ee in E:
120
+ ....: print((e, ee))
121
+ ((0, 1), (0, 1))
122
+ ((0, 1), (0, 2))
123
+ ((0, 1), (1, 2))
124
+ ((0, 2), (0, 1))
125
+ ((0, 2), (0, 2))
126
+ ((0, 2), (1, 2))
127
+ ((1, 2), (0, 1))
128
+ ((1, 2), (0, 2))
129
+ ((1, 2), (1, 2))
130
+
131
+ We can check if a view is empty::
132
+
133
+ sage: E = EdgesView(graphs.CycleGraph(3), sort=False)
134
+ sage: if E:
135
+ ....: print('not empty')
136
+ not empty
137
+ sage: E = EdgesView(Graph(), sort=False)
138
+ sage: if not E:
139
+ ....: print('empty')
140
+ empty
141
+
142
+ When ``sort`` is ``True``, edges are sorted by default in the default
143
+ fashion::
144
+
145
+ sage: G = Graph([(0, 1, 'C'), (0, 2, 'A'), (1, 2, 'B')])
146
+ sage: E = EdgesView(G, sort=True); E
147
+ [(0, 1, 'C'), (0, 2, 'A'), (1, 2, 'B')]
148
+
149
+ This can be overridden by specifying a key function. This first example just
150
+ ignores the labels in the third component of the triple::
151
+
152
+ sage: G = Graph([(0, 1, 'C'), (0, 2, 'A'), (1, 2, 'B')])
153
+ sage: E = EdgesView(G, sort=True, key=lambda x: (x[1], -x[0])); E
154
+ [(0, 1, 'C'), (1, 2, 'B'), (0, 2, 'A')]
155
+
156
+ We can also sort according to the labels::
157
+
158
+ sage: G = Graph([(0, 1, 'C'), (0, 2, 'A'), (1, 2, 'B')])
159
+ sage: E = EdgesView(G, sort=True, key=lambda x: x[2]); E
160
+ [(0, 2, 'A'), (1, 2, 'B'), (0, 1, 'C')]
161
+
162
+ Not sorting the ends of the vertices::
163
+
164
+ sage: G = Graph()
165
+ sage: G.add_edges([[1,2], [2,3], [0,3]])
166
+ sage: E = EdgesView(G, sort=False, sort_vertices=False); E
167
+ [(3, 0, None), (2, 1, None), (3, 2, None)]
168
+
169
+ With a directed graph::
170
+
171
+ sage: G = digraphs.DeBruijn(2, 2) # needs sage.combinat
172
+ sage: E = EdgesView(G, labels=False, sort=True); E # needs sage.combinat
173
+ [('00', '00'), ('00', '01'), ('01', '10'), ('01', '11'),
174
+ ('10', '00'), ('10', '01'), ('11', '10'), ('11', '11')]
175
+ sage: E = EdgesView(G, labels=False, sort=True, key=lambda e:(e[1], e[0])); E # needs sage.combinat
176
+ [('00', '00'), ('10', '00'), ('00', '01'), ('10', '01'),
177
+ ('01', '10'), ('11', '10'), ('01', '11'), ('11', '11')]
178
+
179
+ We can consider only edges incident to a specified set of vertices::
180
+
181
+ sage: G = graphs.CycleGraph(5)
182
+ sage: E = EdgesView(G, vertices=[0, 1], labels=False, sort=True); E
183
+ [(0, 1), (0, 4), (1, 2)]
184
+ sage: E = EdgesView(G, vertices=[0], labels=False, sort=True); E
185
+ [(0, 1), (0, 4)]
186
+ sage: E = EdgesView(G, vertices=None, labels=False, sort=True); E
187
+ [(0, 1), (0, 4), (1, 2), (2, 3), (3, 4)]
188
+
189
+ sage: G = digraphs.Circuit(5)
190
+ sage: E = EdgesView(G, vertices=[0, 1], labels=False, sort=True); E
191
+ [(0, 1), (1, 2)]
192
+
193
+ We can ignore the direction of the edges of a directed graph, in which case
194
+ we search across edges in either direction::
195
+
196
+ sage: G = digraphs.Circuit(5)
197
+ sage: E = EdgesView(G, vertices=[0, 1], labels=False, sort=True, ignore_direction=False); E
198
+ [(0, 1), (1, 2)]
199
+ sage: (1, 0) in E
200
+ False
201
+ sage: E = EdgesView(G, vertices=[0, 1], labels=False, sort=True, ignore_direction=True); E
202
+ [(0, 1), (0, 1), (1, 2), (4, 0)]
203
+ sage: (1, 0) in E
204
+ True
205
+ sage: G.has_edge(1, 0)
206
+ False
207
+
208
+ We can consider only the edges between two specified sets of vertices::
209
+
210
+ sage: G = Graph([(0, 1), (1, 2)])
211
+ sage: E = EdgesView(G, vertices=[0], vertices2=[1], labels=False)
212
+ sage: (0, 1) in E and (1, 2) not in E
213
+ True
214
+ sage: E = EdgesView(G, vertices=[0], labels=False)
215
+ sage: (0, 1) in E and (1, 2) not in E
216
+ True
217
+ sage: E = EdgesView(G, vertices2=[1], labels=False)
218
+ sage: (0, 1) in E and (1, 2) in E
219
+ True
220
+ sage: D = DiGraph([(0, 1), (1, 2)])
221
+ sage: E = EdgesView(D, vertices=[0], vertices2=[1], labels=False)
222
+ sage: (0, 1) in E and (1, 2) not in E
223
+ True
224
+ sage: EdgesView(D, vertices=[1], vertices2=[0], labels=False)
225
+ []
226
+ sage: E = EdgesView(D, vertices=[1], vertices2=[0], labels=False, ignore_direction=True)
227
+ sage: (0, 1) in E and (1, 2) not in E
228
+ True
229
+ sage: E = EdgesView(D, vertices=[0], labels=False)
230
+ sage: (0, 1) in E and (1, 2) not in E
231
+ True
232
+ sage: E = EdgesView(D, vertices2=[1], labels=False)
233
+ sage: (0, 1) in E and (1, 2) not in E
234
+ True
235
+ sage: E = EdgesView(D, vertices2=[1], labels=False, ignore_direction=True)
236
+ sage: (0, 1) in E and (1, 2) in E
237
+ True
238
+
239
+ A view is updated as the graph is updated::
240
+
241
+ sage: G = Graph()
242
+ sage: E = EdgesView(G, vertices=[0, 3], labels=False, sort=True); E
243
+ []
244
+ sage: G.add_edges([(0, 1), (1, 2)])
245
+ sage: E
246
+ [(0, 1)]
247
+ sage: G.add_edge(2, 3)
248
+ sage: E
249
+ [(0, 1), (2, 3)]
250
+
251
+ Hence, the graph should not be updated while iterating through a view::
252
+
253
+ sage: G = Graph([('a', 'b'), ('b', 'c')])
254
+ sage: E = EdgesView(G, labels=False, sort=False); E
255
+ [('a', 'b'), ('b', 'c')]
256
+ sage: for u, v in E:
257
+ ....: G.add_edge(u + u, v + v)
258
+ Traceback (most recent call last):
259
+ ...
260
+ RuntimeError: dictionary changed size during iteration
261
+
262
+ Two :class:`EdgesView` are considered equal if they report either both
263
+ directed, or both undirected edges, they have the same settings for
264
+ ``ignore_direction``, they have the same settings for ``labels``, and they
265
+ report the same edges in the same order::
266
+
267
+ sage: G = graphs.HouseGraph()
268
+ sage: EG = EdgesView(G, sort=False)
269
+ sage: H = Graph(EG)
270
+ sage: EH = EdgesView(H, sort=False)
271
+ sage: EG == EH
272
+ True
273
+ sage: G.add_edge(0, 10)
274
+ sage: EG = EdgesView(G, sort=False)
275
+ sage: EG == EH
276
+ False
277
+ sage: H.add_edge(0, 10)
278
+ sage: EH = EdgesView(H, sort=False)
279
+ sage: EG == EH
280
+ True
281
+ sage: H = G.strong_orientation()
282
+ sage: EH = EdgesView(H, sort=False)
283
+ sage: EG == EH
284
+ False
285
+
286
+ The sum of two :class:`EdgesView` is a list containing the edges in both
287
+ :class:`EdgesView`::
288
+
289
+ sage: E1 = EdgesView(Graph([(0, 1)]), labels=False, sort=False)
290
+ sage: E2 = EdgesView(Graph([(2, 3)]), labels=False, sort=False)
291
+ sage: E1 + E2
292
+ [(0, 1), (2, 3)]
293
+ sage: E2 + E1
294
+ [(2, 3), (0, 1)]
295
+
296
+ Recall that a :class:`EdgesView` is read-only and that this method
297
+ returns a list::
298
+
299
+ sage: E1 += E2
300
+ sage: type(E1) is list
301
+ True
302
+
303
+ It is also possible to get the sum a :class:`EdgesView` with itself `n`
304
+ times::
305
+
306
+ sage: E = EdgesView(Graph([(0, 1), (2, 3)]), labels=False, sort=True)
307
+ sage: E * 3
308
+ [(0, 1), (2, 3), (0, 1), (2, 3), (0, 1), (2, 3)]
309
+ sage: 3 * E
310
+ [(0, 1), (2, 3), (0, 1), (2, 3), (0, 1), (2, 3)]
311
+
312
+ Recall that a :class:`EdgesView` is read-only and that this method
313
+ returns a list::
314
+
315
+ sage: E *= 2
316
+ sage: type(E) is list
317
+ True
318
+
319
+ We can ask for the `i`-th edge, or a slice of the edges as a list::
320
+
321
+ sage: E = EdgesView(graphs.HouseGraph(), labels=False, sort=True)
322
+ sage: E[0]
323
+ (0, 1)
324
+ sage: E[2]
325
+ (1, 3)
326
+ sage: E[-1]
327
+ (3, 4)
328
+ sage: E[1:-1]
329
+ [(0, 2), (1, 3), (2, 3), (2, 4)]
330
+ sage: E[::-1]
331
+ [(3, 4), (2, 4), (2, 3), (1, 3), (0, 2), (0, 1)]
332
+ """
333
+ cdef readonly GenericGraph_pyx _graph
334
+ cdef list _vertices
335
+ cdef frozenset _vertex_set
336
+ cdef list _vertices2
337
+ cdef frozenset _vertex_set2
338
+ cdef readonly bint _labels
339
+ cdef readonly bint _ignore_direction
340
+ cdef bint _sort_vertices
341
+ cdef bint _sort_edges
342
+ cdef _sort_edges_key
343
+
344
+ def __init__(self, G, vertices=None, vertices2=None, labels=True,
345
+ ignore_direction=False,
346
+ sort=False, key=None, sort_vertices=True):
347
+ """
348
+ Construction of this :class:`EdgesView`.
349
+
350
+ EXAMPLES::
351
+
352
+ sage: from sage.graphs.views import EdgesView
353
+ sage: G = Graph([(0, 1, 'C'), (0, 2, 'A'), (1, 2, 'B')])
354
+ sage: E = EdgesView(G, sort=True); E
355
+ [(0, 1, 'C'), (0, 2, 'A'), (1, 2, 'B')]
356
+
357
+ TESTS::
358
+
359
+ sage: EdgesView(Graph(), sort=False, key=lambda x:0)
360
+ Traceback (most recent call last):
361
+ ...
362
+ ValueError: sort keyword is not True, yet a key function is given
363
+ """
364
+ self._graph = <GenericGraph_pyx?> G
365
+
366
+ if vertices is None:
367
+ self._vertices = None
368
+ self._vertex_set = None
369
+ else:
370
+ self._vertices = list(vertices)
371
+ self._vertex_set = frozenset(self._vertices)
372
+
373
+ if vertices2 is None:
374
+ self._vertices2 = None
375
+ self._vertex_set2 = None
376
+ else:
377
+ self._vertices2 = list(vertices2)
378
+ self._vertex_set2 = frozenset(self._vertices2)
379
+
380
+ # None and 0 are interpreted as False, 1 as True
381
+ self._labels = labels
382
+ self._ignore_direction = ignore_direction
383
+ self._sort_edges = sort
384
+ if not sort and key is not None:
385
+ raise ValueError('sort keyword is not True, yet a key function is given')
386
+ self._sort_edges_key = key
387
+ self._sort_vertices = sort_vertices
388
+
389
+ def __len__(self):
390
+ """
391
+ Return the number of edges in ``self``.
392
+
393
+ EXAMPLES::
394
+
395
+ sage: from sage.graphs.views import EdgesView
396
+ sage: G = graphs.HouseGraph()
397
+ sage: E = EdgesView(G)
398
+ sage: len(E)
399
+ 6
400
+ sage: len(E) == G.size()
401
+ True
402
+ sage: E = EdgesView(G, vertices=[0], labels=False, sort=True); E
403
+ [(0, 1), (0, 2)]
404
+ sage: len(E)
405
+ 2
406
+ sage: G = digraphs.Circuit(4)
407
+ sage: len(EdgesView(G, ignore_direction=False, sort=False))
408
+ 4
409
+ sage: len(EdgesView(G, ignore_direction=True, sort=False))
410
+ 8
411
+ """
412
+ if self._vertices is None and self._vertices2 is None:
413
+ if self._graph._directed and self._ignore_direction:
414
+ return 2 * self._graph.size()
415
+ return self._graph.size()
416
+ return sum(1 for _ in self)
417
+
418
+ def __repr__(self):
419
+ """
420
+ Return a string representation of ``self``.
421
+
422
+ EXAMPLES::
423
+
424
+ sage: from sage.graphs.views import EdgesView
425
+ sage: G = graphs.HouseGraph()
426
+ sage: E = EdgesView(G, labels=False)
427
+ sage: repr(E)
428
+ '[(0, 1), (0, 2), (1, 3), (2, 3), (2, 4), (3, 4)]'
429
+ sage: E
430
+ [(0, 1), (0, 2), (1, 3), (2, 3), (2, 4), (3, 4)]
431
+ """
432
+ return "[%s]" % ', '.join(map(repr, self))
433
+
434
+ def _iter_unsorted(self):
435
+ """
436
+ Iterator over the unsorted edges in ``self``.
437
+
438
+ EXAMPLES::
439
+
440
+ sage: from sage.graphs.views import EdgesView
441
+ sage: G = graphs.HouseGraph()
442
+ sage: E = EdgesView(G, labels=False, sort=False)
443
+ sage: list(E)
444
+ [(0, 1), (0, 2), (1, 3), (2, 3), (2, 4), (3, 4)]
445
+ """
446
+ if self._vertices is None:
447
+ vertices = self._graph
448
+ vertex_set = self._graph
449
+ else:
450
+ vertices = self._vertices
451
+ vertex_set = self._vertex_set
452
+
453
+ if self._vertices2 is None:
454
+ if self._graph._directed:
455
+ yield from self._graph._backend.iterator_out_edges(vertices, self._labels)
456
+ if self._ignore_direction:
457
+ yield from self._graph._backend.iterator_in_edges(vertices, self._labels)
458
+ elif self._sort_vertices:
459
+ yield from self._graph._backend.iterator_edges(vertices, self._labels)
460
+ else:
461
+ yield from self._graph._backend.iterator_unsorted_edges(vertices, self._labels)
462
+ elif self._graph._directed:
463
+ for e in self._graph._backend.iterator_out_edges(vertices, self._labels):
464
+ if e[1] in self._vertex_set2:
465
+ yield e
466
+ if self._ignore_direction:
467
+ for e in self._graph._backend.iterator_in_edges(vertices, self._labels):
468
+ if e[0] in self._vertex_set2:
469
+ yield e
470
+ elif self._sort_vertices:
471
+ for e in self._graph._backend.iterator_edges(vertices, self._labels):
472
+ if ((e[0] in vertex_set and e[1] in self._vertex_set2) or
473
+ (e[1] in vertex_set and e[0] in self._vertex_set2)):
474
+ yield e
475
+ else:
476
+ for e in self._graph._backend.iterator_unsorted_edges(vertices, self._labels):
477
+ if ((e[0] in vertex_set and e[1] in self._vertex_set2) or
478
+ (e[1] in vertex_set and e[0] in self._vertex_set2)):
479
+ yield e
480
+
481
+ def __iter__(self):
482
+ """
483
+ Iterator over the edges in ``self``.
484
+
485
+ EXAMPLES::
486
+
487
+ sage: from sage.graphs.views import EdgesView
488
+ sage: G = graphs.HouseGraph()
489
+ sage: E = EdgesView(G, labels=False, sort=True)
490
+ sage: list(E)
491
+ [(0, 1), (0, 2), (1, 3), (2, 3), (2, 4), (3, 4)]
492
+ sage: sum(1 for e in E for ee in E) == len(E) * len(E)
493
+ True
494
+ sage: E = EdgesView(G, labels=False)
495
+ sage: sum(1 for e in E for ee in E) == G.size() * G.size()
496
+ True
497
+ """
498
+ if self._sort_edges:
499
+ yield from sorted(self._iter_unsorted(), key=self._sort_edges_key)
500
+ else:
501
+ yield from self._iter_unsorted()
502
+
503
+ def __bool__(self):
504
+ """
505
+ Check whether ``self`` is not empty.
506
+
507
+ EXAMPLES::
508
+
509
+ sage: from sage.graphs.views import EdgesView
510
+ sage: E = EdgesView(Graph())
511
+ sage: bool(E)
512
+ False
513
+ sage: E = EdgesView(graphs.HouseGraph())
514
+ sage: bool(E)
515
+ True
516
+ """
517
+ for _ in self._iter_unsorted():
518
+ return True
519
+ return False
520
+
521
+ def __eq__(self, right):
522
+ """
523
+ Check whether ``self`` and ``right`` are equal.
524
+
525
+ Do not call this method directly. That is, for ``E1.__eq__(E2)`` write
526
+ ``E1 == E2``.
527
+
528
+ Two :class:`EdgesView` are considered equal if the following hold:
529
+ - they report either both directed, or both undirected edges;
530
+ - they have the same settings for ``ignore_direction``;
531
+ - they have the same settings for ``labels``;
532
+ - they report the same edges in the same order.
533
+
534
+ EXAMPLES::
535
+
536
+ sage: from sage.graphs.views import EdgesView
537
+ sage: G = graphs.HouseGraph()
538
+ sage: EG = EdgesView(G)
539
+ sage: H = Graph(EG)
540
+ sage: EH = EdgesView(H)
541
+ sage: EG == EH
542
+ True
543
+ sage: G.add_edge(0, 10)
544
+ sage: EG = EdgesView(G)
545
+ sage: EG == EH
546
+ False
547
+ sage: H.add_edge(0, 10)
548
+ sage: EH = EdgesView(H)
549
+ sage: EG == EH
550
+ True
551
+ sage: H = G.strong_orientation()
552
+ sage: EH = EdgesView(H)
553
+ sage: EG == EH
554
+ False
555
+
556
+ TESTS::
557
+
558
+ sage: from sage.graphs.views import EdgesView
559
+ sage: G = graphs.HouseGraph()
560
+ sage: E = EdgesView(G)
561
+ sage: E == E
562
+ True
563
+ sage: E == G
564
+ False
565
+ sage: G == E
566
+ False
567
+
568
+ Check that :issue:`29180` is fixed::
569
+
570
+ sage: G = graphs.CycleGraph(4)
571
+ sage: E = graphs.EmptyGraph()
572
+ sage: G.edges(sort=True) == E.edges(sort=True)
573
+ False
574
+ """
575
+ if not isinstance(right, EdgesView):
576
+ return NotImplemented
577
+ cdef EdgesView other = <EdgesView> right
578
+ if self is other:
579
+ return True
580
+ # Check parameters
581
+ if (self._graph._directed != other._graph._directed
582
+ or self._ignore_direction != other._ignore_direction
583
+ or self._labels != other._labels):
584
+ return False
585
+ # Check that self and other have the same number of edges
586
+ if len(self) != len(other):
587
+ return False
588
+ # Check that the same edges are reported in the same order
589
+ return all(es == eo for es, eo in zip(self, other))
590
+
591
+ def __contains__(self, e):
592
+ """
593
+ Check whether edge ``e`` is part of ``self``.
594
+
595
+ INPUT:
596
+
597
+ - ``e`` -- tuple; when ``self.labels`` is ``True``, the expected form is
598
+ ``(u, v, label)``, while when ``self.labels`` is ``False``, the
599
+ expected form is ``(u, v)``
600
+
601
+ EXAMPLES::
602
+
603
+ sage: from sage.graphs.views import EdgesView
604
+ sage: G = Graph([(0, 1)])
605
+ sage: E = EdgesView(G, labels=False)
606
+ sage: print(E)
607
+ [(0, 1)]
608
+ sage: (0, 1) in E
609
+ True
610
+ sage: (0, 1, None) in E
611
+ False
612
+ sage: E = EdgesView(G, labels=True)
613
+ sage: print(E)
614
+ [(0, 1, None)]
615
+ sage: (0, 1) in E
616
+ False
617
+ sage: (0, 1, None) in E
618
+ True
619
+ sage: G = Graph([(0, 1), (1, 2)])
620
+ sage: E = EdgesView(G, vertices=[0], vertices2=[1], labels=False)
621
+ sage: (0, 1) in E and (1, 2) not in E
622
+ True
623
+ sage: E = EdgesView(G, vertices=[0], labels=False)
624
+ sage: (0, 1) in E and (1, 2) not in E
625
+ True
626
+ sage: E = EdgesView(G, vertices2=[1], labels=False)
627
+ sage: (0, 1) in E and (1, 2) in E
628
+ True
629
+ """
630
+ if self._labels:
631
+ try:
632
+ u, v, label = e
633
+ except Exception:
634
+ return False
635
+ else:
636
+ try:
637
+ u, v = e
638
+ except Exception:
639
+ return False
640
+ label = None
641
+ if self._vertices2 is None:
642
+ if (self._vertex_set is not None
643
+ and u not in self._vertex_set and v not in self._vertex_set):
644
+ return False
645
+ if self._graph._directed and self._ignore_direction:
646
+ return (self._graph._backend.has_edge(u, v, label)
647
+ or self._graph._backend.has_edge(v, u, label))
648
+ return self._graph._backend.has_edge(u, v, label)
649
+
650
+ if u not in self._vertex_set2 and v not in self._vertex_set2:
651
+ return False
652
+ if (self._vertex_set is not None
653
+ and u not in self._vertex_set and v not in self._vertex_set):
654
+ return False
655
+ if self._graph._directed:
656
+ if self._ignore_direction:
657
+ return (self._graph._backend.has_edge(u, v, label)
658
+ or self._graph._backend.has_edge(v, u, label))
659
+ elif ((self._vertex_set is not None and u not in self._vertex_set)
660
+ or v not in self._vertex_set2):
661
+ return False
662
+ return self._graph._backend.has_edge(u, v, label)
663
+
664
+ def __getitem__(self, i):
665
+ r"""
666
+ Return the `i`-th edge in ``self``.
667
+
668
+ This method takes time `O(i)`. When several calls to this method are
669
+ done, prefer making ``list`` from ``self`` before querying items.
670
+
671
+ INPUT:
672
+
673
+ - ``i`` -- integer or slice
674
+
675
+ EXAMPLES::
676
+
677
+ sage: from sage.graphs.views import EdgesView
678
+ sage: E = EdgesView(graphs.HouseGraph(), labels=False)
679
+ sage: E[0]
680
+ (0, 1)
681
+ sage: E[2]
682
+ (1, 3)
683
+ sage: E[1:-1]
684
+ [(0, 2), (1, 3), (2, 3), (2, 4)]
685
+ sage: E[-1]
686
+ (3, 4)
687
+
688
+ TESTS::
689
+
690
+ sage: from sage.graphs.views import EdgesView
691
+ sage: E = EdgesView(graphs.HouseGraph(), labels=False)
692
+ sage: E[10]
693
+ Traceback (most recent call last):
694
+ ...
695
+ IndexError: index out of range
696
+ """
697
+ cdef Py_ssize_t start, stop, step
698
+ if isinstance(i, slice):
699
+ start, stop, step = i.start or 0, i.stop or sys_maxsize, i.step or 1
700
+ if start >= 0 and stop >= 0 and step >= 0:
701
+ return list(islice(self, start, stop, step))
702
+ else:
703
+ return list(self)[i]
704
+ elif i < 0:
705
+ return list(self)[i]
706
+ try:
707
+ return next(islice(self, i, i + 1, 1))
708
+ except StopIteration:
709
+ raise IndexError('index out of range')
710
+
711
+ def __add__(left, right):
712
+ """
713
+ Return a list containing the edges of ``left`` and ``right``.
714
+
715
+ The returned list contains the edges of ``left`` with prescribed order
716
+ followed by the edges of ``right`` in prescribed order.
717
+
718
+ INPUT:
719
+
720
+ - ``left``, ``right`` -- :class:`EdgesView` or list of edges
721
+
722
+ EXAMPLES::
723
+
724
+ sage: from sage.graphs.views import EdgesView
725
+ sage: E1 = EdgesView(Graph([(0, 1)]), labels=False)
726
+ sage: E2 = EdgesView(Graph([(2, 3)]), labels=False)
727
+ sage: E1 + E2
728
+ [(0, 1), (2, 3)]
729
+ sage: E2 + E1
730
+ [(2, 3), (0, 1)]
731
+ sage: E1 + E2 + E1
732
+ [(0, 1), (2, 3), (0, 1)]
733
+
734
+ Recall that a :class:`EdgesView` is read-only and that this method
735
+ returns a list::
736
+
737
+ sage: E1 += E2
738
+ sage: type(E1) is list
739
+ True
740
+
741
+ TESTS::
742
+
743
+ sage: from sage.graphs.views import EdgesView
744
+ sage: E = EdgesView(graphs.HouseGraph())
745
+ sage: E + 'foo'
746
+ Traceback (most recent call last):
747
+ ...
748
+ TypeError: unsupported operand type(s) for +: 'sage.graphs.views.EdgesView' and 'str'
749
+ """
750
+ if not isinstance(left, (list, EdgesView)) or not isinstance(right, (list, EdgesView)):
751
+ return NotImplemented
752
+ cdef list L = list(left)
753
+ L.extend(right)
754
+ return L
755
+
756
+ def __mul__(left, right):
757
+ r"""
758
+ Return the sum of ``left`` with itself ``right`` times.
759
+
760
+ INPUT:
761
+
762
+ - ``right`` -- integer
763
+
764
+ EXAMPLES::
765
+
766
+ sage: from sage.graphs.views import EdgesView
767
+ sage: E = EdgesView(Graph([(0, 1), (2, 3)]), labels=False, sort=True)
768
+ sage: E * 3
769
+ [(0, 1), (2, 3), (0, 1), (2, 3), (0, 1), (2, 3)]
770
+ sage: 3 * E
771
+ [(0, 1), (2, 3), (0, 1), (2, 3), (0, 1), (2, 3)]
772
+
773
+ Recall that a :class:`EdgesView` is read-only and that this method
774
+ returns a list::
775
+
776
+ sage: E *= 2
777
+ sage: type(E) is list
778
+ True
779
+
780
+ TESTS::
781
+
782
+ sage: from sage.graphs.views import EdgesView
783
+ sage: E = EdgesView(Graph([(0, 1)]))
784
+ sage: E * (-1)
785
+ []
786
+ sage: E * 1.5
787
+ Traceback (most recent call last):
788
+ ...
789
+ TypeError: can...t multiply sequence by non-int of type 'sage.rings.real_mpfr.RealLiteral'
790
+ """
791
+ if isinstance(left, EdgesView):
792
+ return list(left) * right
793
+ # Case __rmul__
794
+ return list(right) * left