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