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
@@ -0,0 +1,1177 @@
1
+ # sage_setup: distribution = sagemath-graphs
2
+ # sage.doctest: needs database_graphs
3
+ """
4
+ Graph database
5
+
6
+ This module implements classes (:class:`~GraphDatabase`, :class:`~GraphQuery`,
7
+ :class:`~GenericGraphQuery`) for interfacing with the ``sqlite`` database
8
+ ``graphs.db``.
9
+
10
+ The :class:`~GraphDatabase` class interfaces with the ``sqlite`` database
11
+ ``graphs.db``. It is an immutable database that inherits from
12
+ :class:`~sage.databases.sql_db.SQLDatabase` (see :mod:`sage.databases.sql_db`).
13
+
14
+ The database contains all unlabeled graphs with 7 or fewer nodes. This class
15
+ will also interface with the optional database package containing all unlabeled
16
+ graphs with 8 or fewer nodes. The database(s) consists of five tables, and has
17
+ the structure given by the function :func:`~graph_db_info` (For a full
18
+ description including column data types, create a :class:`~GraphDatabase`
19
+ instance and call the method
20
+ :meth:`~sage.databases.sql_db.SQLDatabase.get_skeleton`).
21
+
22
+ AUTHORS:
23
+
24
+ - Emily A. Kirkman (2008-09-20): first version of interactive queries,
25
+ cleaned up code and generalized many elements to
26
+ sage.databases.sql_db.py
27
+
28
+ - Emily A. Kirkman (2007-07-23): inherits GenericSQLDatabase, also
29
+ added classes: GraphQuery and GenericGraphQuery
30
+
31
+ - Emily A. Kirkman (2007-05-11): initial sqlite version
32
+
33
+ - Emily A. Kirkman (2007-02-13): initial version (non-sqlite)
34
+
35
+ REFERENCES:
36
+
37
+ - Data provided by Jason Grout (Brigham Young University). [Online]
38
+ Available: http://artsci.drake.edu/grout/graphs/
39
+ """
40
+
41
+ # ##############################################################################
42
+ # Copyright (C) 2007 Emily A. Kirkman
43
+ #
44
+ #
45
+ # Distributed under the terms of the GNU General Public License (GPL)
46
+ # https://www.gnu.org/licenses/
47
+ # ##############################################################################
48
+ import re
49
+
50
+ from . import graph
51
+ from sage.rings.integer import Integer
52
+ from sage.databases.sql_db import SQLDatabase, SQLQuery
53
+ from sage.features.databases import DatabaseGraphs
54
+ from sage.graphs.graph import Graph
55
+ dblocation = DatabaseGraphs().absolute_filename()
56
+
57
+
58
+ def degseq_to_data(degree_sequence):
59
+ """
60
+ Convert a degree sequence list to a sorted (max-min) integer data type.
61
+
62
+ The input degree sequence list (of Integers) is converted to a sorted
63
+ (max-min) integer data type, as used for faster access in the underlying
64
+ database.
65
+
66
+ INPUT:
67
+
68
+ - ``degree_sequence`` -- list of integers; input degree sequence list
69
+
70
+ EXAMPLES::
71
+
72
+ sage: from sage.graphs.graph_database import degseq_to_data
73
+ sage: degseq_to_data([2,2,3,1])
74
+ 3221
75
+ """
76
+ degree_sequence.sort()
77
+ return sum(di * 10**i for i, di in enumerate(degree_sequence))
78
+
79
+
80
+ def data_to_degseq(data, graph6=None):
81
+ """
82
+ Convert a database integer data type to a degree sequence list.
83
+
84
+ INPUT:
85
+
86
+ - ``data`` -- integer data type (one digit per vertex representing its
87
+ degree, sorted high to low) to be converted to a degree sequence list
88
+
89
+ - ``graph6`` -- string (default: ``None``); the ``graph6`` identifier is
90
+ required for all graphs with no edges, so that the correct number of zeros
91
+ is returned.
92
+
93
+ EXAMPLES::
94
+
95
+ sage: from sage.graphs.graph_database import data_to_degseq
96
+ sage: data_to_degseq(3221)
97
+ [1, 2, 2, 3]
98
+ sage: data_to_degseq(0, 'D??')
99
+ [0, 0, 0, 0, 0]
100
+ """
101
+ degseq = Integer(data).digits(10)
102
+ if not degseq:
103
+ # compute number of 0s in list from graph6 string
104
+ from sage.graphs.generic_graph_pyx import length_and_string_from_graph6
105
+ return length_and_string_from_graph6(str(graph6))[0] * [0]
106
+ return degseq
107
+
108
+
109
+ def graph6_to_plot(graph6):
110
+ """
111
+ Return a ``Graphics`` object from a ``graph6`` string.
112
+
113
+ This method constructs a graph from a ``graph6`` string and returns a
114
+ :class:`sage.plot.graphics.Graphics` object with arguments preset for the
115
+ :meth:`sage.plot.graphics.Graphics.show` method.
116
+
117
+ INPUT:
118
+
119
+ - ``graph6`` -- a ``graph6`` string
120
+
121
+ EXAMPLES::
122
+
123
+ sage: from sage.graphs.graph_database import graph6_to_plot
124
+ sage: type(graph6_to_plot('D??')) # needs sage.plot
125
+ <class 'sage.plot.graphics.Graphics'>
126
+ """
127
+ g = Graph(str(graph6))
128
+ return g.plot(layout='circular', vertex_size=30, vertex_labels=False, graph_border=False)
129
+
130
+
131
+ def subgraphs_to_query(subgraphs, db):
132
+ """
133
+ Return a GraphQuery object required for the induced_subgraphs parameter.
134
+
135
+ This method constructs and returns a :class:`~GraphQuery` object respecting
136
+ the special input required for the ``induced_subgraphs`` parameter.
137
+
138
+ INPUT:
139
+
140
+ - ``subgraphs`` -- list of strings; the list should be of one of the
141
+ following two formats:
142
+
143
+ - ``['one_of', String, ..., String]`` -- will search for graphs containing
144
+ a subgraph isomorphic to *any* of the ``graph6`` strings in the list
145
+
146
+ - ``['all_of', String, ..., String]`` -- will search for graphs containing
147
+ a subgraph isomorphic to *each* of the ``graph6`` strings in the list
148
+
149
+ - ``db`` -- a :class:`~GraphDatabase`
150
+
151
+ .. NOTE::
152
+
153
+ This is a helper method called by the :class:`~GraphQuery` constructor
154
+ to handle this special format. This method should not be used on its own
155
+ because it doesn't set any display columns in the query string, causing
156
+ a failure to fetch the data when run.
157
+
158
+ EXAMPLES::
159
+
160
+ sage: from sage.graphs.graph_database import subgraphs_to_query
161
+ sage: gd = GraphDatabase()
162
+ sage: q = subgraphs_to_query(['all_of', 'A?', 'B?', 'C?'], gd)
163
+ sage: q.get_query_string()
164
+ 'SELECT ,,,,, FROM misc WHERE ( ( misc.induced_subgraphs regexp ? ) AND (
165
+ misc.induced_subgraphs regexp ? ) ) AND ( misc.induced_subgraphs regexp ? )'
166
+ """
167
+ q = GraphQuery(graph_db=db, induced_subgraphs=subgraphs[1])
168
+ if subgraphs[0] == 'all_of':
169
+ for i in range(2, len(subgraphs)):
170
+ q.intersect(GraphQuery(graph_db=db, induced_subgraphs=subgraphs[i]),
171
+ in_place=True)
172
+ elif subgraphs[0] == 'one_of':
173
+ for i in range(2, len(subgraphs)):
174
+ q.union(GraphQuery(graph_db=db, induced_subgraphs=subgraphs[i]),
175
+ in_place=True)
176
+ else:
177
+ raise KeyError('unable to initiate query: illegal input format for induced_subgraphs')
178
+ return q
179
+
180
+
181
+ # tables columns input data type sqlite data type
182
+ # -----------------------------------------------------------------------------
183
+ aut_grp = ['aut_grp_size', # Integer INTEGER
184
+ 'num_orbits', # Integer INTEGER
185
+ 'num_fixed_points', # Integer INTEGER
186
+ 'vertex_transitive', # bool BOOLEAN
187
+ 'edge_transitive'] # bool BOOLEAN
188
+ degrees = ['degree_sequence', # list INTEGER (see degseq_to_data module function)
189
+ 'min_degree', # Integer INTEGER
190
+ 'max_degree', # Integer INTEGER
191
+ 'average_degree', # Real REAL
192
+ 'degrees_sd', # Real REAL
193
+ 'regular'] # bool BOOLEAN
194
+ misc = ['vertex_connectivity', # Integer INTEGER
195
+ 'edge_connectivity', # Integer INTEGER
196
+ 'num_components', # Integer INTEGER
197
+ 'girth', # Integer INTEGER
198
+ 'radius', # Integer INTEGER
199
+ 'diameter', # Integer INTEGER
200
+ 'clique_number', # Integer INTEGER
201
+ 'independence_number', # Integer INTEGER
202
+ 'num_cut_vertices', # Integer INTEGER
203
+ 'min_vertex_cover_size', # Integer INTEGER
204
+ 'num_spanning_trees', # Integer INTEGER
205
+ 'induced_subgraphs'] # String STRING
206
+ spectrum = ['spectrum', # String STRING
207
+ 'min_eigenvalue', # Real REAL
208
+ 'max_eigenvalue', # Real REAL
209
+ 'eigenvalues_sd', # Real REAL
210
+ 'energy'] # Real REAL
211
+ graph_data = ['complement_graph6', # String STRING
212
+ 'eulerian', # bool BOOLEAN
213
+ 'graph6', # String STRING
214
+ 'lovasz_number', # Real REAL
215
+ 'num_cycles', # Integer INTEGER
216
+ 'num_edges', # Integer INTEGER
217
+ 'num_hamiltonian_cycles', # Integer INTEGER
218
+ 'num_vertices', # Integer INTEGER
219
+ 'perfect', # bool BOOLEAN
220
+ 'planar'] # bool BOOLEAN
221
+
222
+ valid_kwds = aut_grp + degrees + misc + spectrum + graph_data
223
+
224
+
225
+ def graph_db_info(tablename=None):
226
+ """
227
+ Return a dictionary of allowed table and column names.
228
+
229
+ INPUT:
230
+
231
+ - ``tablename`` -- restricts the output to a single table
232
+
233
+ EXAMPLES::
234
+
235
+ sage: sorted(graph_db_info())
236
+ ['aut_grp', 'degrees', 'graph_data', 'misc', 'spectrum']
237
+
238
+ ::
239
+
240
+ sage: graph_db_info(tablename='graph_data')
241
+ ['complement_graph6',
242
+ 'eulerian',
243
+ 'graph6',
244
+ 'lovasz_number',
245
+ 'num_cycles',
246
+ 'num_edges',
247
+ 'num_hamiltonian_cycles',
248
+ 'num_vertices',
249
+ 'perfect',
250
+ 'planar']
251
+ """
252
+ info = {'graph_data': graph_data,
253
+ 'aut_grp': aut_grp,
254
+ 'degrees': degrees,
255
+ 'misc': misc,
256
+ 'spectrum': spectrum}
257
+ if tablename is not None:
258
+ info = info[tablename]
259
+ return info
260
+
261
+
262
+ class GenericGraphQuery(SQLQuery):
263
+
264
+ def __init__(self, query_string, database=None, param_tuple=None):
265
+ """
266
+ A query for a :class:`~GraphDatabase`.
267
+
268
+ INPUT:
269
+
270
+ - ``query_string`` -- string representing the SQL query
271
+
272
+ - ``database`` -- (default: ``None``) the :class:`~GraphDatabase`
273
+ instance to query (if ``None`` then a new instance is created)
274
+
275
+ - ``param_tuple`` -- tuple of strings (default: ``None``); what to
276
+ replace question marks in ``query_string`` with (optional, but a good
277
+ idea)
278
+
279
+ .. NOTE::
280
+
281
+ This query class is generally intended for developers and more
282
+ advanced users. It allows you to execute any query, and so may be
283
+ considered unsafe.
284
+
285
+ EXAMPLES:
286
+
287
+ See :class:`~GraphDatabase` class docstrings or enter::
288
+
289
+ sage: G = GraphDatabase()
290
+ sage: G.get_skeleton()
291
+ {...
292
+
293
+ to see the underlying structure of the database. Also see
294
+ :class:`sage.databases.sql_db.SQLQuery` in :mod:`sage.databases.sql_db`
295
+ for more info and a tutorial.
296
+
297
+ A piece of advice about '?' and param_tuple: it is generally considered
298
+ safer to query with a '?' in place of each value parameter, and using a
299
+ second argument (a tuple of strings) in a call to the ``sqlite``
300
+ database. Successful use of the ``param_tuple`` argument is
301
+ exemplified::
302
+
303
+ sage: G = GraphDatabase()
304
+ sage: q = 'select graph_id,graph6,num_vertices,num_edges from graph_data where graph_id<=(?) and num_vertices=(?)'
305
+ sage: param = (22,5)
306
+ sage: Q = SQLQuery(G, q, param)
307
+ sage: Q.show()
308
+ graph_id graph6 num_vertices num_edges
309
+ --------------------------------------------------------------------------------
310
+ 18 D?? 5 0
311
+ 19 D?C 5 1
312
+ 20 D?K 5 2
313
+ 21 D@O 5 2
314
+ 22 D?[ 5 3
315
+ """
316
+ if database is None:
317
+ database = GraphDatabase()
318
+ if not isinstance(database, GraphDatabase):
319
+ raise TypeError('%s is not a valid GraphDatabase' % database)
320
+ SQLQuery.__init__(self, database, query_string, param_tuple)
321
+
322
+
323
+ class GraphQuery(GenericGraphQuery):
324
+
325
+ def __init__(self, graph_db=None, query_dict=None, display_cols=None,
326
+ immutable=False, **kwds):
327
+ r"""
328
+ A query for an instance of :class:`~GraphDatabase`.
329
+
330
+ This class nicely wraps the :class:`sage.databases.sql_db.SQLQuery`
331
+ class located in :mod:`sage.databases.sql_db` to make the query
332
+ constraints intuitive and with as many pre-definitions as
333
+ possible. (i.e.: since it has to be a :class:`~GraphDatabase`, we
334
+ already know the table structure and types; and since it is immutable,
335
+ we can treat these as a guarantee).
336
+
337
+ .. NOTE::
338
+
339
+ :class:`sage.databases.sql_db.SQLQuery` functions are available for
340
+ :class:`~GraphQuery`. See :mod:`sage.databases.sql_db` for more
341
+ details.
342
+
343
+ INPUT:
344
+
345
+ - ``graph_db`` -- :class:`~GraphDatabase` (default: ``None``); instance
346
+ to apply the query to (If ``None``, then a new instance is created)
347
+
348
+ - ``query_dict`` -- dictionary (default: ``None``); a dictionary
349
+ specifying the query itself. Format is: ``{'table_name': 'tblname',
350
+ 'display_cols': ['col1', 'col2'], 'expression': [col, operator,
351
+ value]}``. If not ``None``, ``query_dict`` will take precedence over
352
+ all other arguments.
353
+
354
+ - ``display_cols`` -- list of strings (default: ``None``); a list of
355
+ column names (strings) to display in the result when running or
356
+ showing a query
357
+
358
+ - ``immutable`` -- boolean (default: ``False``); whether to return
359
+ immutable or mutable graphs
360
+
361
+ - ``kwds`` -- the columns of the database are all keywords. For a
362
+ database table/column structure dictionary, call
363
+ :func:`~graph_db_info`. Keywords accept both single values and lists
364
+ of length 2. The list allows the user to specify an expression other
365
+ than equality. Valid expressions are strings, and for numeric values
366
+ (i.e. Reals and Integers) are: '=','','','=','='. String values also
367
+ accept 'regexp' as an expression argument. The only keyword exception
368
+ to this format is ``induced_subgraphs``, which accepts one of the
369
+ following options:
370
+
371
+ - ``['one_of', String, ..., String]`` -- will search for graphs
372
+ containing a subgraph isomorphic to *any* of the ``graph6`` strings
373
+ in the list
374
+
375
+ - ``['all_of', String, ..., String]`` -- will search for graphs
376
+ containing a subgraph isomorphic to *each* of the ``graph6`` strings
377
+ in the list
378
+
379
+ EXAMPLES::
380
+
381
+ sage: Q = GraphQuery(display_cols=['graph6', 'num_vertices', 'degree_sequence'], num_edges=['<=', 5], min_degree=1)
382
+ sage: Q.number_of()
383
+ 35
384
+ sage: Q.show()
385
+ Graph6 Num Vertices Degree Sequence
386
+ ------------------------------------------------------------
387
+ A_ 2 [1, 1]
388
+ BW 3 [1, 1, 2]
389
+ CF 4 [1, 1, 1, 3]
390
+ CK 4 [1, 1, 1, 1]
391
+ CL 4 [1, 1, 2, 2]
392
+ CN 4 [1, 2, 2, 3]
393
+ D?{ 5 [1, 1, 1, 1, 4]
394
+ D@s 5 [1, 1, 1, 2, 3]
395
+ D@{ 5 [1, 1, 2, 2, 4]
396
+ DBg 5 [1, 1, 2, 2, 2]
397
+ DBk 5 [1, 1, 2, 3, 3]
398
+ DIk 5 [1, 2, 2, 2, 3]
399
+ DK[ 5 [1, 2, 2, 2, 3]
400
+ D_K 5 [1, 1, 1, 1, 2]
401
+ D`K 5 [1, 1, 2, 2, 2]
402
+ E?Bw 6 [1, 1, 1, 1, 1, 5]
403
+ E?Fg 6 [1, 1, 1, 1, 2, 4]
404
+ E?N? 6 [1, 1, 1, 1, 2, 2]
405
+ E?NG 6 [1, 1, 1, 1, 3, 3]
406
+ E@FG 6 [1, 1, 1, 2, 2, 3]
407
+ E@N? 6 [1, 1, 2, 2, 2, 2]
408
+ E@Q? 6 [1, 1, 1, 1, 1, 1]
409
+ E@QW 6 [1, 1, 1, 2, 2, 3]
410
+ E@YO 6 [1, 1, 2, 2, 2, 2]
411
+ E_?w 6 [1, 1, 1, 1, 1, 3]
412
+ E_Cg 6 [1, 1, 1, 1, 2, 2]
413
+ E_Cw 6 [1, 1, 1, 2, 2, 3]
414
+ E_Ko 6 [1, 1, 2, 2, 2, 2]
415
+ F??^? 7 [1, 1, 1, 1, 1, 2, 3]
416
+ F?LCG 7 [1, 1, 1, 1, 2, 2, 2]
417
+ FK??W 7 [1, 1, 1, 1, 1, 1, 2]
418
+ FK?GW 7 [1, 1, 1, 1, 2, 2, 2]
419
+ F_?@w 7 [1, 1, 1, 1, 1, 1, 4]
420
+ F_?Hg 7 [1, 1, 1, 1, 1, 2, 3]
421
+ F_?XO 7 [1, 1, 1, 1, 2, 2, 2]
422
+
423
+ Check the behavior of parameter ``immutable``::
424
+
425
+ sage: Q = GraphQuery(display_cols=['graph6'], num_vertices=3)
426
+ sage: any(g.is_immutable() for g in Q)
427
+ False
428
+ sage: Q = GraphQuery(display_cols=['graph6'], num_vertices=3, immutable=True)
429
+ sage: all(g.is_immutable() for g in Q)
430
+ True
431
+ """
432
+ self._immutable = immutable
433
+ if graph_db is None:
434
+ graph_db = GraphDatabase()
435
+ if query_dict is not None:
436
+ if query_dict['expression'][0] == 'degree_sequence':
437
+ query_dict['expression'][3] = degseq_to_data(query_dict['expression'][3])
438
+ elif query_dict['expression'][0] == 'induced_subgraphs':
439
+ query_dict['expression'][3] = subgraphs_to_data(query_dict['expression'][3])
440
+ SQLQuery.__init__(self, graph_db, query_dict)
441
+ else:
442
+ # construct a query from the given parameters
443
+ SQLQuery.__init__(self, graph_db)
444
+
445
+ # if display_cols is None:
446
+ # raise TypeError('Nonetype display_cols cannot retrieve data')
447
+
448
+ master_join = {}
449
+
450
+ for key in kwds:
451
+ # check validity
452
+ if key not in valid_kwds:
453
+ raise KeyError('%s is not a valid key for this database.' % str(key))
454
+
455
+ # designate a query_dict and reserve display_cols until end
456
+ # (database.py currently concatenates them including repeats)
457
+ qdict = {'display_cols': None}
458
+
459
+ # set table name
460
+ if key in graph_data:
461
+ qdict['table_name'] = 'graph_data'
462
+ elif key in aut_grp:
463
+ qdict['table_name'] = 'aut_grp'
464
+ elif key in degrees:
465
+ qdict['table_name'] = 'degrees'
466
+ elif key in misc:
467
+ qdict['table_name'] = 'misc'
468
+ elif key in spectrum:
469
+ qdict['table_name'] = 'spectrum'
470
+
471
+ # set expression
472
+ if not isinstance(kwds[key], list):
473
+ if key == 'induced_subgraphs':
474
+ s6 = (graph.Graph(kwds[key]).canonical_label()).graph6_string()
475
+ qdict['expression'] = [key, 'regexp', '.*%s.*' % s6]
476
+ else:
477
+ qdict['expression'] = [key, '=', kwds[key]]
478
+ elif key == 'degree_sequence':
479
+ qdict['expression'] = [key, '=', degseq_to_data(kwds[key])]
480
+ elif key != 'induced_subgraphs':
481
+ qdict['expression'] = [key] + kwds[key]
482
+
483
+ # add key parameter to query
484
+ join_dict = {qdict['table_name']: ('graph_id', 'graph_id')}
485
+ if key == 'induced_subgraphs' and isinstance(kwds[key], list):
486
+ self.intersect(subgraphs_to_query(kwds[key], graph_db),
487
+ 'graph_data', join_dict, in_place=True)
488
+ else:
489
+ self.intersect(SQLQuery(graph_db, qdict), 'graph_data',
490
+ join_dict, in_place=True)
491
+
492
+ # include search params (keys) in join clause
493
+ # again, we exclude graph_data because it is the base table
494
+ if qdict['table_name'] != 'graph_data':
495
+ master_join[qdict['table_name']] = ('graph_id', 'graph_id')
496
+
497
+ # display columns from each table
498
+ aut_grp_disp = ['aut_grp']
499
+ degrees_disp = ['degrees']
500
+ misc_disp = ['misc']
501
+ spectrum_disp = ['spectrum']
502
+ graph_data_disp = ['graph_data']
503
+
504
+ disp_tables = [aut_grp_disp, degrees_disp, misc_disp, spectrum_disp]
505
+ # graph_data intentionally left out because it is always called
506
+
507
+ # organize display
508
+ if display_cols is not None:
509
+ for col in display_cols:
510
+ if col in graph_data:
511
+ graph_data_disp.append(col)
512
+ elif col in aut_grp:
513
+ aut_grp_disp.append(col)
514
+ elif col in degrees:
515
+ degrees_disp.append(col)
516
+ elif col in misc:
517
+ misc_disp.append(col)
518
+ elif col in spectrum:
519
+ spectrum_disp.append(col)
520
+
521
+ # finish filling master join with display tables
522
+ for tab in disp_tables:
523
+ if len(tab) > 1:
524
+ master_join[tab[0]] = ('graph_id', 'graph_id')
525
+
526
+ # join clause for display tables
527
+ join_str = 'FROM graph_data '
528
+ for tab in master_join:
529
+ join_str += 'INNER JOIN %s ON graph_data.graph_id=%s.graph_id ' % (tab, tab)
530
+
531
+ # construct sql syntax substring for display cols
532
+ disp_list = ['SELECT graph_data.graph6, ']
533
+ for col in graph_data_disp[1:]:
534
+ if col != 'graph6':
535
+ disp_list.append('graph_data.%s, ' % col)
536
+ for col in aut_grp_disp[1:]:
537
+ disp_list.append('aut_grp.%s, ' % col)
538
+ for col in degrees_disp[1:]:
539
+ disp_list.append('degrees.%s, ' % col)
540
+ for col in misc_disp[1:]:
541
+ disp_list.append('misc.%s, ' % col)
542
+ for col in spectrum_disp[1:]:
543
+ disp_list.append('spectrum.%s, ' % col)
544
+ disp_list[-1] = disp_list[-1].rstrip(', ') + ' '
545
+ disp_str = ''.join(disp_list)
546
+
547
+ # substitute disp_str and join_str back into self's query string
548
+ self.__query_string__ = re.sub('SELECT.*WHERE ',
549
+ disp_str + join_str + 'WHERE ',
550
+ self.__query_string__)
551
+ self.__query_string__ += ' ORDER BY graph_data.graph6'
552
+
553
+ def query_iterator(self, immutable=None):
554
+ """
555
+ Return an iterator over the results list of the :class:`~GraphQuery`.
556
+
557
+ INPUT:
558
+
559
+ - ``immutable`` -- boolean (default: ``None``); whether to create
560
+ mutable/immutable graphs. By default (``immutable=None``), follow the
561
+ behavior of ``self``.
562
+
563
+ EXAMPLES::
564
+
565
+ sage: Q = GraphQuery(display_cols=['graph6'], num_vertices=7, diameter=5)
566
+ sage: for g in Q:
567
+ ....: print(g.graph6_string())
568
+ F?`po
569
+ F?gqg
570
+ F@?]O
571
+ F@OKg
572
+ F@R@o
573
+ FA_pW
574
+ FEOhW
575
+ FGC{o
576
+ FIAHo
577
+ sage: Q = GraphQuery(display_cols=['graph6'], num_vertices=7, diameter=5)
578
+ sage: it = iter(Q)
579
+ sage: while True:
580
+ ....: try: print(next(it).graph6_string())
581
+ ....: except StopIteration: break
582
+ F?`po
583
+ F?gqg
584
+ F@?]O
585
+ F@OKg
586
+ F@R@o
587
+ FA_pW
588
+ FEOhW
589
+ FGC{o
590
+ FIAHo
591
+
592
+ Check the behavior of parameter ``immutable``::
593
+
594
+ sage: Q = GraphQuery(display_cols=['graph6'], num_vertices=3)
595
+ sage: any(g.is_immutable() for g in Q.query_iterator())
596
+ False
597
+ sage: all(g.is_immutable() for g in Q.query_iterator(immutable=True))
598
+ True
599
+ sage: Q = GraphQuery(display_cols=['graph6'], num_vertices=3, immutable=True)
600
+ sage: all(g.is_immutable() for g in Q.query_iterator())
601
+ True
602
+ sage: any(g.is_immutable() for g in Q.query_iterator(immutable=False))
603
+ False
604
+ """
605
+ if immutable is None:
606
+ immutable = self._immutable
607
+ s = self.__query_string__
608
+ re.sub('SELECT.*FROM ', 'SELECT graph6 FROM ', s)
609
+ q = GenericGraphQuery(s, self.__database__, self.__param_tuple__)
610
+ for g in q.query_results():
611
+ yield Graph(str(g[0]), immutable=immutable)
612
+
613
+ __iter__ = query_iterator
614
+
615
+ def show(self, max_field_size=20, with_picture=False):
616
+ """
617
+ Display the results of a query in table format.
618
+
619
+ INPUT:
620
+
621
+ - ``max_field_size`` -- integer (default: 20); width of fields in
622
+ command prompt version
623
+
624
+ - ``with_picture`` -- boolean (default: ``False``); whether or not to
625
+ display results with a picture of the graph (available only in the
626
+ notebook)
627
+
628
+ EXAMPLES::
629
+
630
+ sage: G = GraphDatabase()
631
+ sage: Q = GraphQuery(G, display_cols=['graph6','num_vertices','aut_grp_size'], num_vertices=4, aut_grp_size=4)
632
+ sage: Q.show()
633
+ Graph6 Num Vertices Aut Grp Size
634
+ ------------------------------------------------------------
635
+ C@ 4 4
636
+ C^ 4 4
637
+
638
+ ::
639
+
640
+ sage: R = GraphQuery(G, display_cols=['graph6','num_vertices','degree_sequence'], num_vertices=4)
641
+ sage: R.show()
642
+ Graph6 Num Vertices Degree Sequence
643
+ ------------------------------------------------------------
644
+ C? 4 [0, 0, 0, 0]
645
+ C@ 4 [0, 0, 1, 1]
646
+ CB 4 [0, 1, 1, 2]
647
+ CF 4 [1, 1, 1, 3]
648
+ CJ 4 [0, 2, 2, 2]
649
+ CK 4 [1, 1, 1, 1]
650
+ CL 4 [1, 1, 2, 2]
651
+ CN 4 [1, 2, 2, 3]
652
+ C] 4 [2, 2, 2, 2]
653
+ C^ 4 [2, 2, 3, 3]
654
+ C~ 4 [3, 3, 3, 3]
655
+
656
+ Show the pictures (in notebook mode only)::
657
+
658
+ sage: S = GraphQuery(G, display_cols=['graph6','aut_grp_size'], num_vertices=4)
659
+ sage: S.show(with_picture=True)
660
+ Traceback (most recent call last):
661
+ ...
662
+ NotImplementedError: Cannot display plot on command line.
663
+
664
+ Note that pictures can be turned off::
665
+
666
+ sage: S.show(with_picture=False)
667
+ Graph6 Aut Grp Size
668
+ ----------------------------------------
669
+ C? 24
670
+ C@ 4
671
+ CB 2
672
+ CF 6
673
+ CJ 6
674
+ CK 8
675
+ CL 2
676
+ CN 2
677
+ C] 8
678
+ C^ 4
679
+ C~ 24
680
+
681
+ Show your own query (note that the output is not reformatted for
682
+ generic queries)::
683
+
684
+ sage: (GenericGraphQuery('select degree_sequence from degrees where max_degree=2 and min_degree >= 1', G)).show()
685
+ degree_sequence
686
+ --------------------
687
+ 211
688
+ 222
689
+ 2211
690
+ 2222
691
+ 21111
692
+ 22211
693
+ 22211
694
+ 22222
695
+ 221111
696
+ 221111
697
+ 222211
698
+ 222211
699
+ 222211
700
+ 222222
701
+ 222222
702
+ 2111111
703
+ 2221111
704
+ 2221111
705
+ 2221111
706
+ 2222211
707
+ 2222211
708
+ 2222211
709
+ 2222211
710
+ 2222222
711
+ 2222222
712
+ """
713
+ relabel = {}
714
+ for col in valid_kwds:
715
+ relabel[col] = ' '.join(word.capitalize() for word in col.split('_'))
716
+
717
+ if re.search('SELECT .*degree_sequence.* FROM', self.__query_string__):
718
+ format_cols = {'degree_sequence': data_to_degseq}
719
+ else:
720
+ format_cols = {}
721
+ if with_picture:
722
+ SQLQuery.show(self, max_field_size=max_field_size,
723
+ plot_cols={'graph6': graph6_to_plot},
724
+ format_cols=format_cols, id_col='graph6',
725
+ relabel_cols=relabel)
726
+ else:
727
+ SQLQuery.show(self, max_field_size=max_field_size,
728
+ format_cols=format_cols, relabel_cols=relabel,
729
+ id_col='graph6')
730
+
731
+ def get_graphs_list(self, immutable=None):
732
+ """
733
+ Return a list of Sage Graph objects that satisfy the query.
734
+
735
+ INPUT:
736
+
737
+ - ``immutable`` -- boolean (default: ``None``); whether to create
738
+ mutable/immutable graphs. By default (``immutable=None``), follow the
739
+ behavior of ``self``.
740
+
741
+ EXAMPLES::
742
+
743
+ sage: Q = GraphQuery(display_cols=['graph6', 'num_vertices', 'degree_sequence'], num_edges=['<=', 5], min_degree=1)
744
+ sage: L = Q.get_graphs_list()
745
+ sage: L[0]
746
+ Graph on 2 vertices
747
+ sage: len(L)
748
+ 35
749
+
750
+ Check the behavior of parameter ``immutable``::
751
+
752
+ sage: Q = GraphQuery(display_cols=['graph6'], num_vertices=3)
753
+ sage: any(g.is_immutable() for g in Q.get_graphs_list())
754
+ False
755
+ sage: all(g.is_immutable() for g in Q.get_graphs_list(immutable=True))
756
+ True
757
+ sage: Q = GraphQuery(display_cols=['graph6'], num_vertices=3, immutable=True)
758
+ sage: all(g.is_immutable() for g in Q.get_graphs_list())
759
+ True
760
+ sage: any(g.is_immutable() for g in Q.get_graphs_list(immutable=False))
761
+ False
762
+ """
763
+ if immutable is None:
764
+ immutable = self._immutable
765
+ return list(self.query_iterator(immutable=immutable))
766
+
767
+ def number_of(self):
768
+ """
769
+ Return the number of graphs in the database that satisfy the query.
770
+
771
+ EXAMPLES::
772
+
773
+ sage: Q = GraphQuery(display_cols=['graph6', 'num_vertices', 'degree_sequence'] ,num_edges=['<=', 5], min_degree=1)
774
+ sage: Q.number_of()
775
+ 35
776
+ """
777
+ # run graphs_list and return len
778
+ s = self.__query_string__
779
+ re.sub('SELECT.*FROM ', 'SELECT graph6 FROM ', s)
780
+ q = GenericGraphQuery(s, self.__database__, self.__param_tuple__)
781
+ return len(q.query_results())
782
+
783
+
784
+ class GraphDatabase(SQLDatabase):
785
+
786
+ def __init__(self):
787
+ """
788
+ Graph Database.
789
+
790
+ This class interfaces with the ``sqlite`` database ``graphs.db``. It is
791
+ an immutable database that inherits from
792
+ :class:`~sage.databases.sql_db.SQLDatabase` (see
793
+ :mod:`sage.databases.sql_db`). The display functions and get_graphs_list
794
+ create their own queries, but it is also possible to query the database
795
+ by constructing either a :class:`~sage.databases.sql_db.SQLQuery`.
796
+
797
+ The database contains all unlabeled graphs with 7 or fewer nodes. This
798
+ class will also interface with the optional database package containing
799
+ all unlabeled graphs with 8 or fewer nodes. The database consists of
800
+ five tables. For a full table and column structure, call
801
+ :func:`~graph_db_info`.
802
+
803
+ The tables are associated by the unique primary key ``graph_id`` (int).
804
+
805
+ To query this database, we create a :class:`~GraphQuery`. This can be
806
+ done directly with the :meth:`~GraphDatabase.query` method or by
807
+ initializing one of:
808
+
809
+ - :class:`~GenericGraphQuery` -- allows direct entry of a query string
810
+ and tuple of parameters. This is the route for more advanced users
811
+ that are familiar with SQL
812
+
813
+ - :class:`~GraphQuery` -- a wrapper of SQLQuery, a general
814
+ database/query wrapper of SQLite for new users
815
+
816
+ REFERENCES:
817
+
818
+ - Data provided by Jason Grout (Brigham Young
819
+ University). [Online] Available:
820
+ http://artsci.drake.edu/grout/graphs/
821
+
822
+ EXAMPLES::
823
+
824
+ sage: G = GraphDatabase()
825
+ sage: G.get_skeleton()
826
+ {'aut_grp': {'aut_grp_size': {'index': True,
827
+ 'primary_key': False,
828
+ 'sql': 'INTEGER',
829
+ 'unique': False},
830
+ 'edge_transitive': {'index': True,
831
+ 'primary_key': False,
832
+ 'sql': 'BOOLEAN',
833
+ 'unique': False},
834
+ 'graph_id': {'index': False,
835
+ 'primary_key': False,
836
+ 'sql': 'INTEGER',
837
+ 'unique': False},
838
+ 'num_fixed_points': {'index': True,
839
+ 'primary_key': False,
840
+ 'sql': 'INTEGER',
841
+ 'unique': False},
842
+ 'num_orbits': {'index': True,
843
+ 'primary_key': False,
844
+ 'sql': 'INTEGER',
845
+ 'unique': False},
846
+ 'vertex_transitive': {'index': True,
847
+ 'primary_key': False,
848
+ 'sql': 'BOOLEAN',
849
+ 'unique': False}},
850
+ 'degrees': {'average_degree': {'index': True,
851
+ 'primary_key': False,
852
+ 'sql': 'REAL',
853
+ 'unique': False},
854
+ 'degree_sequence': {'index': False,
855
+ 'primary_key': False,
856
+ 'sql': 'INTEGER',
857
+ 'unique': False},
858
+ 'degrees_sd': {'index': True,
859
+ 'primary_key': False,
860
+ 'sql': 'REAL',
861
+ 'unique': False},
862
+ 'graph_id': {'index': False,
863
+ 'primary_key': False,
864
+ 'sql': 'INTEGER',
865
+ 'unique': False},
866
+ 'max_degree': {'index': True,
867
+ 'primary_key': False,
868
+ 'sql': 'INTEGER',
869
+ 'unique': False},
870
+ 'min_degree': {'index': True,
871
+ 'primary_key': False,
872
+ 'sql': 'INTEGER',
873
+ 'unique': False},
874
+ 'regular': {'index': True,
875
+ 'primary_key': False,
876
+ 'sql': 'BOOLEAN',
877
+ 'unique': False}},
878
+ 'graph_data': {'complement_graph6': {'index': True,
879
+ 'primary_key': False,
880
+ 'sql': 'TEXT',
881
+ 'unique': False},
882
+ 'eulerian': {'index': True,
883
+ 'primary_key': False,
884
+ 'sql': 'BOOLEAN',
885
+ 'unique': False},
886
+ 'graph6': {'index': True,
887
+ 'primary_key': False,
888
+ 'sql': 'TEXT',
889
+ 'unique': False},
890
+ 'graph_id': {'index': True,
891
+ 'primary_key': False,
892
+ 'sql': 'INTEGER',
893
+ 'unique': True},
894
+ 'lovasz_number': {'index': True,
895
+ 'primary_key': False,
896
+ 'sql': 'REAL',
897
+ 'unique': False},
898
+ 'num_cycles': {'index': True,
899
+ 'primary_key': False,
900
+ 'sql': 'INTEGER',
901
+ 'unique': False},
902
+ 'num_edges': {'index': True,
903
+ 'primary_key': False,
904
+ 'sql': 'INTEGER',
905
+ 'unique': False},
906
+ 'num_hamiltonian_cycles': {'index': True,
907
+ 'primary_key': False,
908
+ 'sql': 'INTEGER',
909
+ 'unique': False},
910
+ 'num_vertices': {'index': True,
911
+ 'primary_key': False,
912
+ 'sql': 'INTEGER',
913
+ 'unique': False},
914
+ 'perfect': {'index': True,
915
+ 'primary_key': False,
916
+ 'sql': 'BOOLEAN',
917
+ 'unique': False},
918
+ 'planar': {'index': True,
919
+ 'primary_key': False,
920
+ 'sql': 'BOOLEAN',
921
+ 'unique': False}},
922
+ 'misc': {'clique_number': {'index': True,
923
+ 'primary_key': False,
924
+ 'sql': 'INTEGER',
925
+ 'unique': False},
926
+ 'diameter': {'index': True,
927
+ 'primary_key': False,
928
+ 'sql': 'INTEGER',
929
+ 'unique': False},
930
+ 'edge_connectivity': {'index': True,
931
+ 'primary_key': False,
932
+ 'sql': 'BOOLEAN',
933
+ 'unique': False},
934
+ 'girth': {'index': True,
935
+ 'primary_key': False,
936
+ 'sql': 'INTEGER',
937
+ 'unique': False},
938
+ 'graph_id': {'index': False,
939
+ 'primary_key': False,
940
+ 'sql': 'INTEGER',
941
+ 'unique': False},
942
+ 'independence_number': {'index': True,
943
+ 'primary_key': False,
944
+ 'sql': 'INTEGER',
945
+ 'unique': False},
946
+ 'induced_subgraphs': {'index': True,
947
+ 'primary_key': False,
948
+ 'sql': 'TEXT',
949
+ 'unique': False},
950
+ 'min_vertex_cover_size': {'index': True,
951
+ 'primary_key': False,
952
+ 'sql': 'INTEGER',
953
+ 'unique': False},
954
+ 'num_components': {'index': True,
955
+ 'primary_key': False,
956
+ 'sql': 'INTEGER',
957
+ 'unique': False},
958
+ 'num_cut_vertices': {'index': True,
959
+ 'primary_key': False,
960
+ 'sql': 'INTEGER',
961
+ 'unique': False},
962
+ 'num_spanning_trees': {'index': True,
963
+ 'primary_key': False,
964
+ 'sql': 'INTEGER',
965
+ 'unique': False},
966
+ 'radius': {'index': True,
967
+ 'primary_key': False,
968
+ 'sql': 'INTEGER',
969
+ 'unique': False},
970
+ 'vertex_connectivity': {'index': True,
971
+ 'primary_key': False,
972
+ 'sql': 'BOOLEAN',
973
+ 'unique': False}},
974
+ 'spectrum': {'eigenvalues_sd': {'index': True,
975
+ 'primary_key': False,
976
+ 'sql': 'REAL',
977
+ 'unique': False},
978
+ 'energy': {'index': True,
979
+ 'primary_key': False,
980
+ 'sql': 'REAL',
981
+ 'unique': False},
982
+ 'graph_id': {'index': False,
983
+ 'primary_key': False,
984
+ 'sql': 'INTEGER',
985
+ 'unique': False},
986
+ 'max_eigenvalue': {'index': True,
987
+ 'primary_key': False,
988
+ 'sql': 'REAL',
989
+ 'unique': False},
990
+ 'min_eigenvalue': {'index': True,
991
+ 'primary_key': False,
992
+ 'sql': 'REAL',
993
+ 'unique': False},
994
+ 'spectrum': {'index': False,
995
+ 'primary_key': False,
996
+ 'sql': 'TEXT',
997
+ 'unique': False}}}
998
+ """
999
+ SQLDatabase.__init__(self, dblocation)
1000
+
1001
+ def _gen_interact_func(self, display, **kwds):
1002
+ """
1003
+ Return a function to interact with GraphQuery parameters and results.
1004
+
1005
+ This is a helper method for the ``interactive_query`` method and should
1006
+ not be called directly.
1007
+ """
1008
+ function_name = '__temporary_interact_function'
1009
+ arg = ['%s=%s' % (word, kwds[word]) for word in kwds]
1010
+ boxes = ["%s=input_grid(1,2,['=',%s])" % (word, kwds[word]) for word in kwds]
1011
+ params = ['%s=%s[0]' % tuple(2 * [arg[i].split('=')[0]]) for i in range(len(arg))]
1012
+
1013
+ s = 'def %s(%s):' % (function_name, ','.join(boxes))
1014
+ t = """
1015
+ print('<html><h2>Query Results:</h2></html>')
1016
+ GraphQuery(display_cols=%s,%s).show(with_picture=True)
1017
+ """ % tuple([display, ','.join(params)])
1018
+ s += '\t' + '\n\t'.join(t.split('\n')) + '\n'
1019
+ exec(s)
1020
+ return locals()[function_name]
1021
+
1022
+ def query(self, query_dict=None, display_cols=None, **kwds):
1023
+ """
1024
+ Create a GraphQuery on this database.
1025
+
1026
+ For full class details, type ``GraphQuery?``
1027
+ and press :kbd:`Shift` + :kbd:`Enter`.
1028
+
1029
+ EXAMPLES::
1030
+
1031
+ sage: D = GraphDatabase()
1032
+ sage: q = D.query(display_cols=['graph6', 'num_vertices', 'degree_sequence'], num_edges=['<=', 5]) # needs sage.symbolic
1033
+ sage: q.show() # needs sage.symbolic
1034
+ Graph6 Num Vertices Degree Sequence
1035
+ ------------------------------------------------------------
1036
+ @ 1 [0]
1037
+ A? 2 [0, 0]
1038
+ A_ 2 [1, 1]
1039
+ B? 3 [0, 0, 0]
1040
+ BG 3 [0, 1, 1]
1041
+ BW 3 [1, 1, 2]
1042
+ Bw 3 [2, 2, 2]
1043
+ C? 4 [0, 0, 0, 0]
1044
+ C@ 4 [0, 0, 1, 1]
1045
+ CB 4 [0, 1, 1, 2]
1046
+ CF 4 [1, 1, 1, 3]
1047
+ CJ 4 [0, 2, 2, 2]
1048
+ CK 4 [1, 1, 1, 1]
1049
+ CL 4 [1, 1, 2, 2]
1050
+ CN 4 [1, 2, 2, 3]
1051
+ C] 4 [2, 2, 2, 2]
1052
+ C^ 4 [2, 2, 3, 3]
1053
+ D?? 5 [0, 0, 0, 0, 0]
1054
+ D?C 5 [0, 0, 0, 1, 1]
1055
+ D?K 5 [0, 0, 1, 1, 2]
1056
+ D?[ 5 [0, 1, 1, 1, 3]
1057
+ D?{ 5 [1, 1, 1, 1, 4]
1058
+ D@K 5 [0, 0, 2, 2, 2]
1059
+ D@O 5 [0, 1, 1, 1, 1]
1060
+ D@S 5 [0, 1, 1, 2, 2]
1061
+ D@[ 5 [0, 1, 2, 2, 3]
1062
+ D@s 5 [1, 1, 1, 2, 3]
1063
+ D@{ 5 [1, 1, 2, 2, 4]
1064
+ DBW 5 [0, 2, 2, 2, 2]
1065
+ DB[ 5 [0, 2, 2, 3, 3]
1066
+ DBg 5 [1, 1, 2, 2, 2]
1067
+ DBk 5 [1, 1, 2, 3, 3]
1068
+ DIk 5 [1, 2, 2, 2, 3]
1069
+ DK[ 5 [1, 2, 2, 2, 3]
1070
+ DLo 5 [2, 2, 2, 2, 2]
1071
+ D_K 5 [1, 1, 1, 1, 2]
1072
+ D`K 5 [1, 1, 2, 2, 2]
1073
+ E??? 6 [0, 0, 0, 0, 0, 0]
1074
+ E??G 6 [0, 0, 0, 0, 1, 1]
1075
+ E??W 6 [0, 0, 0, 1, 1, 2]
1076
+ E??w 6 [0, 0, 1, 1, 1, 3]
1077
+ E?@w 6 [0, 1, 1, 1, 1, 4]
1078
+ E?Bw 6 [1, 1, 1, 1, 1, 5]
1079
+ E?CW 6 [0, 0, 0, 2, 2, 2]
1080
+ E?C_ 6 [0, 0, 1, 1, 1, 1]
1081
+ E?Cg 6 [0, 0, 1, 1, 2, 2]
1082
+ E?Cw 6 [0, 0, 1, 2, 2, 3]
1083
+ E?Dg 6 [0, 1, 1, 1, 2, 3]
1084
+ E?Dw 6 [0, 1, 1, 2, 2, 4]
1085
+ E?Fg 6 [1, 1, 1, 1, 2, 4]
1086
+ E?Ko 6 [0, 0, 2, 2, 2, 2]
1087
+ E?Kw 6 [0, 0, 2, 2, 3, 3]
1088
+ E?LO 6 [0, 1, 1, 2, 2, 2]
1089
+ E?LW 6 [0, 1, 1, 2, 3, 3]
1090
+ E?N? 6 [1, 1, 1, 1, 2, 2]
1091
+ E?NG 6 [1, 1, 1, 1, 3, 3]
1092
+ E@FG 6 [1, 1, 1, 2, 2, 3]
1093
+ E@HW 6 [0, 1, 2, 2, 2, 3]
1094
+ E@N? 6 [1, 1, 2, 2, 2, 2]
1095
+ E@Ow 6 [0, 1, 2, 2, 2, 3]
1096
+ E@Q? 6 [1, 1, 1, 1, 1, 1]
1097
+ E@QW 6 [1, 1, 1, 2, 2, 3]
1098
+ E@T_ 6 [0, 2, 2, 2, 2, 2]
1099
+ E@YO 6 [1, 1, 2, 2, 2, 2]
1100
+ EG?W 6 [0, 1, 1, 1, 1, 2]
1101
+ EGCW 6 [0, 1, 1, 2, 2, 2]
1102
+ E_?w 6 [1, 1, 1, 1, 1, 3]
1103
+ E_Cg 6 [1, 1, 1, 1, 2, 2]
1104
+ E_Cw 6 [1, 1, 1, 2, 2, 3]
1105
+ E_Ko 6 [1, 1, 2, 2, 2, 2]
1106
+ F???? 7 [0, 0, 0, 0, 0, 0, 0]
1107
+ F???G 7 [0, 0, 0, 0, 0, 1, 1]
1108
+ F???W 7 [0, 0, 0, 0, 1, 1, 2]
1109
+ F???w 7 [0, 0, 0, 1, 1, 1, 3]
1110
+ F??@w 7 [0, 0, 1, 1, 1, 1, 4]
1111
+ F??Bw 7 [0, 1, 1, 1, 1, 1, 5]
1112
+ F??GW 7 [0, 0, 0, 0, 2, 2, 2]
1113
+ F??G_ 7 [0, 0, 0, 1, 1, 1, 1]
1114
+ F??Gg 7 [0, 0, 0, 1, 1, 2, 2]
1115
+ F??Gw 7 [0, 0, 0, 1, 2, 2, 3]
1116
+ F??Hg 7 [0, 0, 1, 1, 1, 2, 3]
1117
+ F??Hw 7 [0, 0, 1, 1, 2, 2, 4]
1118
+ F??Jg 7 [0, 1, 1, 1, 1, 2, 4]
1119
+ F??Wo 7 [0, 0, 0, 2, 2, 2, 2]
1120
+ F??Ww 7 [0, 0, 0, 2, 2, 3, 3]
1121
+ F??XO 7 [0, 0, 1, 1, 2, 2, 2]
1122
+ F??XW 7 [0, 0, 1, 1, 2, 3, 3]
1123
+ F??Z? 7 [0, 1, 1, 1, 1, 2, 2]
1124
+ F??ZG 7 [0, 1, 1, 1, 1, 3, 3]
1125
+ F??^? 7 [1, 1, 1, 1, 1, 2, 3]
1126
+ F?CJG 7 [0, 1, 1, 1, 2, 2, 3]
1127
+ F?CPW 7 [0, 0, 1, 2, 2, 2, 3]
1128
+ F?CZ? 7 [0, 1, 1, 2, 2, 2, 2]
1129
+ F?C_w 7 [0, 0, 1, 2, 2, 2, 3]
1130
+ F?Ca? 7 [0, 1, 1, 1, 1, 1, 1]
1131
+ F?CaW 7 [0, 1, 1, 1, 2, 2, 3]
1132
+ F?Ch_ 7 [0, 0, 2, 2, 2, 2, 2]
1133
+ F?CqO 7 [0, 1, 1, 2, 2, 2, 2]
1134
+ F?LCG 7 [1, 1, 1, 1, 2, 2, 2]
1135
+ F@??W 7 [0, 0, 1, 1, 1, 1, 2]
1136
+ F@?GW 7 [0, 0, 1, 1, 2, 2, 2]
1137
+ FG??w 7 [0, 1, 1, 1, 1, 1, 3]
1138
+ FG?Gg 7 [0, 1, 1, 1, 1, 2, 2]
1139
+ FG?Gw 7 [0, 1, 1, 1, 2, 2, 3]
1140
+ FG?Wo 7 [0, 1, 1, 2, 2, 2, 2]
1141
+ FK??W 7 [1, 1, 1, 1, 1, 1, 2]
1142
+ FK?GW 7 [1, 1, 1, 1, 2, 2, 2]
1143
+ F_?@w 7 [1, 1, 1, 1, 1, 1, 4]
1144
+ F_?Hg 7 [1, 1, 1, 1, 1, 2, 3]
1145
+ F_?XO 7 [1, 1, 1, 1, 2, 2, 2]
1146
+ """
1147
+ return GraphQuery(self, query_dict, display_cols, **kwds)
1148
+
1149
+ def interactive_query(self, display_cols, **kwds):
1150
+ """
1151
+ Generate an interact shell to query the database.
1152
+
1153
+ .. WARNING::
1154
+
1155
+ This is no longer implemented since the switch to Python3.
1156
+
1157
+ This method generates an interact shell that allows the user
1158
+ to manipulate query parameters and see the updated results.
1159
+
1160
+ .. TODO::
1161
+
1162
+ This function could use improvement. Add full options of typical
1163
+ :class:`~GraphQuery` (i.e.: have it accept list input); and update
1164
+ options in interact to make it less annoying to put in operators.
1165
+
1166
+ EXAMPLES::
1167
+
1168
+ sage: D = GraphDatabase()
1169
+ sage: D.interactive_query(display_cols=['graph6', 'num_vertices', 'degree_sequence'], num_edges=5, max_degree=3) # needs sage.symbolic
1170
+ Traceback (most recent call last):
1171
+ ...
1172
+ NotImplementedError: not available in Jupyter notebook
1173
+ """
1174
+ raise NotImplementedError('not available in Jupyter notebook')
1175
+ # print('<html><h1>Interactive Graph Query</h1></html>')
1176
+ # f = self._gen_interact_func(display=display_cols, **kwds)
1177
+ # interact(f)