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,581 @@
1
+ # sage_setup: distribution = sagemath-graphs
2
+ # sage.doctest: needs sage.modules
3
+ r"""
4
+ Mutually orthogonal Latin squares (MOLS)
5
+
6
+ The main function of this module is :func:`mutually_orthogonal_latin_squares`
7
+ and can be can be used to generate MOLS (or check that they exist)::
8
+
9
+ sage: MOLS = designs.mutually_orthogonal_latin_squares(4,8) # needs sage.schemes
10
+
11
+ For more information on MOLS, see the :wikipedia:`Wikipedia entry on MOLS
12
+ <Graeco-Latin_square#Mutually_orthogonal_Latin_squares>`. If you are only
13
+ interested by latin squares, see :mod:`~sage.combinat.matrices.latin`.
14
+
15
+ The functions defined here are
16
+
17
+ .. csv-table::
18
+ :class: contentstable
19
+ :widths: 30, 70
20
+ :delim: |
21
+
22
+ :meth:`mutually_orthogonal_latin_squares` | Return `k` Mutually Orthogonal `n\times n` Latin Squares.
23
+ :meth:`are_mutually_orthogonal_latin_squares` | Check that the list ``l`` of matrices in are MOLS.
24
+ :meth:`latin_square_product` | Return the product of two (or more) latin squares.
25
+ :meth:`MOLS_table` | Print the MOLS table.
26
+
27
+ **Table of MOLS**
28
+
29
+ Sage can produce a table of MOLS similar to the one from the Handbook of
30
+ Combinatorial Designs [DesignHandbook]_ (`available here
31
+ <http://books.google.fr/books?id=S9FA9rq1BgoC&dq=handbook%20combinatorial%20designs%20MOLS%2010000&pg=PA176>`_).
32
+
33
+ ::
34
+
35
+ sage: from sage.combinat.designs.latin_squares import MOLS_table
36
+ sage: MOLS_table(600) # long time
37
+ 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
38
+ ________________________________________________________________________________
39
+ 0| +oo +oo 1 2 3 4 1 6 7 8 2 10 5 12 4 4 15 16 5 18
40
+ 20| 4 5 3 22 7 24 4 26 5 28 4 30 31 5 4 5 8 36 4 5
41
+ 40| 7 40 5 42 5 6 4 46 8 48 6 5 5 52 5 6 7 7 5 58
42
+ 60| 5 60 5 6 63 7 5 66 5 6 6 70 7 72 5 7 6 6 6 78
43
+ 80| 9 80 8 82 6 6 6 6 7 88 6 7 6 6 6 6 7 96 6 8
44
+ 100| 8 100 6 102 7 7 6 106 6 108 6 6 13 112 6 7 6 8 6 6
45
+ 120| 7 120 6 6 6 124 6 126 127 7 6 130 6 7 6 7 7 136 6 138
46
+ 140| 6 7 6 10 10 7 6 7 6 148 6 150 7 8 8 7 6 156 7 6
47
+ 160| 9 7 6 162 6 7 6 166 7 168 6 8 6 172 6 6 14 9 6 178
48
+ 180| 6 180 6 6 7 9 6 10 6 8 6 190 7 192 6 7 6 196 6 198
49
+ 200| 7 7 6 7 6 8 6 8 14 11 10 210 6 7 6 7 7 8 6 10
50
+ 220| 6 12 6 222 13 8 6 226 6 228 6 7 7 232 6 7 6 7 6 238
51
+ 240| 7 240 6 242 6 7 6 12 7 7 6 250 6 12 9 7 255 256 6 12
52
+ 260| 6 8 8 262 7 8 7 10 7 268 7 270 15 16 6 13 10 276 6 9
53
+ 280| 7 280 6 282 6 12 6 7 15 288 6 6 6 292 6 6 7 10 10 12
54
+ 300| 7 7 7 7 15 15 6 306 7 7 7 310 7 312 7 10 7 316 7 10
55
+ 320| 15 15 6 16 8 12 6 7 7 9 6 330 7 8 7 6 7 336 6 7
56
+ 340| 6 10 10 342 7 7 6 346 6 348 8 12 18 352 6 9 7 9 6 358
57
+ 360| 7 360 6 7 7 7 6 366 15 15 7 15 7 372 7 15 7 13 7 378
58
+ 380| 7 12 7 382 15 15 7 15 7 388 7 16 7 7 7 7 8 396 7 7
59
+ 400| 15 400 7 15 11 8 7 15 8 408 7 13 8 12 10 9 18 15 7 418
60
+ 420| 7 420 7 15 7 16 6 7 7 7 6 430 15 432 6 15 6 18 7 438
61
+ 440| 7 15 7 442 7 13 7 11 15 448 7 15 7 7 7 15 7 456 7 16
62
+ 460| 7 460 7 462 15 15 7 466 8 8 7 15 7 15 10 18 7 15 6 478
63
+ 480| 15 15 6 15 8 7 6 486 7 15 6 490 6 16 6 7 15 15 6 498
64
+ 500| 7 8 9 502 7 15 6 15 7 508 6 15 511 18 7 15 8 12 8 15
65
+ 520| 8 520 10 522 12 15 8 16 15 528 7 15 8 12 7 15 8 15 10 15
66
+ 540| 12 540 7 15 18 7 7 546 7 8 7 18 7 7 7 7 7 556 7 12
67
+ 560| 15 7 7 562 7 7 6 7 7 568 6 570 7 7 15 22 8 576 7 7
68
+ 580| 7 8 7 10 7 8 7 586 7 18 17 7 15 592 8 15 7 7 8 598
69
+
70
+ Comparison with the results from the Handbook of Combinatorial Designs (2ed)
71
+ [DesignHandbook]_::
72
+
73
+ sage: MOLS_table(600,compare=True) # long time
74
+ 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
75
+ ________________________________________________________________________________
76
+ 0| + +
77
+ 20|
78
+ 40|
79
+ 60|
80
+ 80|
81
+ 100|
82
+ 120|
83
+ 140|
84
+ 160|
85
+ 180|
86
+ 200| -
87
+ 220|
88
+ 240|
89
+ 260|
90
+ 280|
91
+ 300|
92
+ 320| -
93
+ 340|
94
+ 360| - -
95
+ 380| -
96
+ 400|
97
+ 420| -
98
+ 440|
99
+ 460|
100
+ 480|
101
+ 500| -
102
+ 520|
103
+ 540|
104
+ 560|
105
+ 580|
106
+
107
+ .. TODO::
108
+
109
+ Look at [ColDin01]_.
110
+
111
+ REFERENCES:
112
+
113
+ .. [Stinson2004] Douglas R. Stinson,
114
+ *Combinatorial designs: construction and analysis*,
115
+ Springer, 2004.
116
+
117
+ .. [ColDin01] Charles Colbourn, Jeffrey Dinitz,
118
+ *Mutually orthogonal latin squares: a brief survey of constructions*,
119
+ Volume 95, Issues 1-2, Pages 9-48,
120
+ Journal of Statistical Planning and Inference,
121
+ Springer, 1 May 2001.
122
+
123
+ Functions
124
+ ---------
125
+ """
126
+ from itertools import repeat
127
+ from sage.rings.integer import Integer
128
+ from sage.categories.sets_cat import EmptySetError
129
+ from sage.misc.unknown import Unknown
130
+ from sage.arith.misc import is_prime_power
131
+ from sage.rings.finite_rings.finite_field_constructor import GF
132
+
133
+
134
+ def are_mutually_orthogonal_latin_squares(l, verbose=False):
135
+ r"""
136
+ Check whether the list of matrices in ``l`` form mutually orthogonal latin
137
+ squares.
138
+
139
+ INPUT:
140
+
141
+ - ``verbose`` -- if ``True`` then print why the list of matrices provided are
142
+ not mutually orthogonal latin squares
143
+
144
+ EXAMPLES::
145
+
146
+ sage: from sage.combinat.designs.latin_squares import are_mutually_orthogonal_latin_squares
147
+ sage: m1 = matrix([[0,1,2],[2,0,1],[1,2,0]])
148
+ sage: m2 = matrix([[0,1,2],[1,2,0],[2,0,1]])
149
+ sage: m3 = matrix([[0,1,2],[2,0,1],[1,2,0]])
150
+ sage: are_mutually_orthogonal_latin_squares([m1,m2])
151
+ True
152
+ sage: are_mutually_orthogonal_latin_squares([m1,m3])
153
+ False
154
+ sage: are_mutually_orthogonal_latin_squares([m2,m3])
155
+ True
156
+ sage: are_mutually_orthogonal_latin_squares([m1,m2,m3], verbose=True)
157
+ Squares 0 and 2 are not orthogonal
158
+ False
159
+
160
+ sage: m = designs.mutually_orthogonal_latin_squares(7,8) # needs sage.schemes
161
+ sage: are_mutually_orthogonal_latin_squares(m) # needs sage.schemes
162
+ True
163
+
164
+ TESTS:
165
+
166
+ Not a latin square::
167
+
168
+ sage: m1 = matrix([[0,1,0],[2,0,1],[1,2,0]])
169
+ sage: m2 = matrix([[0,1,2],[1,2,0],[2,0,1]])
170
+ sage: are_mutually_orthogonal_latin_squares([m1,m2], verbose=True)
171
+ Matrix 0 is not row latin
172
+ False
173
+ sage: m1 = matrix([[0,1,2],[1,0,2],[1,2,0]])
174
+ sage: are_mutually_orthogonal_latin_squares([m1,m2], verbose=True)
175
+ Matrix 0 is not column latin
176
+ False
177
+ sage: m1 = matrix([[0,0,0],[1,1,1],[2,2,2]])
178
+ sage: m2 = matrix([[0,1,2],[0,1,2],[0,1,2]])
179
+ sage: are_mutually_orthogonal_latin_squares([m1,m2])
180
+ False
181
+ """
182
+
183
+ if not l:
184
+ raise ValueError("the list must be non empty")
185
+
186
+ n = l[0].ncols()
187
+ k = len(l)
188
+ if any(M.ncols() != n or M.nrows() != n for M in l):
189
+ if verbose:
190
+ print("Not all matrices are square matrices of the same dimensions")
191
+ return False
192
+
193
+ # Check that all matrices are latin squares
194
+ for i,M in enumerate(l):
195
+ if any(len(set(R)) != n for R in M):
196
+ if verbose:
197
+ print("Matrix {} is not row latin".format(i))
198
+ return False
199
+ if any(len(set(R)) != n for R in zip(*M)):
200
+ if verbose:
201
+ print("Matrix {} is not column latin".format(i))
202
+ return False
203
+
204
+ from .designs_pyx import is_orthogonal_array
205
+ return is_orthogonal_array(list(zip(*[[x for R in M for x in R] for M in l])),k,n, verbose=verbose, terminology='MOLS')
206
+
207
+
208
+ def mutually_orthogonal_latin_squares(k, n, partitions=False, check=True):
209
+ r"""
210
+ Return `k` Mutually Orthogonal `n\times n` Latin Squares (MOLS).
211
+
212
+ For more information on Mutually Orthogonal Latin Squares, see
213
+ :mod:`~sage.combinat.designs.latin_squares`.
214
+
215
+ INPUT:
216
+
217
+ - ``k`` -- integer; number of MOLS. If ``k`` is ``None`` it is set to the largest
218
+ value available
219
+
220
+ - ``n`` -- integer; size of the latin square
221
+
222
+ - ``partitions`` -- boolean; a Latin Square can be seen as 3 partitions of
223
+ the `n^2` cells of the array into `n` sets of size `n`, respectively:
224
+
225
+ * The partition of rows
226
+ * The partition of columns
227
+ * The partition of number (cells numbered with 0, cells numbered with 1,
228
+ ...)
229
+
230
+ These partitions have the additional property that any two sets from
231
+ different partitions intersect on exactly one element.
232
+
233
+ When ``partitions`` is set to ``True``, this function returns a list of `k+2`
234
+ partitions satisfying this intersection property instead of the `k+2` MOLS
235
+ (though the data is exactly the same in both cases).
236
+
237
+ - ``check`` -- boolean (default: ``True``); whether to check that output is
238
+ correct before returning it. As this is expected to be useless, you may
239
+ want to disable it whenever you want speed.
240
+
241
+ EXAMPLES::
242
+
243
+ sage: designs.mutually_orthogonal_latin_squares(4,5) # needs sage.schemes
244
+ [
245
+ [0 1 2 3 4] [0 1 2 3 4] [0 1 2 3 4] [0 1 2 3 4]
246
+ [1 2 3 4 0] [2 3 4 0 1] [3 4 0 1 2] [4 0 1 2 3]
247
+ [2 3 4 0 1] [4 0 1 2 3] [1 2 3 4 0] [3 4 0 1 2]
248
+ [3 4 0 1 2] [1 2 3 4 0] [4 0 1 2 3] [2 3 4 0 1]
249
+ [4 0 1 2 3], [3 4 0 1 2], [2 3 4 0 1], [1 2 3 4 0]
250
+ ]
251
+
252
+ sage: designs.mutually_orthogonal_latin_squares(3,7) # needs sage.schemes
253
+ [
254
+ [0 1 2 3 4 5 6] [0 1 2 3 4 5 6] [0 1 2 3 4 5 6]
255
+ [1 2 3 4 5 6 0] [2 3 4 5 6 0 1] [3 4 5 6 0 1 2]
256
+ [2 3 4 5 6 0 1] [4 5 6 0 1 2 3] [6 0 1 2 3 4 5]
257
+ [3 4 5 6 0 1 2] [6 0 1 2 3 4 5] [2 3 4 5 6 0 1]
258
+ [4 5 6 0 1 2 3] [1 2 3 4 5 6 0] [5 6 0 1 2 3 4]
259
+ [5 6 0 1 2 3 4] [3 4 5 6 0 1 2] [1 2 3 4 5 6 0]
260
+ [6 0 1 2 3 4 5], [5 6 0 1 2 3 4], [4 5 6 0 1 2 3]
261
+ ]
262
+
263
+ sage: designs.mutually_orthogonal_latin_squares(2,5,partitions=True) # needs sage.schemes
264
+ [[[0, 1, 2, 3, 4],
265
+ [5, 6, 7, 8, 9],
266
+ [10, 11, 12, 13, 14],
267
+ [15, 16, 17, 18, 19],
268
+ [20, 21, 22, 23, 24]],
269
+ [[0, 5, 10, 15, 20],
270
+ [1, 6, 11, 16, 21],
271
+ [2, 7, 12, 17, 22],
272
+ [3, 8, 13, 18, 23],
273
+ [4, 9, 14, 19, 24]],
274
+ [[0, 9, 13, 17, 21],
275
+ [1, 5, 14, 18, 22],
276
+ [2, 6, 10, 19, 23],
277
+ [3, 7, 11, 15, 24],
278
+ [4, 8, 12, 16, 20]],
279
+ [[0, 8, 11, 19, 22],
280
+ [1, 9, 12, 15, 23],
281
+ [2, 5, 13, 16, 24],
282
+ [3, 6, 14, 17, 20],
283
+ [4, 7, 10, 18, 21]]]
284
+
285
+ What is the maximum number of MOLS of size 8 that Sage knows how to build?::
286
+
287
+ sage: designs.orthogonal_arrays.largest_available_k(8)-2 # needs sage.schemes
288
+ 7
289
+
290
+ If you only want to know if Sage is able to build a given set of
291
+ MOLS, query the ``orthogonal_arrays.*`` functions::
292
+
293
+ sage: designs.orthogonal_arrays.is_available(5+2, 5) # 5 MOLS of order 5
294
+ False
295
+ sage: designs.orthogonal_arrays.is_available(4+2,6) # 4 MOLS of order 6 # needs sage.schemes
296
+ False
297
+
298
+ Sage, however, is not able to prove that the second MOLS do not exist::
299
+
300
+ sage: designs.orthogonal_arrays.exists(4+2,6) # 4 MOLS of order 6 # needs sage.schemes
301
+ Unknown
302
+
303
+ If you ask for such a MOLS then you will respectively get an informative
304
+ :exc:`EmptySetError` or :exc:`NotImplementedError`::
305
+
306
+ sage: designs.mutually_orthogonal_latin_squares(5, 5)
307
+ Traceback (most recent call last):
308
+ ...
309
+ EmptySetError: there exist at most n-1 MOLS of size n if n>=2
310
+ sage: designs.mutually_orthogonal_latin_squares(4,6) # needs sage.schemes
311
+ Traceback (most recent call last):
312
+ ...
313
+ NotImplementedError: I don't know how to build 4 MOLS of order 6
314
+
315
+ TESTS:
316
+
317
+ The special case `n=1`::
318
+
319
+ sage: designs.mutually_orthogonal_latin_squares(3, 1)
320
+ [[0], [0], [0]]
321
+
322
+ Wrong input for `k`::
323
+
324
+ sage: designs.mutually_orthogonal_latin_squares(None, 1)
325
+ Traceback (most recent call last):
326
+ ...
327
+ TypeError: k must be a positive integer
328
+
329
+ sage: designs.mutually_orthogonal_latin_squares(-1, 1)
330
+ Traceback (most recent call last):
331
+ ...
332
+ ValueError: k must be positive
333
+
334
+ sage: designs.mutually_orthogonal_latin_squares(2,10)
335
+ [
336
+ [1 8 9 0 2 4 6 3 5 7] [1 7 6 5 0 9 8 2 3 4]
337
+ [7 2 8 9 0 3 5 4 6 1] [8 2 1 7 6 0 9 3 4 5]
338
+ [6 1 3 8 9 0 4 5 7 2] [9 8 3 2 1 7 0 4 5 6]
339
+ [5 7 2 4 8 9 0 6 1 3] [0 9 8 4 3 2 1 5 6 7]
340
+ [0 6 1 3 5 8 9 7 2 4] [2 0 9 8 5 4 3 6 7 1]
341
+ [9 0 7 2 4 6 8 1 3 5] [4 3 0 9 8 6 5 7 1 2]
342
+ [8 9 0 1 3 5 7 2 4 6] [6 5 4 0 9 8 7 1 2 3]
343
+ [2 3 4 5 6 7 1 8 9 0] [3 4 5 6 7 1 2 8 0 9]
344
+ [3 4 5 6 7 1 2 0 8 9] [5 6 7 1 2 3 4 0 9 8]
345
+ [4 5 6 7 1 2 3 9 0 8], [7 1 2 3 4 5 6 9 8 0]
346
+ ]
347
+
348
+ Verify the construction from [KD2015]_::
349
+
350
+ sage: designs.mutually_orthogonal_latin_squares(2, 9)
351
+ [
352
+ [0 1 2 3 4 5 6 7 8] [0 1 2 3 4 5 6 7 8]
353
+ [2 3 6 4 1 8 0 5 7] [3 8 4 7 5 2 1 0 6]
354
+ [3 8 4 7 5 2 1 0 6] [4 7 1 5 8 6 3 2 0]
355
+ [4 7 1 5 8 6 3 2 0] [5 0 8 2 6 1 7 4 3]
356
+ [5 0 8 2 6 1 7 4 3] [6 4 0 1 3 7 2 8 5]
357
+ [6 4 0 1 3 7 2 8 5] [7 6 5 0 2 4 8 3 1]
358
+ [7 6 5 0 2 4 8 3 1] [8 2 7 6 0 3 5 1 4]
359
+ [8 2 7 6 0 3 5 1 4] [1 5 3 8 7 0 4 6 2]
360
+ [1 5 3 8 7 0 4 6 2], [2 3 6 4 1 8 0 5 7]
361
+ ]
362
+ """
363
+ from sage.combinat.designs.orthogonal_arrays import orthogonal_array
364
+ from sage.matrix.constructor import Matrix
365
+ from .database import MOLS_constructions
366
+
367
+ if k is None:
368
+ raise TypeError('k must be a positive integer')
369
+ try:
370
+ Integer(k)
371
+ except TypeError:
372
+ raise
373
+ if k < 0:
374
+ raise ValueError('k must be positive')
375
+
376
+ if n == 1:
377
+ matrices = [Matrix([[0]])] * k
378
+
379
+ elif k >= n:
380
+ raise EmptySetError("there exist at most n-1 MOLS of size n if n>=2")
381
+
382
+ elif n in MOLS_constructions and k <= MOLS_constructions[n][0]:
383
+ _, construction = MOLS_constructions[n]
384
+
385
+ matrices = construction()[:k]
386
+
387
+ # Implements the construction from Theorem 5.2.4 of [KD2015]_ for prime powers.
388
+ # This was implemented to fix :issue:`26107`, which pointed out that this
389
+ # function was unacceptably slow when n was a large prime power
390
+ elif is_prime_power(n):
391
+ F = list(GF(n))
392
+
393
+ # We need the first element of the list to be 0
394
+ assert F[0] == 0
395
+
396
+ # This dictionary is used to convert from field elements to integers
397
+ conv = {F[i] : i for i in range(n)}
398
+
399
+ # Make the matrices
400
+ matrices = [Matrix([[conv[F[i] + F[r]*F[j]] for i in range(n)]
401
+ for j in range(n)]) for r in range(1, k+1)]
402
+
403
+ elif orthogonal_array(k + 2, n, existence=True) is not Unknown:
404
+ # Forwarding non-existence results
405
+ if orthogonal_array(k + 2, n, existence=True):
406
+ pass
407
+ else:
408
+ raise EmptySetError("there does not exist {} MOLS of order {}!".format(k, n))
409
+
410
+ # make sure that the first two columns are "11, 12, ..., 1n, 21, 22, ..."
411
+ OA = sorted(orthogonal_array(k + 2, n, check=False))
412
+
413
+ # We first define matrices as lists of n^2 values
414
+ matrices = [[] for _ in repeat(None, k)]
415
+ for L in OA:
416
+ for i in range(2, k + 2):
417
+ matrices[i-2].append(L[i])
418
+
419
+ # The real matrices
420
+ matrices = [[M[i*n:(i+1)*n] for i in range(n)] for M in matrices]
421
+ matrices = [Matrix(M) for M in matrices]
422
+
423
+ else:
424
+ raise NotImplementedError("I don't know how to build {} MOLS of order {}".format(k, n))
425
+
426
+ if check:
427
+ assert are_mutually_orthogonal_latin_squares(matrices)
428
+
429
+ # partitions have been requested but have not been computed yet
430
+ if partitions is True:
431
+ partitions = [[[i*n+j for j in range(n)] for i in range(n)],
432
+ [[j*n+i for j in range(n)] for i in range(n)]]
433
+ for m in matrices:
434
+ partition = [[] for _ in repeat(None, n)]
435
+ for i in range(n):
436
+ for j in range(n):
437
+ partition[m[i,j]].append(i*n+j)
438
+ partitions.append(partition)
439
+
440
+ if partitions:
441
+ return partitions
442
+ else:
443
+ return matrices
444
+
445
+
446
+ def latin_square_product(M, N, *others):
447
+ r"""
448
+ Return the product of two (or more) latin squares.
449
+
450
+ Given two Latin Squares `M,N` of respective sizes `m,n`, the direct product
451
+ `M\times N` of size `mn` is defined by `(M\times
452
+ N)((i_1,i_2),(j_1,j_2))=(M(i_1,j_1),N(i_2,j_2))` where `i_1,j_1\in [m],
453
+ i_2,j_2\in [n]`
454
+
455
+ Each pair of values `(i,j)\in [m]\times [n]` is then relabeled to `in+j`.
456
+
457
+ This is Lemma 6.25 of [Stinson2004]_.
458
+
459
+ INPUT:
460
+
461
+ - ``M``, ``N``, ``*others`` -- an arbitrary number of latin squares
462
+ (greater than or equal to 2)
463
+
464
+ EXAMPLES::
465
+
466
+ sage: from sage.combinat.designs.latin_squares import latin_square_product
467
+ sage: m=designs.mutually_orthogonal_latin_squares(3,4)[0] # needs sage.schemes
468
+ sage: latin_square_product(m,m,m) # needs sage.schemes
469
+ 64 x 64 sparse matrix over Integer Ring (use the '.str()' method to see the entries)
470
+ """
471
+ from sage.matrix.constructor import Matrix
472
+ m = M.nrows()
473
+ n = N.nrows()
474
+
475
+ D = {((i,j),(ii,jj)):(M[i,ii],N[j,jj])
476
+ for i in range(m)
477
+ for ii in range(m)
478
+ for j in range(n)
479
+ for jj in range(n)}
480
+
481
+ L = lambda i_j: i_j[0] * n + i_j[1]
482
+ D = {(L(c[0]), L(c[1])): L(v) for c, v in D.items()}
483
+ P = Matrix(D)
484
+
485
+ if others:
486
+ return latin_square_product(P, others[0], *others[1:])
487
+ else:
488
+ return P
489
+
490
+
491
+ def MOLS_table(start, stop=None, compare=False, width=None):
492
+ r"""
493
+ Print the MOLS table that Sage can produce.
494
+
495
+ INPUT:
496
+
497
+ - ``start``, ``stop`` -- integers; print the table of MOLS for value of
498
+ `n` such that ``start<=n<stop``. If only one integer is given as input,
499
+ it is interpreted as the value of ``stop`` with ``start=0`` (same
500
+ behaviour as ``range``).
501
+
502
+ - ``compare`` -- boolean; if sets to ``True`` the MOLS displays
503
+ with `+` and `-` entries its difference with the table from the
504
+ Handbook of Combinatorial Designs (2ed).
505
+
506
+ - ``width`` -- integer; the width of each column of the table. By default,
507
+ it is computed from range of values determined by the parameters ``start``
508
+ and ``stop``.
509
+
510
+ EXAMPLES::
511
+
512
+ sage: # needs sage.schemes
513
+ sage: from sage.combinat.designs.latin_squares import MOLS_table
514
+ sage: MOLS_table(100)
515
+ 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
516
+ ________________________________________________________________________________
517
+ 0| +oo +oo 1 2 3 4 1 6 7 8 2 10 5 12 4 4 15 16 5 18
518
+ 20| 4 5 3 22 7 24 4 26 5 28 4 30 31 5 4 5 8 36 4 5
519
+ 40| 7 40 5 42 5 6 4 46 8 48 6 5 5 52 5 6 7 7 5 58
520
+ 60| 5 60 5 6 63 7 5 66 5 6 6 70 7 72 5 7 6 6 6 78
521
+ 80| 9 80 8 82 6 6 6 6 7 88 6 7 6 6 6 6 7 96 6 8
522
+ sage: MOLS_table(100, width=4)
523
+ 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
524
+ ____________________________________________________________________________________________________
525
+ 0| +oo +oo 1 2 3 4 1 6 7 8 2 10 5 12 4 4 15 16 5 18
526
+ 20| 4 5 3 22 7 24 4 26 5 28 4 30 31 5 4 5 8 36 4 5
527
+ 40| 7 40 5 42 5 6 4 46 8 48 6 5 5 52 5 6 7 7 5 58
528
+ 60| 5 60 5 6 63 7 5 66 5 6 6 70 7 72 5 7 6 6 6 78
529
+ 80| 9 80 8 82 6 6 6 6 7 88 6 7 6 6 6 6 7 96 6 8
530
+ sage: MOLS_table(100, compare=True)
531
+ 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
532
+ ________________________________________________________________________________
533
+ 0| + +
534
+ 20|
535
+ 40|
536
+ 60|
537
+ 80|
538
+ sage: MOLS_table(50, 100, compare=True)
539
+ 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
540
+ ________________________________________________________________________________
541
+ 40|
542
+ 60|
543
+ 80|
544
+ """
545
+ from .orthogonal_arrays import largest_available_k
546
+ if stop is None:
547
+ start,stop = 0,start
548
+ # make start and stop be congruent to 0 mod 20
549
+ start = start - (start % 20)
550
+ stop = stop-1
551
+ stop = stop + (20-(stop % 20))
552
+ assert start % 20 == 0 and stop % 20 == 0
553
+ if stop <= start:
554
+ return
555
+
556
+ # choose an appropriate width (needs to be >= 3 because "+oo" should fit)
557
+ if width is None:
558
+ width = max(3, Integer(stop-1).ndigits(10))
559
+
560
+ print(" " * (width + 2) + " ".join("{i:>{width}}".format(i=i,width=width)
561
+ for i in range(20)))
562
+ print(" " * (width + 1) + "_" * ((width + 1) * 20), end="")
563
+ for i in range(start,stop):
564
+ if i % 20 == 0:
565
+ print("\n{:>{width}}|".format(i, width=width), end="")
566
+ k = largest_available_k(i)-2
567
+ if compare:
568
+ from . import MOLS_handbook_data
569
+ lower_bound = MOLS_handbook_data.lower_bound(i)
570
+ if i < 2 or lower_bound == k:
571
+ c = ""
572
+ elif lower_bound < k:
573
+ c = "+"
574
+ else:
575
+ c = "-"
576
+ else:
577
+ if i < 2:
578
+ c = "+oo"
579
+ else:
580
+ c = k
581
+ print(' {:>{width}}'.format(c, width=width), end="")