passagemath-categories 10.6.32__cp314-cp314t-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 (719) hide show
  1. passagemath_categories-10.6.32.dist-info/METADATA +156 -0
  2. passagemath_categories-10.6.32.dist-info/RECORD +719 -0
  3. passagemath_categories-10.6.32.dist-info/WHEEL +5 -0
  4. passagemath_categories-10.6.32.dist-info/top_level.txt +2 -0
  5. passagemath_categories.libs/libgcc_s-2d945d6c.so.1 +0 -0
  6. passagemath_categories.libs/libgmp-28992bcb.so.10.5.0 +0 -0
  7. passagemath_categories.libs/libstdc++-85f2cd6d.so.6.0.33 +0 -0
  8. sage/all__sagemath_categories.py +28 -0
  9. sage/arith/all.py +38 -0
  10. sage/arith/constants.pxd +27 -0
  11. sage/arith/functions.cpython-314t-aarch64-linux-musl.so +0 -0
  12. sage/arith/functions.pxd +4 -0
  13. sage/arith/functions.pyx +221 -0
  14. sage/arith/misc.py +6552 -0
  15. sage/arith/multi_modular.cpython-314t-aarch64-linux-musl.so +0 -0
  16. sage/arith/multi_modular.pxd +39 -0
  17. sage/arith/multi_modular.pyx +994 -0
  18. sage/arith/rational_reconstruction.cpython-314t-aarch64-linux-musl.so +0 -0
  19. sage/arith/rational_reconstruction.pxd +4 -0
  20. sage/arith/rational_reconstruction.pyx +115 -0
  21. sage/arith/srange.cpython-314t-aarch64-linux-musl.so +0 -0
  22. sage/arith/srange.pyx +571 -0
  23. sage/calculus/all__sagemath_categories.py +2 -0
  24. sage/calculus/functional.py +481 -0
  25. sage/calculus/functions.py +151 -0
  26. sage/categories/additive_groups.py +73 -0
  27. sage/categories/additive_magmas.py +1044 -0
  28. sage/categories/additive_monoids.py +114 -0
  29. sage/categories/additive_semigroups.py +184 -0
  30. sage/categories/affine_weyl_groups.py +238 -0
  31. sage/categories/algebra_ideals.py +95 -0
  32. sage/categories/algebra_modules.py +96 -0
  33. sage/categories/algebras.py +349 -0
  34. sage/categories/algebras_with_basis.py +377 -0
  35. sage/categories/all.py +160 -0
  36. sage/categories/aperiodic_semigroups.py +29 -0
  37. sage/categories/associative_algebras.py +47 -0
  38. sage/categories/bialgebras.py +101 -0
  39. sage/categories/bialgebras_with_basis.py +414 -0
  40. sage/categories/bimodules.py +206 -0
  41. sage/categories/chain_complexes.py +268 -0
  42. sage/categories/classical_crystals.py +480 -0
  43. sage/categories/coalgebras.py +405 -0
  44. sage/categories/coalgebras_with_basis.py +232 -0
  45. sage/categories/coercion_methods.cpython-314t-aarch64-linux-musl.so +0 -0
  46. sage/categories/coercion_methods.pyx +52 -0
  47. sage/categories/commutative_additive_groups.py +104 -0
  48. sage/categories/commutative_additive_monoids.py +45 -0
  49. sage/categories/commutative_additive_semigroups.py +48 -0
  50. sage/categories/commutative_algebra_ideals.py +87 -0
  51. sage/categories/commutative_algebras.py +94 -0
  52. sage/categories/commutative_ring_ideals.py +58 -0
  53. sage/categories/commutative_rings.py +736 -0
  54. sage/categories/complete_discrete_valuation.py +293 -0
  55. sage/categories/complex_reflection_groups.py +145 -0
  56. sage/categories/complex_reflection_or_generalized_coxeter_groups.py +1249 -0
  57. sage/categories/coxeter_group_algebras.py +186 -0
  58. sage/categories/coxeter_groups.py +3402 -0
  59. sage/categories/crystals.py +2628 -0
  60. sage/categories/cw_complexes.py +216 -0
  61. sage/categories/dedekind_domains.py +137 -0
  62. sage/categories/discrete_valuation.py +325 -0
  63. sage/categories/distributive_magmas_and_additive_magmas.py +100 -0
  64. sage/categories/division_rings.py +114 -0
  65. sage/categories/domains.py +95 -0
  66. sage/categories/drinfeld_modules.py +789 -0
  67. sage/categories/dual.py +42 -0
  68. sage/categories/enumerated_sets.py +1146 -0
  69. sage/categories/euclidean_domains.py +271 -0
  70. sage/categories/examples/algebras_with_basis.py +102 -0
  71. sage/categories/examples/all.py +1 -0
  72. sage/categories/examples/commutative_additive_monoids.py +130 -0
  73. sage/categories/examples/commutative_additive_semigroups.py +199 -0
  74. sage/categories/examples/coxeter_groups.py +8 -0
  75. sage/categories/examples/crystals.py +236 -0
  76. sage/categories/examples/cw_complexes.py +163 -0
  77. sage/categories/examples/facade_sets.py +187 -0
  78. sage/categories/examples/filtered_algebras_with_basis.py +204 -0
  79. sage/categories/examples/filtered_modules_with_basis.py +154 -0
  80. sage/categories/examples/finite_coxeter_groups.py +252 -0
  81. sage/categories/examples/finite_dimensional_algebras_with_basis.py +148 -0
  82. sage/categories/examples/finite_dimensional_lie_algebras_with_basis.py +495 -0
  83. sage/categories/examples/finite_enumerated_sets.py +208 -0
  84. sage/categories/examples/finite_monoids.py +150 -0
  85. sage/categories/examples/finite_semigroups.py +190 -0
  86. sage/categories/examples/finite_weyl_groups.py +191 -0
  87. sage/categories/examples/graded_connected_hopf_algebras_with_basis.py +152 -0
  88. sage/categories/examples/graded_modules_with_basis.py +168 -0
  89. sage/categories/examples/graphs.py +122 -0
  90. sage/categories/examples/hopf_algebras_with_basis.py +145 -0
  91. sage/categories/examples/infinite_enumerated_sets.py +190 -0
  92. sage/categories/examples/lie_algebras.py +352 -0
  93. sage/categories/examples/lie_algebras_with_basis.py +196 -0
  94. sage/categories/examples/magmas.py +162 -0
  95. sage/categories/examples/manifolds.py +94 -0
  96. sage/categories/examples/monoids.py +144 -0
  97. sage/categories/examples/posets.py +178 -0
  98. sage/categories/examples/semigroups.py +580 -0
  99. sage/categories/examples/semigroups_cython.cpython-314t-aarch64-linux-musl.so +0 -0
  100. sage/categories/examples/semigroups_cython.pyx +221 -0
  101. sage/categories/examples/semirings.py +249 -0
  102. sage/categories/examples/sets_cat.py +706 -0
  103. sage/categories/examples/sets_with_grading.py +101 -0
  104. sage/categories/examples/with_realizations.py +542 -0
  105. sage/categories/fields.py +991 -0
  106. sage/categories/filtered_algebras.py +63 -0
  107. sage/categories/filtered_algebras_with_basis.py +548 -0
  108. sage/categories/filtered_hopf_algebras_with_basis.py +138 -0
  109. sage/categories/filtered_modules.py +210 -0
  110. sage/categories/filtered_modules_with_basis.py +1209 -0
  111. sage/categories/finite_complex_reflection_groups.py +1506 -0
  112. sage/categories/finite_coxeter_groups.py +1138 -0
  113. sage/categories/finite_crystals.py +103 -0
  114. sage/categories/finite_dimensional_algebras_with_basis.py +1860 -0
  115. sage/categories/finite_dimensional_bialgebras_with_basis.py +33 -0
  116. sage/categories/finite_dimensional_coalgebras_with_basis.py +33 -0
  117. sage/categories/finite_dimensional_graded_lie_algebras_with_basis.py +231 -0
  118. sage/categories/finite_dimensional_hopf_algebras_with_basis.py +38 -0
  119. sage/categories/finite_dimensional_lie_algebras_with_basis.py +2774 -0
  120. sage/categories/finite_dimensional_modules_with_basis.py +1407 -0
  121. sage/categories/finite_dimensional_nilpotent_lie_algebras_with_basis.py +167 -0
  122. sage/categories/finite_dimensional_semisimple_algebras_with_basis.py +270 -0
  123. sage/categories/finite_enumerated_sets.py +769 -0
  124. sage/categories/finite_fields.py +252 -0
  125. sage/categories/finite_groups.py +256 -0
  126. sage/categories/finite_lattice_posets.py +242 -0
  127. sage/categories/finite_monoids.py +316 -0
  128. sage/categories/finite_permutation_groups.py +339 -0
  129. sage/categories/finite_posets.py +1994 -0
  130. sage/categories/finite_semigroups.py +136 -0
  131. sage/categories/finite_sets.py +93 -0
  132. sage/categories/finite_weyl_groups.py +39 -0
  133. sage/categories/finitely_generated_lambda_bracket_algebras.py +112 -0
  134. sage/categories/finitely_generated_lie_conformal_algebras.py +114 -0
  135. sage/categories/finitely_generated_magmas.py +57 -0
  136. sage/categories/finitely_generated_semigroups.py +214 -0
  137. sage/categories/function_fields.py +76 -0
  138. sage/categories/g_sets.py +77 -0
  139. sage/categories/gcd_domains.py +65 -0
  140. sage/categories/generalized_coxeter_groups.py +94 -0
  141. sage/categories/graded_algebras.py +85 -0
  142. sage/categories/graded_algebras_with_basis.py +258 -0
  143. sage/categories/graded_bialgebras.py +32 -0
  144. sage/categories/graded_bialgebras_with_basis.py +32 -0
  145. sage/categories/graded_coalgebras.py +65 -0
  146. sage/categories/graded_coalgebras_with_basis.py +51 -0
  147. sage/categories/graded_hopf_algebras.py +41 -0
  148. sage/categories/graded_hopf_algebras_with_basis.py +169 -0
  149. sage/categories/graded_lie_algebras.py +91 -0
  150. sage/categories/graded_lie_algebras_with_basis.py +44 -0
  151. sage/categories/graded_lie_conformal_algebras.py +74 -0
  152. sage/categories/graded_modules.py +133 -0
  153. sage/categories/graded_modules_with_basis.py +329 -0
  154. sage/categories/graphs.py +138 -0
  155. sage/categories/group_algebras.py +430 -0
  156. sage/categories/groupoid.py +94 -0
  157. sage/categories/groups.py +667 -0
  158. sage/categories/h_trivial_semigroups.py +64 -0
  159. sage/categories/hecke_modules.py +185 -0
  160. sage/categories/highest_weight_crystals.py +980 -0
  161. sage/categories/hopf_algebras.py +219 -0
  162. sage/categories/hopf_algebras_with_basis.py +309 -0
  163. sage/categories/infinite_enumerated_sets.py +115 -0
  164. sage/categories/integral_domains.py +203 -0
  165. sage/categories/j_trivial_semigroups.py +29 -0
  166. sage/categories/kac_moody_algebras.py +82 -0
  167. sage/categories/kahler_algebras.py +203 -0
  168. sage/categories/l_trivial_semigroups.py +63 -0
  169. sage/categories/lambda_bracket_algebras.py +280 -0
  170. sage/categories/lambda_bracket_algebras_with_basis.py +107 -0
  171. sage/categories/lattice_posets.py +89 -0
  172. sage/categories/left_modules.py +49 -0
  173. sage/categories/lie_algebras.py +1070 -0
  174. sage/categories/lie_algebras_with_basis.py +261 -0
  175. sage/categories/lie_conformal_algebras.py +350 -0
  176. sage/categories/lie_conformal_algebras_with_basis.py +147 -0
  177. sage/categories/lie_groups.py +73 -0
  178. sage/categories/loop_crystals.py +1290 -0
  179. sage/categories/magmas.py +1189 -0
  180. sage/categories/magmas_and_additive_magmas.py +149 -0
  181. sage/categories/magmatic_algebras.py +365 -0
  182. sage/categories/manifolds.py +352 -0
  183. sage/categories/matrix_algebras.py +40 -0
  184. sage/categories/metric_spaces.py +387 -0
  185. sage/categories/modular_abelian_varieties.py +78 -0
  186. sage/categories/modules.py +989 -0
  187. sage/categories/modules_with_basis.py +2794 -0
  188. sage/categories/monoid_algebras.py +38 -0
  189. sage/categories/monoids.py +739 -0
  190. sage/categories/noetherian_rings.py +87 -0
  191. sage/categories/number_fields.py +242 -0
  192. sage/categories/ore_modules.py +189 -0
  193. sage/categories/partially_ordered_monoids.py +49 -0
  194. sage/categories/permutation_groups.py +63 -0
  195. sage/categories/pointed_sets.py +42 -0
  196. sage/categories/polyhedra.py +74 -0
  197. sage/categories/poor_man_map.py +270 -0
  198. sage/categories/posets.py +722 -0
  199. sage/categories/principal_ideal_domains.py +270 -0
  200. sage/categories/quantum_group_representations.py +543 -0
  201. sage/categories/quotient_fields.py +728 -0
  202. sage/categories/r_trivial_semigroups.py +45 -0
  203. sage/categories/regular_crystals.py +898 -0
  204. sage/categories/regular_supercrystals.py +170 -0
  205. sage/categories/right_modules.py +49 -0
  206. sage/categories/ring_ideals.py +74 -0
  207. sage/categories/rings.py +1904 -0
  208. sage/categories/rngs.py +175 -0
  209. sage/categories/schemes.py +393 -0
  210. sage/categories/semigroups.py +1060 -0
  211. sage/categories/semirings.py +71 -0
  212. sage/categories/semisimple_algebras.py +114 -0
  213. sage/categories/sets_with_grading.py +235 -0
  214. sage/categories/shephard_groups.py +43 -0
  215. sage/categories/signed_tensor.py +120 -0
  216. sage/categories/simplicial_complexes.py +134 -0
  217. sage/categories/simplicial_sets.py +1206 -0
  218. sage/categories/super_algebras.py +149 -0
  219. sage/categories/super_algebras_with_basis.py +144 -0
  220. sage/categories/super_hopf_algebras_with_basis.py +126 -0
  221. sage/categories/super_lie_conformal_algebras.py +193 -0
  222. sage/categories/super_modules.py +229 -0
  223. sage/categories/super_modules_with_basis.py +193 -0
  224. sage/categories/supercommutative_algebras.py +99 -0
  225. sage/categories/supercrystals.py +406 -0
  226. sage/categories/tensor.py +110 -0
  227. sage/categories/topological_spaces.py +170 -0
  228. sage/categories/triangular_kac_moody_algebras.py +439 -0
  229. sage/categories/tutorial.py +58 -0
  230. sage/categories/unique_factorization_domains.py +318 -0
  231. sage/categories/unital_algebras.py +426 -0
  232. sage/categories/vector_bundles.py +159 -0
  233. sage/categories/vector_spaces.py +357 -0
  234. sage/categories/weyl_groups.py +853 -0
  235. sage/combinat/all__sagemath_categories.py +34 -0
  236. sage/combinat/backtrack.py +180 -0
  237. sage/combinat/combinat.py +2269 -0
  238. sage/combinat/combinat_cython.cpython-314t-aarch64-linux-musl.so +0 -0
  239. sage/combinat/combinat_cython.pxd +6 -0
  240. sage/combinat/combinat_cython.pyx +390 -0
  241. sage/combinat/combination.py +796 -0
  242. sage/combinat/combinatorial_map.py +416 -0
  243. sage/combinat/composition.py +2192 -0
  244. sage/combinat/dlx.py +510 -0
  245. sage/combinat/integer_lists/__init__.py +7 -0
  246. sage/combinat/integer_lists/base.cpython-314t-aarch64-linux-musl.so +0 -0
  247. sage/combinat/integer_lists/base.pxd +16 -0
  248. sage/combinat/integer_lists/base.pyx +713 -0
  249. sage/combinat/integer_lists/invlex.cpython-314t-aarch64-linux-musl.so +0 -0
  250. sage/combinat/integer_lists/invlex.pxd +4 -0
  251. sage/combinat/integer_lists/invlex.pyx +1650 -0
  252. sage/combinat/integer_lists/lists.py +328 -0
  253. sage/combinat/integer_lists/nn.py +48 -0
  254. sage/combinat/integer_vector.py +1818 -0
  255. sage/combinat/integer_vector_weighted.py +413 -0
  256. sage/combinat/matrices/all__sagemath_categories.py +5 -0
  257. sage/combinat/matrices/dancing_links.cpython-314t-aarch64-linux-musl.so +0 -0
  258. sage/combinat/matrices/dancing_links.pyx +1159 -0
  259. sage/combinat/matrices/dancing_links_c.h +380 -0
  260. sage/combinat/matrices/dlxcpp.py +136 -0
  261. sage/combinat/partition.py +10070 -0
  262. sage/combinat/partitions.cpython-314t-aarch64-linux-musl.so +0 -0
  263. sage/combinat/partitions.pyx +743 -0
  264. sage/combinat/permutation.py +10168 -0
  265. sage/combinat/permutation_cython.cpython-314t-aarch64-linux-musl.so +0 -0
  266. sage/combinat/permutation_cython.pxd +11 -0
  267. sage/combinat/permutation_cython.pyx +407 -0
  268. sage/combinat/q_analogues.py +1090 -0
  269. sage/combinat/ranker.py +268 -0
  270. sage/combinat/subset.py +1561 -0
  271. sage/combinat/subsets_hereditary.py +202 -0
  272. sage/combinat/subsets_pairwise.py +184 -0
  273. sage/combinat/tools.py +63 -0
  274. sage/combinat/tuple.py +348 -0
  275. sage/data_structures/all.py +2 -0
  276. sage/data_structures/all__sagemath_categories.py +2 -0
  277. sage/data_structures/binary_matrix.pxd +138 -0
  278. sage/data_structures/binary_search.cpython-314t-aarch64-linux-musl.so +0 -0
  279. sage/data_structures/binary_search.pxd +3 -0
  280. sage/data_structures/binary_search.pyx +66 -0
  281. sage/data_structures/bitset.cpython-314t-aarch64-linux-musl.so +0 -0
  282. sage/data_structures/bitset.pxd +40 -0
  283. sage/data_structures/bitset.pyx +2385 -0
  284. sage/data_structures/bitset_base.cpython-314t-aarch64-linux-musl.so +0 -0
  285. sage/data_structures/bitset_base.pxd +926 -0
  286. sage/data_structures/bitset_base.pyx +117 -0
  287. sage/data_structures/bitset_intrinsics.h +487 -0
  288. sage/data_structures/blas_dict.cpython-314t-aarch64-linux-musl.so +0 -0
  289. sage/data_structures/blas_dict.pxd +12 -0
  290. sage/data_structures/blas_dict.pyx +469 -0
  291. sage/data_structures/list_of_pairs.cpython-314t-aarch64-linux-musl.so +0 -0
  292. sage/data_structures/list_of_pairs.pxd +16 -0
  293. sage/data_structures/list_of_pairs.pyx +122 -0
  294. sage/data_structures/mutable_poset.py +3312 -0
  295. sage/data_structures/pairing_heap.cpython-314t-aarch64-linux-musl.so +0 -0
  296. sage/data_structures/pairing_heap.h +346 -0
  297. sage/data_structures/pairing_heap.pxd +88 -0
  298. sage/data_structures/pairing_heap.pyx +1464 -0
  299. sage/data_structures/sparse_bitset.pxd +62 -0
  300. sage/data_structures/stream.py +5070 -0
  301. sage/databases/all__sagemath_categories.py +7 -0
  302. sage/databases/sql_db.py +2236 -0
  303. sage/ext/all__sagemath_categories.py +3 -0
  304. sage/ext/fast_callable.cpython-314t-aarch64-linux-musl.so +0 -0
  305. sage/ext/fast_callable.pxd +4 -0
  306. sage/ext/fast_callable.pyx +2746 -0
  307. sage/ext/fast_eval.cpython-314t-aarch64-linux-musl.so +0 -0
  308. sage/ext/fast_eval.pxd +1 -0
  309. sage/ext/fast_eval.pyx +102 -0
  310. sage/ext/interpreters/__init__.py +1 -0
  311. sage/ext/interpreters/all__sagemath_categories.py +2 -0
  312. sage/ext/interpreters/wrapper_el.cpython-314t-aarch64-linux-musl.so +0 -0
  313. sage/ext/interpreters/wrapper_el.pxd +18 -0
  314. sage/ext/interpreters/wrapper_el.pyx +148 -0
  315. sage/ext/interpreters/wrapper_py.cpython-314t-aarch64-linux-musl.so +0 -0
  316. sage/ext/interpreters/wrapper_py.pxd +17 -0
  317. sage/ext/interpreters/wrapper_py.pyx +133 -0
  318. sage/functions/airy.py +937 -0
  319. sage/functions/all.py +97 -0
  320. sage/functions/bessel.py +2102 -0
  321. sage/functions/error.py +784 -0
  322. sage/functions/exp_integral.py +1529 -0
  323. sage/functions/gamma.py +1087 -0
  324. sage/functions/generalized.py +672 -0
  325. sage/functions/hyperbolic.py +747 -0
  326. sage/functions/hypergeometric.py +1156 -0
  327. sage/functions/jacobi.py +1705 -0
  328. sage/functions/log.py +1402 -0
  329. sage/functions/min_max.py +338 -0
  330. sage/functions/orthogonal_polys.py +3106 -0
  331. sage/functions/other.py +2303 -0
  332. sage/functions/piecewise.py +1505 -0
  333. sage/functions/prime_pi.cpython-314t-aarch64-linux-musl.so +0 -0
  334. sage/functions/prime_pi.pyx +262 -0
  335. sage/functions/special.py +1212 -0
  336. sage/functions/spike_function.py +278 -0
  337. sage/functions/transcendental.py +690 -0
  338. sage/functions/trig.py +1062 -0
  339. sage/functions/wigner.py +726 -0
  340. sage/geometry/abc.cpython-314t-aarch64-linux-musl.so +0 -0
  341. sage/geometry/abc.pyx +82 -0
  342. sage/geometry/all__sagemath_categories.py +1 -0
  343. sage/groups/all__sagemath_categories.py +11 -0
  344. sage/groups/generic.py +1733 -0
  345. sage/groups/groups_catalog.py +113 -0
  346. sage/groups/perm_gps/all__sagemath_categories.py +1 -0
  347. sage/groups/perm_gps/partn_ref/all.py +1 -0
  348. sage/groups/perm_gps/partn_ref/all__sagemath_categories.py +1 -0
  349. sage/groups/perm_gps/partn_ref/automorphism_group_canonical_label.cpython-314t-aarch64-linux-musl.so +0 -0
  350. sage/groups/perm_gps/partn_ref/automorphism_group_canonical_label.pxd +52 -0
  351. sage/groups/perm_gps/partn_ref/automorphism_group_canonical_label.pyx +906 -0
  352. sage/groups/perm_gps/partn_ref/canonical_augmentation.cpython-314t-aarch64-linux-musl.so +0 -0
  353. sage/groups/perm_gps/partn_ref/canonical_augmentation.pxd +85 -0
  354. sage/groups/perm_gps/partn_ref/canonical_augmentation.pyx +534 -0
  355. sage/groups/perm_gps/partn_ref/data_structures.cpython-314t-aarch64-linux-musl.so +0 -0
  356. sage/groups/perm_gps/partn_ref/data_structures.pxd +576 -0
  357. sage/groups/perm_gps/partn_ref/data_structures.pyx +1792 -0
  358. sage/groups/perm_gps/partn_ref/double_coset.cpython-314t-aarch64-linux-musl.so +0 -0
  359. sage/groups/perm_gps/partn_ref/double_coset.pxd +45 -0
  360. sage/groups/perm_gps/partn_ref/double_coset.pyx +739 -0
  361. sage/groups/perm_gps/partn_ref/refinement_lists.cpython-314t-aarch64-linux-musl.so +0 -0
  362. sage/groups/perm_gps/partn_ref/refinement_lists.pxd +18 -0
  363. sage/groups/perm_gps/partn_ref/refinement_lists.pyx +82 -0
  364. sage/groups/perm_gps/partn_ref/refinement_python.cpython-314t-aarch64-linux-musl.so +0 -0
  365. sage/groups/perm_gps/partn_ref/refinement_python.pxd +16 -0
  366. sage/groups/perm_gps/partn_ref/refinement_python.pyx +564 -0
  367. sage/groups/perm_gps/partn_ref/refinement_sets.cpython-314t-aarch64-linux-musl.so +0 -0
  368. sage/groups/perm_gps/partn_ref/refinement_sets.pxd +60 -0
  369. sage/groups/perm_gps/partn_ref/refinement_sets.pyx +858 -0
  370. sage/interfaces/abc.py +140 -0
  371. sage/interfaces/all.py +58 -0
  372. sage/interfaces/all__sagemath_categories.py +1 -0
  373. sage/interfaces/expect.py +1643 -0
  374. sage/interfaces/interface.py +1682 -0
  375. sage/interfaces/process.cpython-314t-aarch64-linux-musl.so +0 -0
  376. sage/interfaces/process.pxd +5 -0
  377. sage/interfaces/process.pyx +288 -0
  378. sage/interfaces/quit.py +167 -0
  379. sage/interfaces/sage0.py +604 -0
  380. sage/interfaces/sagespawn.cpython-314t-aarch64-linux-musl.so +0 -0
  381. sage/interfaces/sagespawn.pyx +308 -0
  382. sage/interfaces/tab_completion.py +101 -0
  383. sage/misc/all__sagemath_categories.py +78 -0
  384. sage/misc/allocator.cpython-314t-aarch64-linux-musl.so +0 -0
  385. sage/misc/allocator.pxd +6 -0
  386. sage/misc/allocator.pyx +47 -0
  387. sage/misc/binary_tree.cpython-314t-aarch64-linux-musl.so +0 -0
  388. sage/misc/binary_tree.pxd +29 -0
  389. sage/misc/binary_tree.pyx +537 -0
  390. sage/misc/callable_dict.cpython-314t-aarch64-linux-musl.so +0 -0
  391. sage/misc/callable_dict.pyx +89 -0
  392. sage/misc/citation.cpython-314t-aarch64-linux-musl.so +0 -0
  393. sage/misc/citation.pyx +159 -0
  394. sage/misc/converting_dict.py +293 -0
  395. sage/misc/defaults.py +129 -0
  396. sage/misc/derivative.cpython-314t-aarch64-linux-musl.so +0 -0
  397. sage/misc/derivative.pyx +223 -0
  398. sage/misc/functional.py +2005 -0
  399. sage/misc/html.py +589 -0
  400. sage/misc/latex.py +2673 -0
  401. sage/misc/latex_macros.py +236 -0
  402. sage/misc/latex_standalone.py +1833 -0
  403. sage/misc/map_threaded.py +38 -0
  404. sage/misc/mathml.py +76 -0
  405. sage/misc/method_decorator.py +88 -0
  406. sage/misc/mrange.py +755 -0
  407. sage/misc/multireplace.py +41 -0
  408. sage/misc/object_multiplexer.py +92 -0
  409. sage/misc/parser.cpython-314t-aarch64-linux-musl.so +0 -0
  410. sage/misc/parser.pyx +1107 -0
  411. sage/misc/random_testing.py +264 -0
  412. sage/misc/rest_index_of_methods.py +377 -0
  413. sage/misc/search.cpython-314t-aarch64-linux-musl.so +0 -0
  414. sage/misc/search.pxd +2 -0
  415. sage/misc/search.pyx +68 -0
  416. sage/misc/stopgap.cpython-314t-aarch64-linux-musl.so +0 -0
  417. sage/misc/stopgap.pyx +95 -0
  418. sage/misc/table.py +853 -0
  419. sage/monoids/all__sagemath_categories.py +1 -0
  420. sage/monoids/indexed_free_monoid.py +1071 -0
  421. sage/monoids/monoid.py +82 -0
  422. sage/numerical/all__sagemath_categories.py +1 -0
  423. sage/numerical/backends/all__sagemath_categories.py +1 -0
  424. sage/numerical/backends/generic_backend.cpython-314t-aarch64-linux-musl.so +0 -0
  425. sage/numerical/backends/generic_backend.pxd +61 -0
  426. sage/numerical/backends/generic_backend.pyx +1893 -0
  427. sage/numerical/backends/generic_sdp_backend.cpython-314t-aarch64-linux-musl.so +0 -0
  428. sage/numerical/backends/generic_sdp_backend.pxd +38 -0
  429. sage/numerical/backends/generic_sdp_backend.pyx +755 -0
  430. sage/parallel/all.py +6 -0
  431. sage/parallel/decorate.py +575 -0
  432. sage/parallel/map_reduce.py +1997 -0
  433. sage/parallel/multiprocessing_sage.py +76 -0
  434. sage/parallel/ncpus.py +35 -0
  435. sage/parallel/parallelism.py +364 -0
  436. sage/parallel/reference.py +47 -0
  437. sage/parallel/use_fork.py +333 -0
  438. sage/rings/abc.cpython-314t-aarch64-linux-musl.so +0 -0
  439. sage/rings/abc.pxd +31 -0
  440. sage/rings/abc.pyx +526 -0
  441. sage/rings/algebraic_closure_finite_field.py +1154 -0
  442. sage/rings/all__sagemath_categories.py +91 -0
  443. sage/rings/big_oh.py +227 -0
  444. sage/rings/continued_fraction.py +2754 -0
  445. sage/rings/continued_fraction_gosper.py +220 -0
  446. sage/rings/factorint.cpython-314t-aarch64-linux-musl.so +0 -0
  447. sage/rings/factorint.pyx +295 -0
  448. sage/rings/fast_arith.cpython-314t-aarch64-linux-musl.so +0 -0
  449. sage/rings/fast_arith.pxd +21 -0
  450. sage/rings/fast_arith.pyx +535 -0
  451. sage/rings/finite_rings/all__sagemath_categories.py +9 -0
  452. sage/rings/finite_rings/conway_polynomials.py +542 -0
  453. sage/rings/finite_rings/element_base.cpython-314t-aarch64-linux-musl.so +0 -0
  454. sage/rings/finite_rings/element_base.pxd +12 -0
  455. sage/rings/finite_rings/element_base.pyx +1176 -0
  456. sage/rings/finite_rings/finite_field_base.cpython-314t-aarch64-linux-musl.so +0 -0
  457. sage/rings/finite_rings/finite_field_base.pxd +7 -0
  458. sage/rings/finite_rings/finite_field_base.pyx +2171 -0
  459. sage/rings/finite_rings/finite_field_constructor.py +827 -0
  460. sage/rings/finite_rings/finite_field_prime_modn.py +372 -0
  461. sage/rings/finite_rings/galois_group.py +154 -0
  462. sage/rings/finite_rings/hom_finite_field.cpython-314t-aarch64-linux-musl.so +0 -0
  463. sage/rings/finite_rings/hom_finite_field.pxd +23 -0
  464. sage/rings/finite_rings/hom_finite_field.pyx +856 -0
  465. sage/rings/finite_rings/hom_prime_finite_field.cpython-314t-aarch64-linux-musl.so +0 -0
  466. sage/rings/finite_rings/hom_prime_finite_field.pxd +15 -0
  467. sage/rings/finite_rings/hom_prime_finite_field.pyx +164 -0
  468. sage/rings/finite_rings/homset.py +357 -0
  469. sage/rings/finite_rings/integer_mod.cpython-314t-aarch64-linux-musl.so +0 -0
  470. sage/rings/finite_rings/integer_mod.pxd +56 -0
  471. sage/rings/finite_rings/integer_mod.pyx +4586 -0
  472. sage/rings/finite_rings/integer_mod_limits.h +11 -0
  473. sage/rings/finite_rings/integer_mod_ring.py +2044 -0
  474. sage/rings/finite_rings/residue_field.cpython-314t-aarch64-linux-musl.so +0 -0
  475. sage/rings/finite_rings/residue_field.pxd +30 -0
  476. sage/rings/finite_rings/residue_field.pyx +1811 -0
  477. sage/rings/finite_rings/stdint.pxd +19 -0
  478. sage/rings/fraction_field.py +1452 -0
  479. sage/rings/fraction_field_element.cpython-314t-aarch64-linux-musl.so +0 -0
  480. sage/rings/fraction_field_element.pyx +1357 -0
  481. sage/rings/function_field/all.py +7 -0
  482. sage/rings/function_field/all__sagemath_categories.py +2 -0
  483. sage/rings/function_field/constructor.py +218 -0
  484. sage/rings/function_field/element.cpython-314t-aarch64-linux-musl.so +0 -0
  485. sage/rings/function_field/element.pxd +11 -0
  486. sage/rings/function_field/element.pyx +1008 -0
  487. sage/rings/function_field/element_rational.cpython-314t-aarch64-linux-musl.so +0 -0
  488. sage/rings/function_field/element_rational.pyx +513 -0
  489. sage/rings/function_field/extensions.py +230 -0
  490. sage/rings/function_field/function_field.py +1468 -0
  491. sage/rings/function_field/function_field_rational.py +1005 -0
  492. sage/rings/function_field/ideal.py +1155 -0
  493. sage/rings/function_field/ideal_rational.py +629 -0
  494. sage/rings/function_field/jacobian_base.py +826 -0
  495. sage/rings/function_field/jacobian_hess.py +1053 -0
  496. sage/rings/function_field/jacobian_khuri_makdisi.py +1027 -0
  497. sage/rings/function_field/maps.py +1039 -0
  498. sage/rings/function_field/order.py +281 -0
  499. sage/rings/function_field/order_basis.py +586 -0
  500. sage/rings/function_field/order_rational.py +576 -0
  501. sage/rings/function_field/place.py +426 -0
  502. sage/rings/function_field/place_rational.py +181 -0
  503. sage/rings/generic.py +320 -0
  504. sage/rings/homset.py +332 -0
  505. sage/rings/ideal.py +1885 -0
  506. sage/rings/ideal_monoid.py +215 -0
  507. sage/rings/infinity.py +1890 -0
  508. sage/rings/integer.cpython-314t-aarch64-linux-musl.so +0 -0
  509. sage/rings/integer.pxd +45 -0
  510. sage/rings/integer.pyx +7874 -0
  511. sage/rings/integer_ring.cpython-314t-aarch64-linux-musl.so +0 -0
  512. sage/rings/integer_ring.pxd +8 -0
  513. sage/rings/integer_ring.pyx +1693 -0
  514. sage/rings/laurent_series_ring.py +931 -0
  515. sage/rings/laurent_series_ring_element.cpython-314t-aarch64-linux-musl.so +0 -0
  516. sage/rings/laurent_series_ring_element.pxd +11 -0
  517. sage/rings/laurent_series_ring_element.pyx +1927 -0
  518. sage/rings/lazy_series.py +7815 -0
  519. sage/rings/lazy_series_ring.py +4356 -0
  520. sage/rings/localization.py +1043 -0
  521. sage/rings/morphism.cpython-314t-aarch64-linux-musl.so +0 -0
  522. sage/rings/morphism.pxd +39 -0
  523. sage/rings/morphism.pyx +3299 -0
  524. sage/rings/multi_power_series_ring.py +1145 -0
  525. sage/rings/multi_power_series_ring_element.py +2184 -0
  526. sage/rings/noncommutative_ideals.cpython-314t-aarch64-linux-musl.so +0 -0
  527. sage/rings/noncommutative_ideals.pyx +423 -0
  528. sage/rings/number_field/all__sagemath_categories.py +1 -0
  529. sage/rings/number_field/number_field_base.cpython-314t-aarch64-linux-musl.so +0 -0
  530. sage/rings/number_field/number_field_base.pxd +8 -0
  531. sage/rings/number_field/number_field_base.pyx +507 -0
  532. sage/rings/number_field/number_field_element_base.cpython-314t-aarch64-linux-musl.so +0 -0
  533. sage/rings/number_field/number_field_element_base.pxd +6 -0
  534. sage/rings/number_field/number_field_element_base.pyx +36 -0
  535. sage/rings/number_field/number_field_ideal.py +3550 -0
  536. sage/rings/padics/all__sagemath_categories.py +4 -0
  537. sage/rings/padics/local_generic.py +1670 -0
  538. sage/rings/padics/local_generic_element.cpython-314t-aarch64-linux-musl.so +0 -0
  539. sage/rings/padics/local_generic_element.pxd +5 -0
  540. sage/rings/padics/local_generic_element.pyx +1017 -0
  541. sage/rings/padics/misc.py +256 -0
  542. sage/rings/padics/padic_generic.py +1911 -0
  543. sage/rings/padics/pow_computer.cpython-314t-aarch64-linux-musl.so +0 -0
  544. sage/rings/padics/pow_computer.pxd +38 -0
  545. sage/rings/padics/pow_computer.pyx +671 -0
  546. sage/rings/padics/precision_error.py +24 -0
  547. sage/rings/polynomial/all__sagemath_categories.py +25 -0
  548. sage/rings/polynomial/commutative_polynomial.cpython-314t-aarch64-linux-musl.so +0 -0
  549. sage/rings/polynomial/commutative_polynomial.pxd +6 -0
  550. sage/rings/polynomial/commutative_polynomial.pyx +24 -0
  551. sage/rings/polynomial/cyclotomic.cpython-314t-aarch64-linux-musl.so +0 -0
  552. sage/rings/polynomial/cyclotomic.pyx +404 -0
  553. sage/rings/polynomial/flatten.py +711 -0
  554. sage/rings/polynomial/ideal.py +102 -0
  555. sage/rings/polynomial/infinite_polynomial_element.py +1768 -0
  556. sage/rings/polynomial/infinite_polynomial_ring.py +1653 -0
  557. sage/rings/polynomial/laurent_polynomial.cpython-314t-aarch64-linux-musl.so +0 -0
  558. sage/rings/polynomial/laurent_polynomial.pxd +18 -0
  559. sage/rings/polynomial/laurent_polynomial.pyx +2190 -0
  560. sage/rings/polynomial/laurent_polynomial_ideal.py +590 -0
  561. sage/rings/polynomial/laurent_polynomial_ring.py +832 -0
  562. sage/rings/polynomial/laurent_polynomial_ring_base.py +708 -0
  563. sage/rings/polynomial/multi_polynomial.cpython-314t-aarch64-linux-musl.so +0 -0
  564. sage/rings/polynomial/multi_polynomial.pxd +12 -0
  565. sage/rings/polynomial/multi_polynomial.pyx +3082 -0
  566. sage/rings/polynomial/multi_polynomial_element.py +2570 -0
  567. sage/rings/polynomial/multi_polynomial_ideal.py +5771 -0
  568. sage/rings/polynomial/multi_polynomial_ring.py +947 -0
  569. sage/rings/polynomial/multi_polynomial_ring_base.cpython-314t-aarch64-linux-musl.so +0 -0
  570. sage/rings/polynomial/multi_polynomial_ring_base.pxd +15 -0
  571. sage/rings/polynomial/multi_polynomial_ring_base.pyx +1855 -0
  572. sage/rings/polynomial/multi_polynomial_sequence.py +2204 -0
  573. sage/rings/polynomial/polydict.cpython-314t-aarch64-linux-musl.so +0 -0
  574. sage/rings/polynomial/polydict.pxd +45 -0
  575. sage/rings/polynomial/polydict.pyx +2701 -0
  576. sage/rings/polynomial/polynomial_compiled.cpython-314t-aarch64-linux-musl.so +0 -0
  577. sage/rings/polynomial/polynomial_compiled.pxd +59 -0
  578. sage/rings/polynomial/polynomial_compiled.pyx +509 -0
  579. sage/rings/polynomial/polynomial_element.cpython-314t-aarch64-linux-musl.so +0 -0
  580. sage/rings/polynomial/polynomial_element.pxd +64 -0
  581. sage/rings/polynomial/polynomial_element.pyx +13255 -0
  582. sage/rings/polynomial/polynomial_element_generic.py +1637 -0
  583. sage/rings/polynomial/polynomial_fateman.py +97 -0
  584. sage/rings/polynomial/polynomial_quotient_ring.py +2465 -0
  585. sage/rings/polynomial/polynomial_quotient_ring_element.py +779 -0
  586. sage/rings/polynomial/polynomial_ring.py +3784 -0
  587. sage/rings/polynomial/polynomial_ring_constructor.py +1051 -0
  588. sage/rings/polynomial/polynomial_ring_homomorphism.cpython-314t-aarch64-linux-musl.so +0 -0
  589. sage/rings/polynomial/polynomial_ring_homomorphism.pxd +5 -0
  590. sage/rings/polynomial/polynomial_ring_homomorphism.pyx +121 -0
  591. sage/rings/polynomial/polynomial_singular_interface.py +549 -0
  592. sage/rings/polynomial/symmetric_ideal.py +989 -0
  593. sage/rings/polynomial/symmetric_reduction.cpython-314t-aarch64-linux-musl.so +0 -0
  594. sage/rings/polynomial/symmetric_reduction.pxd +8 -0
  595. sage/rings/polynomial/symmetric_reduction.pyx +669 -0
  596. sage/rings/polynomial/term_order.py +2279 -0
  597. sage/rings/polynomial/toy_buchberger.py +449 -0
  598. sage/rings/polynomial/toy_d_basis.py +387 -0
  599. sage/rings/polynomial/toy_variety.py +362 -0
  600. sage/rings/power_series_mpoly.cpython-314t-aarch64-linux-musl.so +0 -0
  601. sage/rings/power_series_mpoly.pxd +9 -0
  602. sage/rings/power_series_mpoly.pyx +161 -0
  603. sage/rings/power_series_poly.cpython-314t-aarch64-linux-musl.so +0 -0
  604. sage/rings/power_series_poly.pxd +10 -0
  605. sage/rings/power_series_poly.pyx +1317 -0
  606. sage/rings/power_series_ring.py +1441 -0
  607. sage/rings/power_series_ring_element.cpython-314t-aarch64-linux-musl.so +0 -0
  608. sage/rings/power_series_ring_element.pxd +12 -0
  609. sage/rings/power_series_ring_element.pyx +3028 -0
  610. sage/rings/puiseux_series_ring.py +487 -0
  611. sage/rings/puiseux_series_ring_element.cpython-314t-aarch64-linux-musl.so +0 -0
  612. sage/rings/puiseux_series_ring_element.pxd +7 -0
  613. sage/rings/puiseux_series_ring_element.pyx +1055 -0
  614. sage/rings/qqbar_decorators.py +167 -0
  615. sage/rings/quotient_ring.py +1598 -0
  616. sage/rings/quotient_ring_element.py +979 -0
  617. sage/rings/rational.cpython-314t-aarch64-linux-musl.so +0 -0
  618. sage/rings/rational.pxd +20 -0
  619. sage/rings/rational.pyx +4284 -0
  620. sage/rings/rational_field.py +1730 -0
  621. sage/rings/real_double.cpython-314t-aarch64-linux-musl.so +0 -0
  622. sage/rings/real_double.pxd +16 -0
  623. sage/rings/real_double.pyx +2218 -0
  624. sage/rings/real_lazy.cpython-314t-aarch64-linux-musl.so +0 -0
  625. sage/rings/real_lazy.pxd +30 -0
  626. sage/rings/real_lazy.pyx +1773 -0
  627. sage/rings/ring.cpython-314t-aarch64-linux-musl.so +0 -0
  628. sage/rings/ring.pxd +30 -0
  629. sage/rings/ring.pyx +850 -0
  630. sage/rings/semirings/all.py +3 -0
  631. sage/rings/semirings/non_negative_integer_semiring.py +107 -0
  632. sage/rings/semirings/tropical_mpolynomial.py +972 -0
  633. sage/rings/semirings/tropical_polynomial.py +997 -0
  634. sage/rings/semirings/tropical_semiring.cpython-314t-aarch64-linux-musl.so +0 -0
  635. sage/rings/semirings/tropical_semiring.pyx +676 -0
  636. sage/rings/semirings/tropical_variety.py +1701 -0
  637. sage/rings/sum_of_squares.cpython-314t-aarch64-linux-musl.so +0 -0
  638. sage/rings/sum_of_squares.pxd +3 -0
  639. sage/rings/sum_of_squares.pyx +336 -0
  640. sage/rings/tests.py +504 -0
  641. sage/schemes/affine/affine_homset.py +508 -0
  642. sage/schemes/affine/affine_morphism.py +1574 -0
  643. sage/schemes/affine/affine_point.py +460 -0
  644. sage/schemes/affine/affine_rational_point.py +308 -0
  645. sage/schemes/affine/affine_space.py +1264 -0
  646. sage/schemes/affine/affine_subscheme.py +592 -0
  647. sage/schemes/affine/all.py +25 -0
  648. sage/schemes/all__sagemath_categories.py +5 -0
  649. sage/schemes/generic/algebraic_scheme.py +2092 -0
  650. sage/schemes/generic/all.py +5 -0
  651. sage/schemes/generic/ambient_space.py +400 -0
  652. sage/schemes/generic/divisor.py +465 -0
  653. sage/schemes/generic/divisor_group.py +313 -0
  654. sage/schemes/generic/glue.py +84 -0
  655. sage/schemes/generic/homset.py +820 -0
  656. sage/schemes/generic/hypersurface.py +234 -0
  657. sage/schemes/generic/morphism.py +2107 -0
  658. sage/schemes/generic/point.py +237 -0
  659. sage/schemes/generic/scheme.py +1190 -0
  660. sage/schemes/generic/spec.py +199 -0
  661. sage/schemes/product_projective/all.py +6 -0
  662. sage/schemes/product_projective/homset.py +236 -0
  663. sage/schemes/product_projective/morphism.py +517 -0
  664. sage/schemes/product_projective/point.py +568 -0
  665. sage/schemes/product_projective/rational_point.py +550 -0
  666. sage/schemes/product_projective/space.py +1301 -0
  667. sage/schemes/product_projective/subscheme.py +466 -0
  668. sage/schemes/projective/all.py +24 -0
  669. sage/schemes/projective/proj_bdd_height.py +453 -0
  670. sage/schemes/projective/projective_homset.py +718 -0
  671. sage/schemes/projective/projective_morphism.py +2792 -0
  672. sage/schemes/projective/projective_point.py +1484 -0
  673. sage/schemes/projective/projective_rational_point.py +569 -0
  674. sage/schemes/projective/projective_space.py +2571 -0
  675. sage/schemes/projective/projective_subscheme.py +1574 -0
  676. sage/sets/all.py +17 -0
  677. sage/sets/cartesian_product.py +376 -0
  678. sage/sets/condition_set.py +525 -0
  679. sage/sets/disjoint_set.cpython-314t-aarch64-linux-musl.so +0 -0
  680. sage/sets/disjoint_set.pxd +36 -0
  681. sage/sets/disjoint_set.pyx +998 -0
  682. sage/sets/disjoint_union_enumerated_sets.py +625 -0
  683. sage/sets/family.cpython-314t-aarch64-linux-musl.so +0 -0
  684. sage/sets/family.pxd +12 -0
  685. sage/sets/family.pyx +1556 -0
  686. sage/sets/finite_enumerated_set.py +406 -0
  687. sage/sets/finite_set_map_cy.cpython-314t-aarch64-linux-musl.so +0 -0
  688. sage/sets/finite_set_map_cy.pxd +34 -0
  689. sage/sets/finite_set_map_cy.pyx +708 -0
  690. sage/sets/finite_set_maps.py +591 -0
  691. sage/sets/image_set.py +448 -0
  692. sage/sets/integer_range.py +829 -0
  693. sage/sets/non_negative_integers.py +241 -0
  694. sage/sets/positive_integers.py +93 -0
  695. sage/sets/primes.py +188 -0
  696. sage/sets/real_set.py +2760 -0
  697. sage/sets/recursively_enumerated_set.cpython-314t-aarch64-linux-musl.so +0 -0
  698. sage/sets/recursively_enumerated_set.pxd +31 -0
  699. sage/sets/recursively_enumerated_set.pyx +2082 -0
  700. sage/sets/set.py +2083 -0
  701. sage/sets/set_from_iterator.py +1021 -0
  702. sage/sets/totally_ordered_finite_set.py +329 -0
  703. sage/symbolic/all__sagemath_categories.py +1 -0
  704. sage/symbolic/function.cpython-314t-aarch64-linux-musl.so +0 -0
  705. sage/symbolic/function.pxd +29 -0
  706. sage/symbolic/function.pyx +1488 -0
  707. sage/symbolic/symbols.py +56 -0
  708. sage/tests/all__sagemath_categories.py +1 -0
  709. sage/tests/cython.cpython-314t-aarch64-linux-musl.so +0 -0
  710. sage/tests/cython.pyx +37 -0
  711. sage/tests/stl_vector.cpython-314t-aarch64-linux-musl.so +0 -0
  712. sage/tests/stl_vector.pyx +171 -0
  713. sage/typeset/all.py +6 -0
  714. sage/typeset/ascii_art.py +295 -0
  715. sage/typeset/character_art.py +789 -0
  716. sage/typeset/character_art_factory.py +572 -0
  717. sage/typeset/symbols.py +334 -0
  718. sage/typeset/unicode_art.py +183 -0
  719. sage/typeset/unicode_characters.py +101 -0
@@ -0,0 +1,2204 @@
1
+ # sage_setup: distribution = sagemath-categories
2
+ r"""
3
+ Polynomial Sequences
4
+
5
+ We call a finite list of polynomials a ``Polynomial Sequence``.
6
+
7
+ Polynomial sequences in Sage can optionally be viewed as consisting of
8
+ various parts or sub-sequences. These kind of polynomial sequences
9
+ which naturally split into parts arise naturally for example in
10
+ algebraic cryptanalysis of symmetric cryptographic primitives. The
11
+ most prominent examples of these systems are: the small scale variants
12
+ of the AES [CMR2005]_ (cf. :func:`sage.crypto.mq.sr.SR`) and Flurry/Curry [BPW2006]_. By
13
+ default, a polynomial sequence has exactly one part.
14
+
15
+ AUTHORS:
16
+
17
+ - Martin Albrecht (2007ff): initial version
18
+ - Martin Albrecht (2009): refactoring, clean-up, new functions
19
+ - Martin Albrecht (2011): refactoring, moved to sage.rings.polynomial
20
+ - Alex Raichev (2011-06): added algebraic_dependence()
21
+ - Charles Bouillaguet (2013-1): added solve()
22
+
23
+ EXAMPLES:
24
+
25
+ As an example consider a small scale variant of the AES::
26
+
27
+ sage: sr = mq.SR(2, 1, 2, 4, gf2=True, polybori=True) # needs sage.rings.polynomial.pbori
28
+ sage: sr # needs sage.rings.polynomial.pbori
29
+ SR(2,1,2,4)
30
+
31
+ We can construct a polynomial sequence for a random plaintext-ciphertext
32
+ pair and study it::
33
+
34
+ sage: set_random_seed(1)
35
+ sage: while True: # workaround (see :issue:`31891`) # needs sage.rings.polynomial.pbori
36
+ ....: try:
37
+ ....: F, s = sr.polynomial_system()
38
+ ....: break
39
+ ....: except ZeroDivisionError:
40
+ ....: pass
41
+ sage: F # needs sage.rings.polynomial.pbori
42
+ Polynomial Sequence with 112 Polynomials in 64 Variables
43
+
44
+ sage: r2 = F.part(2); r2 # needs sage.rings.polynomial.pbori
45
+ (w200 + k100 + x100 + x102 + x103,
46
+ w201 + k101 + x100 + x101 + x103 + 1,
47
+ w202 + k102 + x100 + x101 + x102 + 1,
48
+ w203 + k103 + x101 + x102 + x103,
49
+ w210 + k110 + x110 + x112 + x113,
50
+ w211 + k111 + x110 + x111 + x113 + 1,
51
+ w212 + k112 + x110 + x111 + x112 + 1,
52
+ w213 + k113 + x111 + x112 + x113,
53
+ x100*w100 + x100*w103 + x101*w102 + x102*w101 + x103*w100,
54
+ x100*w100 + x100*w101 + x101*w100 + x101*w103 + x102*w102 + x103*w101,
55
+ x100*w101 + x100*w102 + x101*w100 + x101*w101 + x102*w100 + x102*w103 + x103*w102,
56
+ x100*w100 + x100*w102 + x100*w103 + x101*w100 + x101*w101 + x102*w102 + x103*w100 + x100,
57
+ x100*w101 + x100*w103 + x101*w101 + x101*w102 + x102*w100 + x102*w103 + x103*w101 + x101,
58
+ x100*w100 + x100*w102 + x101*w100 + x101*w102 + x101*w103 + x102*w100 + x102*w101 + x103*w102 + x102,
59
+ x100*w101 + x100*w102 + x101*w100 + x101*w103 + x102*w101 + x103*w103 + x103,
60
+ x100*w100 + x100*w101 + x100*w103 + x101*w101 + x102*w100 + x102*w102 + x103*w100 + w100,
61
+ x100*w102 + x101*w100 + x101*w101 + x101*w103 + x102*w101 + x103*w100 + x103*w102 + w101,
62
+ x100*w100 + x100*w101 + x100*w102 + x101*w102 + x102*w100 + x102*w101 + x102*w103 + x103*w101 + w102,
63
+ x100*w101 + x101*w100 + x101*w102 + x102*w100 + x103*w101 + x103*w103 + w103,
64
+ x100*w102 + x101*w101 + x102*w100 + x103*w103 + 1,
65
+ x110*w110 + x110*w113 + x111*w112 + x112*w111 + x113*w110,
66
+ x110*w110 + x110*w111 + x111*w110 + x111*w113 + x112*w112 + x113*w111,
67
+ x110*w111 + x110*w112 + x111*w110 + x111*w111 + x112*w110 + x112*w113 + x113*w112,
68
+ x110*w110 + x110*w112 + x110*w113 + x111*w110 + x111*w111 + x112*w112 + x113*w110 + x110,
69
+ x110*w111 + x110*w113 + x111*w111 + x111*w112 + x112*w110 + x112*w113 + x113*w111 + x111,
70
+ x110*w110 + x110*w112 + x111*w110 + x111*w112 + x111*w113 + x112*w110 + x112*w111 + x113*w112 + x112,
71
+ x110*w111 + x110*w112 + x111*w110 + x111*w113 + x112*w111 + x113*w113 + x113,
72
+ x110*w110 + x110*w111 + x110*w113 + x111*w111 + x112*w110 + x112*w112 + x113*w110 + w110,
73
+ x110*w112 + x111*w110 + x111*w111 + x111*w113 + x112*w111 + x113*w110 + x113*w112 + w111,
74
+ x110*w110 + x110*w111 + x110*w112 + x111*w112 + x112*w110 + x112*w111 + x112*w113 + x113*w111 + w112,
75
+ x110*w111 + x111*w110 + x111*w112 + x112*w110 + x113*w111 + x113*w113 + w113,
76
+ x110*w112 + x111*w111 + x112*w110 + x113*w113 + 1)
77
+
78
+ We separate the system in independent subsystems::
79
+
80
+ sage: C = Sequence(r2).connected_components(); C # needs sage.rings.polynomial.pbori
81
+ [[w200 + k100 + x100 + x102 + x103,
82
+ w201 + k101 + x100 + x101 + x103 + 1,
83
+ w202 + k102 + x100 + x101 + x102 + 1,
84
+ w203 + k103 + x101 + x102 + x103,
85
+ x100*w100 + x100*w103 + x101*w102 + x102*w101 + x103*w100,
86
+ x100*w100 + x100*w101 + x101*w100 + x101*w103 + x102*w102 + x103*w101,
87
+ x100*w101 + x100*w102 + x101*w100 + x101*w101 + x102*w100 + x102*w103 + x103*w102,
88
+ x100*w100 + x100*w102 + x100*w103 + x101*w100 + x101*w101 + x102*w102 + x103*w100 + x100,
89
+ x100*w101 + x100*w103 + x101*w101 + x101*w102 + x102*w100 + x102*w103 + x103*w101 + x101,
90
+ x100*w100 + x100*w102 + x101*w100 + x101*w102 + x101*w103 + x102*w100 + x102*w101 + x103*w102 + x102,
91
+ x100*w101 + x100*w102 + x101*w100 + x101*w103 + x102*w101 + x103*w103 + x103,
92
+ x100*w100 + x100*w101 + x100*w103 + x101*w101 + x102*w100 + x102*w102 + x103*w100 + w100,
93
+ x100*w102 + x101*w100 + x101*w101 + x101*w103 + x102*w101 + x103*w100 + x103*w102 + w101,
94
+ x100*w100 + x100*w101 + x100*w102 + x101*w102 + x102*w100 + x102*w101 + x102*w103 + x103*w101 + w102,
95
+ x100*w101 + x101*w100 + x101*w102 + x102*w100 + x103*w101 + x103*w103 + w103,
96
+ x100*w102 + x101*w101 + x102*w100 + x103*w103 + 1],
97
+ [w210 + k110 + x110 + x112 + x113,
98
+ w211 + k111 + x110 + x111 + x113 + 1,
99
+ w212 + k112 + x110 + x111 + x112 + 1,
100
+ w213 + k113 + x111 + x112 + x113,
101
+ x110*w110 + x110*w113 + x111*w112 + x112*w111 + x113*w110,
102
+ x110*w110 + x110*w111 + x111*w110 + x111*w113 + x112*w112 + x113*w111,
103
+ x110*w111 + x110*w112 + x111*w110 + x111*w111 + x112*w110 + x112*w113 + x113*w112,
104
+ x110*w110 + x110*w112 + x110*w113 + x111*w110 + x111*w111 + x112*w112 + x113*w110 + x110,
105
+ x110*w111 + x110*w113 + x111*w111 + x111*w112 + x112*w110 + x112*w113 + x113*w111 + x111,
106
+ x110*w110 + x110*w112 + x111*w110 + x111*w112 + x111*w113 + x112*w110 + x112*w111 + x113*w112 + x112,
107
+ x110*w111 + x110*w112 + x111*w110 + x111*w113 + x112*w111 + x113*w113 + x113,
108
+ x110*w110 + x110*w111 + x110*w113 + x111*w111 + x112*w110 + x112*w112 + x113*w110 + w110,
109
+ x110*w112 + x111*w110 + x111*w111 + x111*w113 + x112*w111 + x113*w110 + x113*w112 + w111,
110
+ x110*w110 + x110*w111 + x110*w112 + x111*w112 + x112*w110 + x112*w111 + x112*w113 + x113*w111 + w112,
111
+ x110*w111 + x111*w110 + x111*w112 + x112*w110 + x113*w111 + x113*w113 + w113,
112
+ x110*w112 + x111*w111 + x112*w110 + x113*w113 + 1]]
113
+ sage: C[0].groebner_basis() # needs sage.rings.polynomial.pbori
114
+ Polynomial Sequence with 30 Polynomials in 16 Variables
115
+
116
+ and compute the coefficient matrix::
117
+
118
+ sage: A,v = Sequence(r2).coefficients_monomials() # needs sage.rings.polynomial.pbori
119
+ sage: A.rank() # needs sage.rings.polynomial.pbori
120
+ 32
121
+
122
+ Using these building blocks we can implement a simple XL algorithm
123
+ easily::
124
+
125
+ sage: sr = mq.SR(1,1,1,4, gf2=True, polybori=True, order='lex') # needs sage.rings.polynomial.pbori
126
+ sage: while True: # workaround (see :issue:`31891`) # needs sage.rings.polynomial.pbori
127
+ ....: try:
128
+ ....: F, s = sr.polynomial_system()
129
+ ....: break
130
+ ....: except ZeroDivisionError:
131
+ ....: pass
132
+
133
+ sage: # needs sage.rings.polynomial.pbori
134
+ sage: monomials = [a*b for a in F.variables() for b in F.variables() if a < b]
135
+ sage: len(monomials)
136
+ 190
137
+ sage: F2 = Sequence(map(mul, cartesian_product_iterator((monomials, F))))
138
+ sage: A, v = F2.coefficients_monomials(sparse=False)
139
+ sage: A.echelonize()
140
+ sage: A
141
+ 6840 x 4474 dense matrix over Finite Field of size 2...
142
+ sage: A.rank()
143
+ 4056
144
+ sage: A[4055] * v
145
+ k001*k003
146
+
147
+ TESTS::
148
+
149
+ sage: P.<x,y> = PolynomialRing(QQ)
150
+ sage: I = [[x^2 + y^2], [x^2 - y^2]]
151
+ sage: F = Sequence(I, P)
152
+ sage: loads(dumps(F)) == F
153
+ True
154
+
155
+ .. NOTE::
156
+
157
+ In many other computer algebra systems (cf. Singular) this class
158
+ would be called ``Ideal`` but an ideal is a very distinct object
159
+ from its generators and thus this is not an ideal in Sage.
160
+
161
+ Classes
162
+ -------
163
+ """
164
+
165
+ from sage.misc.persist import register_unpickle_override
166
+ from sage.misc.cachefunc import cached_method
167
+ from sage.misc.converting_dict import KeyConvertingDict
168
+ from sage.rings.finite_rings.finite_field_base import FiniteField
169
+ from sage.rings.finite_rings.finite_field_constructor import FiniteField as GF
170
+ from sage.rings.infinity import Infinity
171
+ from sage.rings.polynomial.multi_polynomial_ideal import MPolynomialIdeal
172
+ from sage.rings.polynomial.multi_polynomial_ring import MPolynomialRing_base
173
+ from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing
174
+ from sage.rings.polynomial.infinite_polynomial_ring import InfinitePolynomialRing_sparse
175
+ from sage.rings.quotient_ring import QuotientRing_nc
176
+ from sage.structure.sequence import Sequence_generic
177
+
178
+ try:
179
+ from sage.interfaces.singular import singular, singular_gb_standard_options
180
+ from sage.libs.singular.standard_options import \
181
+ libsingular_gb_standard_options
182
+ except ImportError:
183
+ singular = None
184
+ def singular_gb_standard_options(func):
185
+ return func
186
+ libsingular_gb_standard_options = singular_gb_standard_options
187
+
188
+
189
+ def is_PolynomialSequence(F):
190
+ """
191
+ Return ``True`` if ``F`` is a ``PolynomialSequence``.
192
+
193
+ INPUT:
194
+
195
+ - ``F`` -- anything
196
+
197
+ EXAMPLES::
198
+
199
+ sage: P.<x,y> = PolynomialRing(QQ)
200
+ sage: I = [[x^2 + y^2], [x^2 - y^2]]
201
+ sage: F = Sequence(I, P); F
202
+ [x^2 + y^2, x^2 - y^2]
203
+
204
+ sage: from sage.rings.polynomial.multi_polynomial_sequence import PolynomialSequence_generic
205
+ sage: isinstance(F, PolynomialSequence_generic)
206
+ True
207
+ """
208
+ from sage.misc.superseded import deprecation
209
+ deprecation(38266,
210
+ "The function is_PolynomialSequence is deprecated; "
211
+ "use 'isinstance(..., PolynomialSequence_generic)' instead.")
212
+ return isinstance(F, PolynomialSequence_generic)
213
+
214
+
215
+ def PolynomialSequence(arg1, arg2=None, immutable=False, cr=False, cr_str=None):
216
+ """
217
+ Construct a new polynomial sequence object.
218
+
219
+ INPUT:
220
+
221
+ - ``arg1`` -- a multivariate polynomial ring, an ideal or a matrix
222
+
223
+ - ``arg2`` -- an iterable object of parts or polynomials
224
+ (default: ``None``)
225
+
226
+ - ``immutable`` -- if ``True`` the sequence is immutable (default: ``False``)
227
+
228
+ - ``cr``, ``cr_str`` -- see :func:`~sage.structure.sequence.Sequence`
229
+
230
+ EXAMPLES::
231
+
232
+ sage: P.<a,b,c,d> = PolynomialRing(GF(127), 4)
233
+ sage: I = sage.rings.ideal.Katsura(P) # needs sage.libs.singular
234
+
235
+ If a list of tuples is provided, those form the parts::
236
+
237
+ sage: F = Sequence([I.gens(),I.gens()], I.ring()); F # indirect doctest # needs sage.libs.singular
238
+ [a + 2*b + 2*c + 2*d - 1,
239
+ a^2 + 2*b^2 + 2*c^2 + 2*d^2 - a,
240
+ 2*a*b + 2*b*c + 2*c*d - b,
241
+ b^2 + 2*a*c + 2*b*d - c,
242
+ a + 2*b + 2*c + 2*d - 1,
243
+ a^2 + 2*b^2 + 2*c^2 + 2*d^2 - a,
244
+ 2*a*b + 2*b*c + 2*c*d - b,
245
+ b^2 + 2*a*c + 2*b*d - c]
246
+ sage: F.nparts() # needs sage.libs.singular
247
+ 2
248
+
249
+ If an ideal is provided, the generators are used::
250
+
251
+ sage: Sequence(I) # needs sage.libs.singular
252
+ [a + 2*b + 2*c + 2*d - 1,
253
+ a^2 + 2*b^2 + 2*c^2 + 2*d^2 - a,
254
+ 2*a*b + 2*b*c + 2*c*d - b,
255
+ b^2 + 2*a*c + 2*b*d - c]
256
+
257
+ If a list of polynomials is provided, the system has only one part::
258
+
259
+ sage: F = Sequence(I.gens(), I.ring()); F # needs sage.libs.singular
260
+ [a + 2*b + 2*c + 2*d - 1,
261
+ a^2 + 2*b^2 + 2*c^2 + 2*d^2 - a,
262
+ 2*a*b + 2*b*c + 2*c*d - b,
263
+ b^2 + 2*a*c + 2*b*d - c]
264
+ sage: F.nparts() # needs sage.libs.singular
265
+ 1
266
+
267
+ We test that the ring is inferred correctly::
268
+
269
+ sage: P.<x,y,z> = GF(2)[]
270
+ sage: from sage.rings.polynomial.multi_polynomial_sequence import PolynomialSequence
271
+ sage: PolynomialSequence([1,x,y]).ring()
272
+ Multivariate Polynomial Ring in x, y, z over Finite Field of size 2
273
+
274
+ sage: PolynomialSequence([[1,x,y], [0]]).ring()
275
+ Multivariate Polynomial Ring in x, y, z over Finite Field of size 2
276
+
277
+ TESTS:
278
+
279
+ A ``PolynomialSequence`` can exist with elements in an infinite field of
280
+ characteristic 2 (see :issue:`19452`)::
281
+
282
+ sage: from sage.rings.polynomial.multi_polynomial_sequence import PolynomialSequence
283
+ sage: F = GF(2)
284
+ sage: L.<t> = PowerSeriesRing(F,'t')
285
+ sage: R.<x,y> = PolynomialRing(L,'x,y')
286
+ sage: PolynomialSequence([0], R)
287
+ [0]
288
+
289
+ A ``PolynomialSequence`` can be created from an iterator (see :issue:`25989`)::
290
+
291
+ sage: R.<x,y,z> = QQ[]
292
+ sage: PolynomialSequence(iter(R.gens()))
293
+ [x, y, z]
294
+ sage: PolynomialSequence(iter(R.gens()), R)
295
+ [x, y, z]
296
+ sage: PolynomialSequence(iter([(x,y), (z,)]), R)
297
+ [x, y, z]
298
+
299
+ A ``PolynomialSequence`` can be created from elements of an
300
+ ``InfinitePolynomialRing``::
301
+
302
+ sage: R.<a> = InfinitePolynomialRing(QQ)
303
+ sage: s = PolynomialSequence([a[i]-a[i+1] for i in range(3)])
304
+ sage: s
305
+ [-a_1 + a_0, -a_2 + a_1, -a_3 + a_2]
306
+ sage: s.coefficients_monomials() # needs sage.modules
307
+ (
308
+ [ 0 0 -1 1]
309
+ [ 0 -1 1 0]
310
+ [-1 1 0 0], (a_3, a_2, a_1, a_0)
311
+ )
312
+ """
313
+ from sage.structure.element import Matrix
314
+ try:
315
+ from sage.rings.polynomial.pbori.pbori import BooleanMonomialMonoid
316
+ except ImportError:
317
+ BooleanMonomialMonoid = ()
318
+
319
+ def is_ring(r):
320
+ return (isinstance(r, (MPolynomialRing_base,
321
+ BooleanMonomialMonoid,
322
+ InfinitePolynomialRing_sparse))
323
+ or (isinstance(r, QuotientRing_nc)
324
+ and isinstance(r.cover_ring(), MPolynomialRing_base)))
325
+
326
+ if is_ring(arg1):
327
+ ring, gens = arg1, arg2
328
+
329
+ elif is_ring(arg2):
330
+ ring, gens = arg2, arg1
331
+
332
+ elif isinstance(arg1, Matrix):
333
+ ring, gens = arg1.base_ring(), arg1.list()
334
+
335
+ elif isinstance(arg1, MPolynomialIdeal):
336
+ ring, gens = arg1.ring(), arg1.gens()
337
+ else:
338
+ gens = list(arg1)
339
+
340
+ if arg2:
341
+ ring = arg2
342
+ if not is_ring(ring):
343
+ raise TypeError("Ring '%s' not supported." % ring)
344
+ else:
345
+ try:
346
+ e = next(iter(gens))
347
+ except StopIteration:
348
+ raise ValueError("Cannot determine ring from provided information.")
349
+
350
+ import sage.structure.element as coerce
351
+
352
+ el = 0
353
+
354
+ for f in gens:
355
+ try:
356
+ el, _ = coerce.canonical_coercion(el, f)
357
+ except TypeError:
358
+ el = 0
359
+ for part in gens:
360
+ for f in part:
361
+ el, _ = coerce.canonical_coercion(el, f)
362
+
363
+ if is_ring(el.parent()):
364
+ ring = el.parent()
365
+ else:
366
+ raise TypeError("Cannot determine ring.")
367
+
368
+ try:
369
+ gens = iter(gens)
370
+ e = next(gens)
371
+ # fast path for known collection types
372
+ if isinstance(e, (tuple, list, Sequence_generic, PolynomialSequence_generic)):
373
+ nested = True
374
+ else:
375
+ nested = False
376
+ try:
377
+ e2 = ring(e)
378
+ except TypeError:
379
+ nested = True
380
+ from itertools import chain
381
+ if nested:
382
+ parts = tuple(tuple(ring(f) for f in part) for part in chain([e], gens))
383
+ else:
384
+ parts = tuple(chain([e2], map(ring, gens))),
385
+ except StopIteration:
386
+ parts = ((),)
387
+
388
+ K = ring.base_ring()
389
+
390
+ # make sure we use the polynomial ring as ring not the monoid
391
+ ring = (ring(1) + ring(1)).parent()
392
+
393
+ if not isinstance(K, FiniteField) or K.characteristic() != 2:
394
+ return PolynomialSequence_generic(parts, ring, immutable=immutable, cr=cr, cr_str=cr_str)
395
+ elif K.degree() == 1:
396
+ return PolynomialSequence_gf2(parts, ring, immutable=immutable, cr=cr, cr_str=cr_str)
397
+ elif K.degree() > 1:
398
+ return PolynomialSequence_gf2e(parts, ring, immutable=immutable, cr=cr, cr_str=cr_str)
399
+
400
+
401
+ class PolynomialSequence_generic(Sequence_generic):
402
+ def __init__(self, parts, ring, immutable=False, cr=False, cr_str=None):
403
+ """
404
+ Construct a new system of multivariate polynomials.
405
+
406
+ INPUT:
407
+
408
+ - ``parts`` -- a list of lists with polynomials
409
+
410
+ - ``ring`` -- a multivariate polynomial ring
411
+
412
+ - ``immutable`` -- if ``True`` the sequence is immutable (default: ``False``)
413
+
414
+ - ``cr``, ``cr_str`` -- see :func:`~sage.structure.sequence.Sequence`
415
+
416
+ EXAMPLES::
417
+
418
+ sage: P.<a,b,c,d> = PolynomialRing(GF(127), 4)
419
+ sage: I = sage.rings.ideal.Katsura(P) # needs sage.libs.singular
420
+
421
+ sage: Sequence([I.gens()], I.ring()) # indirect doctest # needs sage.libs.singular
422
+ [a + 2*b + 2*c + 2*d - 1, a^2 + 2*b^2 + 2*c^2 + 2*d^2 - a,
423
+ 2*a*b + 2*b*c + 2*c*d - b, b^2 + 2*a*c + 2*b*d - c]
424
+
425
+ If an ideal is provided, the generators are used.::
426
+
427
+ sage: Sequence(I) # needs sage.libs.singular
428
+ [a + 2*b + 2*c + 2*d - 1, a^2 + 2*b^2 + 2*c^2 + 2*d^2 - a,
429
+ 2*a*b + 2*b*c + 2*c*d - b, b^2 + 2*a*c + 2*b*d - c]
430
+
431
+ If a list of polynomials is provided, the system has only one
432
+ part.::
433
+
434
+ sage: Sequence(I.gens(), I.ring()) # needs sage.libs.singular
435
+ [a + 2*b + 2*c + 2*d - 1, a^2 + 2*b^2 + 2*c^2 + 2*d^2 - a,
436
+ 2*a*b + 2*b*c + 2*c*d - b, b^2 + 2*a*c + 2*b*d - c]
437
+ """
438
+
439
+ Sequence_generic.__init__(self, sum(parts, tuple()), ring, check=False, immutable=immutable,
440
+ cr=cr, cr_str=cr_str, use_sage_types=True)
441
+ self._ring = ring
442
+ self._parts = parts
443
+
444
+ def __copy__(self):
445
+ """
446
+ Return a copy of this system.
447
+
448
+ EXAMPLES::
449
+
450
+ sage: # needs sage.rings.polynomial.pbori
451
+ sage: sr = mq.SR(allow_zero_inversions=True)
452
+ sage: F,s = sr.polynomial_system()
453
+ sage: copy(F) # indirect doctest
454
+ Polynomial Sequence with 40 Polynomials in 20 Variables
455
+ sage: type(F) == type(copy(F))
456
+ True
457
+ """
458
+ return self.__class__(self._parts, self._ring, immutable=self.is_immutable())
459
+
460
+ def ring(self):
461
+ """
462
+ Return the polynomial ring all elements live in.
463
+
464
+ EXAMPLES::
465
+
466
+ sage: sr = mq.SR(allow_zero_inversions=True, gf2=True, order='block') # needs sage.rings.polynomial.pbori
467
+ sage: F, s = sr.polynomial_system() # needs sage.rings.polynomial.pbori
468
+ sage: print(F.ring().repr_long()) # needs sage.rings.polynomial.pbori
469
+ Polynomial Ring
470
+ Base Ring : Finite Field of size 2
471
+ Size : 20 Variables
472
+ Block 0 : Ordering : deglex
473
+ Names : k100, k101, k102, k103, x100, x101, x102, x103, w100, w101, w102, w103, s000, s001, s002, s003
474
+ Block 1 : Ordering : deglex
475
+ Names : k000, k001, k002, k003
476
+ """
477
+ return self._ring
478
+
479
+ universe = ring
480
+
481
+ def nparts(self):
482
+ """
483
+ Return number of parts of this system.
484
+
485
+ EXAMPLES::
486
+
487
+ sage: sr = mq.SR(allow_zero_inversions=True) # needs sage.rings.polynomial.pbori
488
+ sage: F, s = sr.polynomial_system() # needs sage.rings.polynomial.pbori
489
+ sage: F.nparts() # needs sage.rings.polynomial.pbori
490
+ 4
491
+ """
492
+ return len(self._parts)
493
+
494
+ def parts(self):
495
+ """
496
+ Return a tuple of parts of this system.
497
+
498
+ EXAMPLES::
499
+
500
+ sage: # needs sage.rings.polynomial.pbori
501
+ sage: sr = mq.SR(allow_zero_inversions=True)
502
+ sage: F, s = sr.polynomial_system()
503
+ sage: l = F.parts()
504
+ sage: len(l)
505
+ 4
506
+ """
507
+ return tuple(self._parts)
508
+
509
+ def part(self, i):
510
+ """
511
+ Return ``i``-th part of this system.
512
+
513
+ EXAMPLES::
514
+
515
+ sage: # needs sage.rings.polynomial.pbori
516
+ sage: sr = mq.SR(allow_zero_inversions=True)
517
+ sage: F, s = sr.polynomial_system()
518
+ sage: R0 = F.part(1)
519
+ sage: R0
520
+ (k000^2 + k001, k001^2 + k002, k002^2 + k003, k003^2 + k000)
521
+ """
522
+ return self._parts[i]
523
+
524
+ def ideal(self):
525
+ """
526
+ Return ideal spanned by the elements of this system.
527
+
528
+ EXAMPLES::
529
+
530
+ sage: # needs sage.rings.polynomial.pbori
531
+ sage: sr = mq.SR(allow_zero_inversions=True)
532
+ sage: F, s = sr.polynomial_system()
533
+ sage: P = F.ring()
534
+ sage: I = F.ideal()
535
+ sage: J = I.elimination_ideal(P.gens()[4:-4]) # needs sage.libs.singular
536
+ sage: J <= I # needs sage.libs.singular
537
+ True
538
+ sage: set(J.gens().variables()).issubset(P.gens()[:4] + P.gens()[-4:]) # needs sage.libs.singular
539
+ True
540
+ """
541
+ return self._ring.ideal(tuple(self))
542
+
543
+ def groebner_basis(self, *args, **kwargs):
544
+ """
545
+ Compute and return a Groebner basis for the ideal spanned by
546
+ the polynomials in this system.
547
+
548
+ INPUT:
549
+
550
+ - ``args`` -- list of arguments passed to
551
+ ``MPolynomialIdeal.groebner_basis`` call
552
+
553
+ - ``kwargs`` -- dictionary of arguments passed to
554
+ ``MPolynomialIdeal.groebner_basis`` call
555
+
556
+ EXAMPLES::
557
+
558
+ sage: # needs sage.rings.polynomial.pbori
559
+ sage: sr = mq.SR(allow_zero_inversions=True)
560
+ sage: F, s = sr.polynomial_system()
561
+ sage: gb = F.groebner_basis() # needs sage.libs.singular
562
+ sage: Ideal(gb).basis_is_groebner() # needs sage.libs.singular
563
+ True
564
+
565
+ TESTS:
566
+
567
+ Check that this method also works for boolean polynomials
568
+ (:issue:`10680`)::
569
+
570
+ sage: # needs sage.rings.polynomial.pbori
571
+ sage: B.<a,b,c,d> = BooleanPolynomialRing()
572
+ sage: F0 = Sequence(map(lambda f: f.lm(), [a,b,c,d]))
573
+ sage: F0.groebner_basis()
574
+ [a, b, c, d]
575
+ sage: F1 = Sequence([a,b,c*d,d^2])
576
+ sage: F1.groebner_basis()
577
+ [a, b, d]
578
+ """
579
+ return self.ideal().groebner_basis(*args, **kwargs)
580
+
581
+ def monomials(self):
582
+ """
583
+ Return an unordered tuple of monomials in this polynomial system.
584
+
585
+ EXAMPLES::
586
+
587
+ sage: sr = mq.SR(allow_zero_inversions=True) # needs sage.rings.polynomial.pbori
588
+ sage: F,s = sr.polynomial_system() # needs sage.rings.polynomial.pbori
589
+ sage: len(F.monomials()) # needs sage.rings.polynomial.pbori
590
+ 49
591
+ """
592
+ M = set()
593
+ for f in self:
594
+ for m in f.monomials():
595
+ M.add(m)
596
+ return tuple(M)
597
+
598
+ def nmonomials(self):
599
+ """
600
+ Return the number of monomials present in this system.
601
+
602
+ EXAMPLES::
603
+
604
+ sage: sr = mq.SR(allow_zero_inversions=True) # needs sage.rings.polynomial.pbori
605
+ sage: F,s = sr.polynomial_system() # needs sage.rings.polynomial.pbori
606
+ sage: F.nmonomials() # needs sage.rings.polynomial.pbori
607
+ 49
608
+ """
609
+ return len(self.monomials())
610
+
611
+ def variables(self):
612
+ """
613
+ Return all variables present in this system. This tuple may or
614
+ may not be equal to the generators of the ring of this system.
615
+
616
+ EXAMPLES::
617
+
618
+ sage: sr = mq.SR(allow_zero_inversions=True) # needs sage.rings.polynomial.pbori
619
+ sage: F,s = sr.polynomial_system() # needs sage.rings.polynomial.pbori
620
+ sage: F.variables()[:10] # needs sage.rings.polynomial.pbori
621
+ (k003, k002, k001, k000, s003, s002, s001, s000, w103, w102)
622
+ """
623
+ V = set()
624
+ for f in self:
625
+ for v in f.variables():
626
+ V.add(v)
627
+ return tuple(sorted(V))
628
+
629
+ def nvariables(self):
630
+ """
631
+ Return number of variables present in this system.
632
+
633
+ EXAMPLES::
634
+
635
+ sage: sr = mq.SR(allow_zero_inversions=True) # needs sage.rings.polynomial.pbori
636
+ sage: F,s = sr.polynomial_system() # needs sage.rings.polynomial.pbori
637
+ sage: F.nvariables() # needs sage.rings.polynomial.pbori
638
+ 20
639
+ """
640
+ return len(self.variables())
641
+
642
+ def algebraic_dependence(self):
643
+ r"""
644
+ Return the ideal of annihilating polynomials for the
645
+ polynomials in ``self``, if those polynomials are algebraically
646
+ dependent.
647
+ Otherwise, return the zero ideal.
648
+
649
+ OUTPUT:
650
+
651
+ If the polynomials `f_1,\ldots,f_r` in ``self`` are algebraically
652
+ dependent, then the output is the ideal
653
+ `\{F \in K[T_1,\ldots,T_r] : F(f_1,\ldots,f_r) = 0\}` of
654
+ annihilating polynomials of `f_1,\ldots,f_r`.
655
+ Here `K` is the coefficient ring of polynomial ring of `f_1,\ldots,f_r`
656
+ and `T_1,\ldots,T_r` are new indeterminates.
657
+ If `f_1,\ldots,f_r` are algebraically independent, then the output
658
+ is the zero ideal in `K[T_1,\ldots,T_r]`.
659
+
660
+ EXAMPLES::
661
+
662
+ sage: # needs sage.libs.singular
663
+ sage: R.<x,y> = PolynomialRing(QQ)
664
+ sage: S = Sequence([x, x*y])
665
+ sage: I = S.algebraic_dependence(); I
666
+ Ideal (0) of Multivariate Polynomial Ring in T0, T1 over Rational Field
667
+
668
+ ::
669
+
670
+ sage: # needs sage.libs.singular
671
+ sage: R.<x,y> = PolynomialRing(QQ)
672
+ sage: S = Sequence([x, (x^2 + y^2 - 1)^2, x*y - 2])
673
+ sage: I = S.algebraic_dependence(); I
674
+ Ideal (16 + 32*T2 - 8*T0^2 + 24*T2^2 - 8*T0^2*T2 + 8*T2^3 + 9*T0^4 - 2*T0^2*T2^2
675
+ + T2^4 - T0^4*T1 + 8*T0^4*T2 - 2*T0^6 + 2*T0^4*T2^2 + T0^8)
676
+ of Multivariate Polynomial Ring in T0, T1, T2 over Rational Field
677
+ sage: [F(S) for F in I.gens()]
678
+ [0]
679
+
680
+ ::
681
+
682
+ sage: # needs sage.libs.singular
683
+ sage: R.<x,y> = PolynomialRing(GF(7))
684
+ sage: S = Sequence([x, (x^2 + y^2 - 1)^2, x*y - 2])
685
+ sage: I = S.algebraic_dependence(); I
686
+ Ideal (2 - 3*T2 - T0^2 + 3*T2^2 - T0^2*T2 + T2^3 + 2*T0^4 - 2*T0^2*T2^2
687
+ + T2^4 - T0^4*T1 + T0^4*T2 - 2*T0^6 + 2*T0^4*T2^2 + T0^8)
688
+ of Multivariate Polynomial Ring in T0, T1, T2 over Finite Field of size 7
689
+ sage: [F(S) for F in I.gens()]
690
+ [0]
691
+
692
+ .. NOTE::
693
+
694
+ This function's code also works for sequences of polynomials from a
695
+ univariate polynomial ring, but i don't know where in the Sage codebase
696
+ to put it to use it to that effect.
697
+
698
+ AUTHORS:
699
+
700
+ - Alex Raichev (2011-06-22)
701
+ """
702
+ R = self.ring()
703
+ K = R.base_ring()
704
+ Xs = list(R.gens())
705
+ r = len(self)
706
+ d = len(Xs)
707
+
708
+ # Expand R by r new variables.
709
+ T = 'T'
710
+ while T in [str(x) for x in Xs]:
711
+ T = T + 'T'
712
+ Ts = [T + str(j) for j in range(r)]
713
+ RR = PolynomialRing(K, d + r, tuple(Xs + Ts))
714
+ Vs = list(RR.gens())
715
+ Xs = Vs[0:d]
716
+ Ts = Vs[d:]
717
+
718
+ J = RR.ideal([Ts[j] - RR(self[j]) for j in range(r)])
719
+ JJ = J.elimination_ideal(Xs)
720
+ # By the elimination theorem, JJ is the kernel of the ring morphism
721
+ # `phi:K[\bar T] \to K[\bar X]` that fixes `K` and sends each
722
+ # `T_i` to `f_i`.
723
+ # So JJ is the ideal of annihilating polynomials of `f_1,\ldots,f_r`,
724
+ # which is the zero ideal in case `f_1,\ldots,f_r` are algebraically
725
+ # independent.
726
+
727
+ # Coerce JJ into `K[T_1,\ldots,T_r]`.
728
+ # Choosing the negdeglex order simply because i find it useful in my work.
729
+ RRR = PolynomialRing(K, r, tuple(Ts), order='negdeglex')
730
+ return RRR.ideal(JJ.gens())
731
+
732
+ def coefficients_monomials(self, order=None, sparse=True):
733
+ """
734
+ Return the matrix of coefficients ``A`` and
735
+ the matching vector of monomials ``v``, such that ``A*v == vector(self)``.
736
+
737
+ Thus value of ``A[i,j]`` corresponds the coefficient of the
738
+ monomial ``v[j]`` in the ``i``-th polynomial in this system.
739
+
740
+ Monomials are ordered w.r.t. the term ordering of ``order``
741
+ if given; otherwise, they are ordered w.r.t. ``self.ring()``
742
+ in reverse order, i.e., such that the smallest entry comes last.
743
+
744
+ INPUT:
745
+
746
+ - ``sparse`` -- construct a sparse matrix (default: ``True``)
747
+ - ``order`` -- list or tuple specifying the order of monomials (default: ``None``)
748
+
749
+ EXAMPLES::
750
+
751
+ sage: # needs sage.libs.singular
752
+ sage: P.<a,b,c,d> = PolynomialRing(GF(127), 4)
753
+ sage: I = sage.rings.ideal.Katsura(P)
754
+ sage: I.gens()
755
+ [a + 2*b + 2*c + 2*d - 1,
756
+ a^2 + 2*b^2 + 2*c^2 + 2*d^2 - a,
757
+ 2*a*b + 2*b*c + 2*c*d - b,
758
+ b^2 + 2*a*c + 2*b*d - c]
759
+ sage: F = Sequence(I)
760
+ sage: A,v = F.coefficients_monomials()
761
+ sage: A
762
+ [ 0 0 0 0 0 0 0 0 0 1 2 2 2 126]
763
+ [ 1 0 2 0 0 2 0 0 2 126 0 0 0 0]
764
+ [ 0 2 0 0 2 0 0 2 0 0 126 0 0 0]
765
+ [ 0 0 1 2 0 0 2 0 0 0 0 126 0 0]
766
+ sage: v
767
+ (a^2, a*b, b^2, a*c, b*c, c^2, b*d, c*d, d^2, a, b, c, d, 1)
768
+ sage: A*v
769
+ (a + 2*b + 2*c + 2*d - 1, a^2 + 2*b^2 + 2*c^2 + 2*d^2 - a,
770
+ 2*a*b + 2*b*c + 2*c*d - b, b^2 + 2*a*c + 2*b*d - c)
771
+ """
772
+ from sage.modules.free_module_element import vector
773
+ from sage.matrix.constructor import matrix
774
+
775
+ if order is None:
776
+ v = sorted(self.monomials(), reverse=True)
777
+ else:
778
+ if isinstance(order, (list, tuple)):
779
+ v = order
780
+ else:
781
+ raise ValueError("order argument can only accept list or tuple")
782
+
783
+ y = dict(zip(v, range(len(v)))) # construct dictionary for fast lookups
784
+ A = matrix(self.ring().base_ring(), len(self), len(v), sparse=sparse)
785
+ for x, poly in enumerate(self):
786
+ for c, m in poly:
787
+ try:
788
+ A[x, y[m]] = c
789
+ except KeyError:
790
+ raise ValueError("order argument does not contain all monomials")
791
+ return A, vector(v)
792
+
793
+ def coefficient_matrix(self, sparse=True):
794
+ """
795
+ Return tuple ``(A,v)`` where ``A`` is the coefficient matrix
796
+ of this system and ``v`` the matching monomial vector.
797
+
798
+ Thus value of ``A[i,j]`` corresponds the coefficient of the
799
+ monomial ``v[j]`` in the ``i``-th polynomial in this system.
800
+
801
+ Monomials are order w.r.t. the term ordering of
802
+ ``self.ring()`` in reverse order, i.e. such that the smallest
803
+ entry comes last.
804
+
805
+ INPUT:
806
+
807
+ - ``sparse`` -- construct a sparse matrix (default: ``True``)
808
+
809
+ EXAMPLES::
810
+
811
+ sage: # needs sage.libs.singular
812
+ sage: P.<a,b,c,d> = PolynomialRing(GF(127), 4)
813
+ sage: I = sage.rings.ideal.Katsura(P)
814
+ sage: I.gens()
815
+ [a + 2*b + 2*c + 2*d - 1,
816
+ a^2 + 2*b^2 + 2*c^2 + 2*d^2 - a,
817
+ 2*a*b + 2*b*c + 2*c*d - b,
818
+ b^2 + 2*a*c + 2*b*d - c]
819
+ sage: F = Sequence(I)
820
+ sage: A,v = F.coefficient_matrix()
821
+ doctest:warning...
822
+ DeprecationWarning: the function coefficient_matrix is deprecated; use coefficients_monomials instead
823
+ See https://github.com/sagemath/sage/issues/37035 for details.
824
+ sage: A
825
+ [ 0 0 0 0 0 0 0 0 0 1 2 2 2 126]
826
+ [ 1 0 2 0 0 2 0 0 2 126 0 0 0 0]
827
+ [ 0 2 0 0 2 0 0 2 0 0 126 0 0 0]
828
+ [ 0 0 1 2 0 0 2 0 0 0 0 126 0 0]
829
+ sage: v
830
+ [a^2]
831
+ [a*b]
832
+ [b^2]
833
+ [a*c]
834
+ [b*c]
835
+ [c^2]
836
+ [b*d]
837
+ [c*d]
838
+ [d^2]
839
+ [ a]
840
+ [ b]
841
+ [ c]
842
+ [ d]
843
+ [ 1]
844
+ sage: A*v
845
+ [ a + 2*b + 2*c + 2*d - 1]
846
+ [a^2 + 2*b^2 + 2*c^2 + 2*d^2 - a]
847
+ [ 2*a*b + 2*b*c + 2*c*d - b]
848
+ [ b^2 + 2*a*c + 2*b*d - c]
849
+ """
850
+ from sage.matrix.constructor import matrix
851
+ from sage.misc.superseded import deprecation
852
+ deprecation(37035, "the function coefficient_matrix is deprecated; use coefficients_monomials instead")
853
+
854
+ R = self.ring()
855
+ A, v = self.coefficients_monomials(sparse=sparse)
856
+ return A, matrix(R, len(v), 1, v)
857
+
858
+ def macaulay_matrix(self, degree,
859
+ homogeneous=False,
860
+ variables=None,
861
+ return_indices=False,
862
+ remove_zero=False,
863
+ reverse_column_order=False,
864
+ row_order=None):
865
+ r"""
866
+ Return the Macaulay matrix of degree ``degree`` for this sequence
867
+ of polynomials.
868
+
869
+ INPUT:
870
+
871
+ - ``homogeneous`` -- boolean (default: ``False``);
872
+ when ``False``, the polynomials in the sequence do not need to be homogeneous
873
+ the rows of the Macaulay matrix correspond to all possible products
874
+ between a polynomial from the sequence and monomials of the polynomial
875
+ ring up to degree ``degree``;
876
+ when ``True``, all polynomials in the sequence must be homogeneous, and
877
+ the rows of the Macaulay matrix then represent all possible products
878
+ between a polynomial in the sequence and a monomial of the polynomial
879
+ ring such that the resulting product is homogeneous of degree
880
+ ``degree + d_max``, where ``d_max`` is the maximum degree among the
881
+ input polynomials
882
+
883
+ - ``variables`` -- list (default: ``None``);
884
+ when ``None``, ``variables`` is interpreted as being the list of
885
+ all variables of the ring of the polynomials in the sequence;
886
+ otherwise ``variables`` is a list describing a subset of these
887
+ variables, and only these variables are used (instead of all ring
888
+ variables) when forming monomials to multiply the polynomials of the
889
+ sequence
890
+
891
+ - ``return_indices`` -- boolean (default: ``False``);
892
+ when ``False``, only return the Macaulay matrix;
893
+ when ``True``, return the Macaulay matrix and two lists: the first
894
+ one is a list of pairs, each of them containing a monomial and the
895
+ index in the sequence of the input polynomial, whose product
896
+ describes the corresponding row of the matrix; the second one is the
897
+ list of monomials corresponding to the columns of the matrix
898
+
899
+ - ``remove_zero`` -- boolean (default: ``False``);
900
+ when ``False``, all monomials of the polynomial ring up to
901
+ degree ``degree``are included as columns in the Macaulay matrix;
902
+ when ``True``, only the monomials that actually appear in the polynomial
903
+ sequence are included
904
+
905
+ - ``reverse_column_order`` -- boolean (default: ``False``);
906
+ when ``False``, by default, the order of the columns is the same
907
+ as the order of the polynomial ring;
908
+ when ``True``, the order of the columns is the reverse of the order
909
+ of the polynomial ring
910
+
911
+ - ``row_order`` -- str (default: ``None``);
912
+ determines the ordering of the rows in the matrix;
913
+ when ``None`` (or ``"POT"``), a **position over term** (POT) order is used:
914
+ rows are first ordered by the index of the corresponding polynomial
915
+ in the sequence, and then by the (multiplicative) monomials;
916
+ when set to ``"TOP"``, the rows follow a **term over position**
917
+ (TOP) order: rows are first ordered by the (multiplicative) monomials
918
+ and then by the index of the corresponding polynomial
919
+ in the sequence
920
+
921
+ EXAMPLES::
922
+
923
+ sage: R.<x,y,z> = PolynomialRing(GF(7), order='deglex')
924
+ sage: L = Sequence([2*x*z - y*z + 2*z^2 + 3*x - 1,
925
+ ....: 2*x^2 - 3*y*z + z^2 - 3*y + 3,
926
+ ....: -x^2 - 2*x*z - 3*y*z + 3*x])
927
+ sage: L.macaulay_matrix(0) # needs sage.combinat sage.modules
928
+ [0 0 2 0 6 2 3 0 0 6]
929
+ [2 0 0 0 4 1 0 4 0 3]
930
+ [6 0 5 0 4 0 3 0 0 0]
931
+
932
+ Example with a sequence of homogeneous polynomials::
933
+
934
+ sage: R.<x,y,z> = PolynomialRing(QQ)
935
+ sage: L = Sequence([x*y^2 + y^3 + x*y*z + y*z^2,
936
+ ....: x^2*y + x*y^2 + x*y*z + 3*x*z^2 + z^3,
937
+ ....: x^3 + 2*y^3 + x^2*z + 2*x*y*z + 2*z^3])
938
+ sage: L.macaulay_matrix(1, homogeneous=True) # needs sage.combinat sage.modules
939
+ [0 0 0 0 0 0 0 1 1 0 1 0 0 1 0]
940
+ [0 0 0 1 1 0 0 1 0 0 0 1 0 0 0]
941
+ [0 0 1 1 0 0 1 0 0 0 1 0 0 0 0]
942
+ [0 0 0 0 0 0 1 1 0 0 1 0 3 0 1]
943
+ [0 0 1 1 0 0 0 1 0 0 3 0 0 1 0]
944
+ [0 1 1 0 0 0 1 0 0 3 0 0 1 0 0]
945
+ [0 0 0 0 0 1 0 0 2 1 2 0 0 0 2]
946
+ [0 1 0 0 2 0 1 2 0 0 0 0 0 2 0]
947
+ [1 0 0 2 0 1 2 0 0 0 0 0 2 0 0]
948
+
949
+ Same example for which we now ask to remove monomials that do not
950
+ appear in the sequence (``remove_zero=True``), and to return the row
951
+ and column indices::
952
+
953
+ sage: R.<x,y,z> = PolynomialRing(QQ)
954
+ sage: L = Sequence([x*y + 2*z^2, y^2 + y*z, x*z])
955
+ sage: L.macaulay_matrix(1, homogeneous=True, remove_zero=True, # needs sage.combinat sage.modules
956
+ ....: return_indices=True)
957
+ (
958
+ [0 0 0 0 1 0 0 0 2]
959
+ [0 1 0 0 0 0 0 2 0]
960
+ [1 0 0 0 0 0 2 0 0]
961
+ [0 0 0 0 0 1 0 1 0]
962
+ [0 0 1 0 0 1 0 0 0]
963
+ [0 1 0 0 1 0 0 0 0]
964
+ [0 0 0 0 0 0 1 0 0]
965
+ [0 0 0 0 1 0 0 0 0]
966
+ [0 0 0 1 0 0 0 0 0],
967
+ [(z, 0), (y, 0), (x, 0), (z, 1), (y, 1), (x, 1), (z, 2), (y, 2), (x, 2)],
968
+ [x^2*y, x*y^2, y^3, x^2*z, x*y*z, y^2*z, x*z^2, y*z^2, z^3]
969
+ )
970
+
971
+ Example in which we build rows using monomials that involve only a
972
+ subset of the ring variables (``variables=['x']``)::
973
+
974
+ sage: R.<x,y,z> = PolynomialRing(QQ)
975
+ sage: L = Sequence([2*y*z - 2*z^2 - 3*x + z - 3,
976
+ ....: -3*y^2 + 3*y*z + 2*z^2 - 2*x - 2*y,
977
+ ....: -2*y - z - 3])
978
+ sage: L.macaulay_matrix(1, variables=['x'], remove_zero=True, # needs sage.combinat sage.modules
979
+ ....: return_indices=True)
980
+ (
981
+ [ 0 0 0 0 0 0 0 0 0 2 -2 -3 0 1 -3]
982
+ [ 0 0 0 2 -2 -3 0 0 1 0 0 -3 0 0 0]
983
+ [ 0 0 0 0 0 0 0 -3 0 3 2 -2 -2 0 0]
984
+ [ 0 -3 0 3 2 -2 -2 0 0 0 0 0 0 0 0]
985
+ [ 0 0 0 0 0 0 0 0 0 0 0 0 -2 -1 -3]
986
+ [ 0 0 0 0 0 0 -2 0 -1 0 0 -3 0 0 0]
987
+ [-2 0 -1 0 0 -3 0 0 0 0 0 0 0 0 0],
988
+ [(1, 0), (x, 0), (1, 1), (x, 1), (1, 2), (x, 2), (x^2, 2)],
989
+ [x^2*y, x*y^2, x^2*z, x*y*z, x*z^2, x^2, x*y, y^2, x*z, y*z, z^2, x, y, z, 1]
990
+ )
991
+
992
+ TESTS::
993
+
994
+ sage: R.<x,y,z> = PolynomialRing(GF(7),order='deglex')
995
+ sage: from sage.rings.polynomial.multi_polynomial_sequence import PolynomialSequence_generic
996
+ sage: PolynomialSequence_generic([], R).macaulay_matrix(1)
997
+ Traceback (most recent call last):
998
+ ...
999
+ ValueError: the sequence of polynomials must be nonempty
1000
+
1001
+ sage: Sequence([x*y, x**2]).macaulay_matrix(-1)
1002
+ Traceback (most recent call last):
1003
+ ...
1004
+ ValueError: the degree must be nonnegative
1005
+
1006
+ sage: Sequence([y*z + z^2 - 1,x*y - z^2 - x ]).macaulay_matrix(0, homogeneous=True)
1007
+ Traceback (most recent call last):
1008
+ ...
1009
+ ValueError: all the polynomials of the sequence must be homogeneous
1010
+
1011
+ sage:Sequence([y*z + z^2 - 1,x*y - z^2 - x ]).macaulay_matrix(0, row_order="POP")
1012
+ Traceback (most recent call last):
1013
+ ...
1014
+ ValueError: the argument of ``row_order`` must be ``None``, "TOP" or "POT"
1015
+
1016
+ sage: R1.<t>=PolynomialRing(GF(3))
1017
+ sage: Sequence([y*z + z^2 - 1,x*y - z^2 - x ]).macaulay_matrix(1, variables=[t])
1018
+ Traceback (most recent call last):
1019
+ ...
1020
+ ValueError: the variables must be in the polynomial ring
1021
+
1022
+ sage: Sequence([y*z + z^2 - 1,x*y - z^2 - x ]).macaulay_matrix(1, row_order="increasing")
1023
+ Traceback (most recent call last):
1024
+ ...
1025
+ ValueError: the argument of ``row_order`` must be ``None``, "TOP" or "POT"
1026
+
1027
+ sage: R.<x,y,z> = PolynomialRing(GF(7),order='degrevlex(2),neglex(1)')
1028
+ sage: Sequence([y*z + z^2 - 1,x*y - z^2 - x ]).macaulay_matrix(1, variables=[x,z])
1029
+ Traceback (most recent call last):
1030
+ ...
1031
+ ValueError: impossible to use the original term order (most likely because it was a block order). Please specify the term order for the subring
1032
+
1033
+ REFERENCES:
1034
+
1035
+ [Mac1902]_, Chapter 1 of [Mac1916]_
1036
+ """
1037
+ m = len(self)
1038
+
1039
+ # handle unsuitable input
1040
+ if m == 0:
1041
+ raise ValueError('the sequence of polynomials must be nonempty')
1042
+ if degree < 0:
1043
+ raise ValueError('the degree must be nonnegative')
1044
+ if homogeneous:
1045
+ for i in range(m):
1046
+ if not (self[i].is_homogeneous()):
1047
+ raise ValueError('all the polynomials of the sequence must be homogeneous')
1048
+ if not (row_order is None or row_order == "TOP" or row_order == "POT"):
1049
+ raise ValueError('the argument of ``row_order`` must be ``None``, "TOP" or "POT"')
1050
+
1051
+ # handle subset of variables
1052
+ S = self.ring()
1053
+ F = S.base_ring()
1054
+ if variables is None:
1055
+ R = S
1056
+ else:
1057
+ vars_names_base_ring = list(S.variable_names())
1058
+ for x in variables:
1059
+ if str(x) not in vars_names_base_ring:
1060
+ raise ValueError("the variables must be in the polynomial ring")
1061
+ try:
1062
+ R = PolynomialRing(F, variables,
1063
+ order=S.term_order())
1064
+ except ValueError:
1065
+ raise ValueError("impossible to use the original term order (most likely because it was a block order). Please specify the term order for the subring")
1066
+
1067
+ # maximum degree for monomials appearing in considered polynomial multiples
1068
+ target_degree = self.maximal_degree() + degree
1069
+
1070
+ # precompute `monomials_of_degree(deg)` for the relevant values of `deg`
1071
+ # homogeneous:
1072
+ # row_indices: we need them for deg = target_degree - self[i].degree(),
1073
+ # for all i = 0 ... len(self)-1
1074
+ # column_indices: we need them for deg = target_degree
1075
+ # non homogeneous:
1076
+ # row_indices: we need them for deg = 0 ... target_degree - self[i].degree(),
1077
+ # for all i = 0 ... len(self)-1,
1078
+ # -> i.e. for deg = 0 ... target_degree - min(self[i].degree() for all i)
1079
+ # column_indices: we need them for deg = 0 ... target_degree
1080
+ R_monomials_of_degree = {}
1081
+ S_monomials_of_degree = {}
1082
+ if homogeneous:
1083
+ for poly_deg in {poly.degree() for poly in self}:
1084
+ deg = target_degree - poly_deg
1085
+ R_monomials_of_degree[deg] = R.monomials_of_degree(deg)
1086
+ S_monomials_of_degree[target_degree] = S.monomials_of_degree(target_degree)
1087
+ else:
1088
+ max_deg = target_degree - min(poly.degree() for poly in self)
1089
+ for deg in range(max_deg + 1):
1090
+ R_monomials_of_degree[deg] = R.monomials_of_degree(deg)
1091
+ for deg in range(target_degree + 1):
1092
+ S_monomials_of_degree[deg] = S.monomials_of_degree(deg)
1093
+
1094
+ # compute list of extended monomials (ring monomials + polynomial position)
1095
+ # that will be used to construct the rows
1096
+ row_indices = []
1097
+ if homogeneous:
1098
+ # order the rows with POT (or None)
1099
+ if row_order is None or row_order == "POT":
1100
+ for i in range(m):
1101
+ deg = target_degree - self[i].degree()
1102
+ R_monomials_of_degree[deg].sort()
1103
+ row_indices += [(mon, i) for mon in R_monomials_of_degree[deg]]
1104
+ # order the rows with TOP
1105
+ else:
1106
+ R_monomials_useful = []
1107
+ for i in range(degree, target_degree-self.minimal_degree()+1):
1108
+ R_monomials_useful += R_monomials_of_degree[i]
1109
+ R_monomials_useful.sort()
1110
+ for mon in R_monomials_useful:
1111
+ row_indices += [(mon, i) for i in range(m) if self[i].degree() + mon.degree() == target_degree]
1112
+ else:
1113
+ # order the row with POT (or None)
1114
+ if row_order is None or row_order == "POT":
1115
+ for i in range(m):
1116
+ R_monomials_useful = []
1117
+ for deg in range(target_degree - self[i].degree() + 1):
1118
+ R_monomials_useful += R_monomials_of_degree[deg]
1119
+ R_monomials_useful.sort()
1120
+ row_indices += [(mon, i) for mon in R_monomials_useful]
1121
+ # order the row with TOP
1122
+ else:
1123
+ R_monomials_useful = []
1124
+ for deg in range(max_deg + 1):
1125
+ R_monomials_useful += R_monomials_of_degree[deg]
1126
+ R_monomials_useful.sort()
1127
+ for mon in R_monomials_useful:
1128
+ row_indices += [(mon, i) for i in range(m)
1129
+ if mon.degree() + self[i].degree() <= target_degree]
1130
+
1131
+ # compute sorted list of monomials that index the columns
1132
+ if remove_zero:
1133
+ # FIXME clean (and refactor multiplications?)
1134
+ column_indices = list(set(sum(((mon * self[i]).monomials() for mon, i in row_indices), [])))
1135
+ else:
1136
+ if homogeneous:
1137
+ column_indices = S_monomials_of_degree[target_degree]
1138
+ else:
1139
+ column_indices = [mon for deg in range(target_degree + 1)
1140
+ for mon in S_monomials_of_degree[deg]]
1141
+ column_indices.sort(reverse=not reverse_column_order)
1142
+ dict_columns = {mon.exponents()[0]: j for (j, mon) in enumerate(column_indices)}
1143
+
1144
+ # actually build the Macaulay matrix
1145
+ from sage.matrix.constructor import matrix
1146
+
1147
+ macaulay_mat = matrix(F, len(row_indices), len(column_indices))
1148
+ for (ii, (mrow, i)) in enumerate(row_indices):
1149
+ # in row ii, we put coefficients of the multiple mrow * self[i]
1150
+ poly = mrow * self[i]
1151
+ for mon, coeff in poly.iterator_exp_coeff():
1152
+ macaulay_mat[ii, dict_columns[mon]] = coeff
1153
+
1154
+ if not return_indices:
1155
+ return macaulay_mat
1156
+ else:
1157
+ return macaulay_mat, row_indices, column_indices
1158
+
1159
+ def subs(self, *args, **kwargs):
1160
+ """
1161
+ Substitute variables for every polynomial in this system and
1162
+ return a new system. See :meth:`MPolynomial.subs` for calling
1163
+ convention.
1164
+
1165
+ INPUT:
1166
+
1167
+ - ``args`` -- arguments to be passed to :meth:`MPolynomial.subs`
1168
+ - ``kwargs`` -- keyword arguments to be passed to :meth:`MPolynomial.subs`
1169
+
1170
+ EXAMPLES::
1171
+
1172
+ sage: sr = mq.SR(allow_zero_inversions=True) # needs sage.rings.polynomial.pbori
1173
+ sage: F, s = sr.polynomial_system(); F # needs sage.rings.polynomial.pbori
1174
+ Polynomial Sequence with 40 Polynomials in 20 Variables
1175
+ sage: F = F.subs(s); F # needs sage.rings.polynomial.pbori
1176
+ Polynomial Sequence with 40 Polynomials in 16 Variables
1177
+ """
1178
+ return PolynomialSequence(self._ring, [tuple([f.subs(*args, **kwargs) for f in r]) for r in self._parts])
1179
+
1180
+ def _singular_(self):
1181
+ """
1182
+ Return Singular ideal representation of this system.
1183
+
1184
+ EXAMPLES::
1185
+
1186
+ sage: # needs sage.libs.singular
1187
+ sage: P.<a,b,c,d> = PolynomialRing(GF(127))
1188
+ sage: I = sage.rings.ideal.Katsura(P)
1189
+ sage: F = Sequence(I); F
1190
+ [a + 2*b + 2*c + 2*d - 1,
1191
+ a^2 + 2*b^2 + 2*c^2 + 2*d^2 - a,
1192
+ 2*a*b + 2*b*c + 2*c*d - b,
1193
+ b^2 + 2*a*c + 2*b*d - c]
1194
+ sage: F._singular_()
1195
+ a+2*b+2*c+2*d-1,
1196
+ a^2+2*b^2+2*c^2+2*d^2-a,
1197
+ 2*a*b+2*b*c+2*c*d-b,
1198
+ b^2+2*a*c+2*b*d-c
1199
+ """
1200
+ return singular.ideal(list(self))
1201
+
1202
+ def _magma_init_(self, magma):
1203
+ """
1204
+ Return Magma ideal representation of the ideal spanned by this
1205
+ system.
1206
+
1207
+ EXAMPLES::
1208
+
1209
+ sage: # needs sage.rings.polynomial.pbori
1210
+ sage: sr = mq.SR(allow_zero_inversions=True, gf2=True)
1211
+ sage: F,s = sr.polynomial_system()
1212
+ sage: F.set_immutable()
1213
+ sage: magma(F) # optional - magma
1214
+ Ideal of Boolean polynomial ring of rank 20 over GF(2)
1215
+ Order: Graded Lexicographical (bit vector word)
1216
+ Variables: k100, k101, k102, k103, x100, x101, x102, x103, w100, w101, w102, w103, s000, s001, s002, s003, k000, k001, k002, k003
1217
+ Basis:
1218
+ [
1219
+ ...
1220
+ ]
1221
+ """
1222
+ P = magma(self.ring()).name()
1223
+ v = [x._magma_init_(magma) for x in list(self)]
1224
+ return 'ideal<%s|%s>' % (P, ','.join(v))
1225
+
1226
+ def _is_short_for_repr(self):
1227
+ """
1228
+ Return whether this system is considered short for :meth:`_repr_`.
1229
+ """
1230
+ return len(self) < 20
1231
+
1232
+ def _repr_(self):
1233
+ """
1234
+ Return a string representation of this system.
1235
+ Typically, :meth:`_repr_pretty_` is used instead of this method.
1236
+
1237
+ EXAMPLES::
1238
+
1239
+ sage: # needs sage.libs.singular
1240
+ sage: P.<a,b,c,d> = PolynomialRing(GF(127))
1241
+ sage: I = sage.rings.ideal.Katsura(P)
1242
+ sage: F = Sequence(I); print(F._repr_())
1243
+ [a + 2*b + 2*c + 2*d - 1,
1244
+ a^2 + 2*b^2 + 2*c^2 + 2*d^2 - a,
1245
+ 2*a*b + 2*b*c + 2*c*d - b,
1246
+ b^2 + 2*a*c + 2*b*d - c]
1247
+
1248
+ If the system contains 20 or more polynomials, a short summary
1249
+ is printed::
1250
+
1251
+ sage: sr = mq.SR(allow_zero_inversions=True, gf2=True) # needs sage.rings.polynomial.pbori
1252
+ sage: F,s = sr.polynomial_system(); F # needs sage.rings.polynomial.pbori
1253
+ Polynomial Sequence with 36 Polynomials in 20 Variables
1254
+ """
1255
+ if self._is_short_for_repr():
1256
+ return super()._repr_()
1257
+ else:
1258
+ return "Polynomial Sequence with %d Polynomials in %d Variables" % (len(self), self.nvariables())
1259
+
1260
+ def _repr_pretty_(self, p, cycle):
1261
+ """
1262
+ For pretty printing in the Sage command prompt.
1263
+
1264
+ EXAMPLES::
1265
+
1266
+ sage: # needs sage.libs.singular
1267
+ sage: P.<a,b,c,d> = PolynomialRing(GF(127))
1268
+ sage: I = sage.rings.ideal.Katsura(P)
1269
+ sage: F = Sequence(I); F # indirect doctest
1270
+ [a + 2*b + 2*c + 2*d - 1,
1271
+ a^2 + 2*b^2 + 2*c^2 + 2*d^2 - a,
1272
+ 2*a*b + 2*b*c + 2*c*d - b,
1273
+ b^2 + 2*a*c + 2*b*d - c]
1274
+
1275
+ If the system contains 20 or more polynomials, a short summary
1276
+ is printed::
1277
+
1278
+ sage: sr = mq.SR(allow_zero_inversions=True, gf2=True) # needs sage.rings.polynomial.pbori
1279
+ sage: F,s = sr.polynomial_system(); F # needs sage.rings.polynomial.pbori
1280
+ Polynomial Sequence with 36 Polynomials in 20 Variables
1281
+ """
1282
+ if self._is_short_for_repr():
1283
+ super()._repr_pretty_(p, cycle)
1284
+ else:
1285
+ p.text(repr(self))
1286
+
1287
+ def __add__(self, right):
1288
+ """
1289
+ Add polynomial systems together, i.e. create a union of their
1290
+ polynomials.
1291
+
1292
+ EXAMPLES::
1293
+
1294
+ sage: # needs sage.libs.singular
1295
+ sage: P.<a,b,c,d> = PolynomialRing(GF(127))
1296
+ sage: I = sage.rings.ideal.Katsura(P)
1297
+ sage: F = Sequence(I)
1298
+ sage: F + [a^127 + a]
1299
+ [a + 2*b + 2*c + 2*d - 1,
1300
+ a^2 + 2*b^2 + 2*c^2 + 2*d^2 - a,
1301
+ 2*a*b + 2*b*c + 2*c*d - b,
1302
+ b^2 + 2*a*c + 2*b*d - c,
1303
+ a^127 + a]
1304
+ sage: F + P.ideal([a^127 + a])
1305
+ [a + 2*b + 2*c + 2*d - 1,
1306
+ a^2 + 2*b^2 + 2*c^2 + 2*d^2 - a,
1307
+ 2*a*b + 2*b*c + 2*c*d - b,
1308
+ b^2 + 2*a*c + 2*b*d - c,
1309
+ a^127 + a]
1310
+ sage: F + Sequence([a^127 + a], P)
1311
+ [a + 2*b + 2*c + 2*d - 1,
1312
+ a^2 + 2*b^2 + 2*c^2 + 2*d^2 - a,
1313
+ 2*a*b + 2*b*c + 2*c*d - b,
1314
+ b^2 + 2*a*c + 2*b*d - c,
1315
+ a^127 + a]
1316
+ """
1317
+ if isinstance(right, PolynomialSequence_generic) and right.ring() == self.ring():
1318
+ return PolynomialSequence(self.ring(), self.parts() + right.parts())
1319
+
1320
+ elif isinstance(right, (tuple, list)) and all((x.parent() == self.ring() for x in right)):
1321
+ return PolynomialSequence(self.ring(), self.parts() + (right,))
1322
+
1323
+ elif isinstance(right, MPolynomialIdeal) and (right.ring() is self.ring() or right.ring() == self.ring()):
1324
+ return PolynomialSequence(self.ring(), self.parts() + (right.gens(),))
1325
+
1326
+ else:
1327
+ raise TypeError("right must be a system over same ring as self.")
1328
+
1329
+ def connection_graph(self):
1330
+ """
1331
+ Return the graph which has the variables of this system as
1332
+ vertices and edges between two variables if they appear in the
1333
+ same polynomial.
1334
+
1335
+ EXAMPLES::
1336
+
1337
+ sage: # needs sage.graphs sage.rings.polynomial.pbori
1338
+ sage: B.<x,y,z> = BooleanPolynomialRing()
1339
+ sage: F = Sequence([x*y + y + 1, z + 1])
1340
+ sage: G = F.connection_graph(); G
1341
+ Graph on 3 vertices
1342
+ sage: G.is_connected()
1343
+ False
1344
+ sage: F = Sequence([x])
1345
+ sage: F.connection_graph()
1346
+ Graph on 1 vertex
1347
+
1348
+ TESTS::
1349
+
1350
+ sage: # needs sage.graphs sage.rings.polynomial.pbori
1351
+ sage: F = Sequence([], B)
1352
+ sage: F.connection_graph()
1353
+ Graph on 0 vertices
1354
+ sage: F = Sequence([1], B)
1355
+ sage: F.connection_graph()
1356
+ Graph on 0 vertices
1357
+ sage: F = Sequence([x])
1358
+ sage: F.connection_graph()
1359
+ Graph on 1 vertex
1360
+ sage: F = Sequence([x, y])
1361
+ sage: F.connection_graph()
1362
+ Graph on 2 vertices
1363
+ sage: F = Sequence([x*y*z])
1364
+ sage: F.connection_graph().is_clique()
1365
+ True
1366
+ sage: F = Sequence([x*y, y*z])
1367
+ sage: F.connection_graph().is_clique()
1368
+ False
1369
+ """
1370
+ from sage.graphs.graph import Graph
1371
+ g = Graph()
1372
+ for f in self:
1373
+ g.add_clique(f.variables())
1374
+ return g
1375
+
1376
+ def connected_components(self):
1377
+ """
1378
+ Split the polynomial system in systems which do not share any
1379
+ variables.
1380
+
1381
+ EXAMPLES:
1382
+
1383
+ As an example consider one part of AES, which naturally
1384
+ splits into four subsystems which are independent::
1385
+
1386
+ sage: # needs sage.rings.polynomial.pbori
1387
+ sage: sr = mq.SR(2, 4, 4, 8, gf2=True, polybori=True)
1388
+ sage: while True: # workaround (see :issue:`31891`)
1389
+ ....: try:
1390
+ ....: F, s = sr.polynomial_system()
1391
+ ....: break
1392
+ ....: except ZeroDivisionError:
1393
+ ....: pass
1394
+ sage: Fz = Sequence(F.part(2))
1395
+ sage: Fz.connected_components()
1396
+ [Polynomial Sequence with 128 Polynomials in 128 Variables,
1397
+ Polynomial Sequence with 128 Polynomials in 128 Variables,
1398
+ Polynomial Sequence with 128 Polynomials in 128 Variables,
1399
+ Polynomial Sequence with 128 Polynomials in 128 Variables]
1400
+
1401
+ TESTS:
1402
+
1403
+ Check the order of the output (:issue:`35518`)::
1404
+
1405
+ sage: R.<x,y,z> = PolynomialRing(ZZ)
1406
+ sage: Sequence([x,z,y]).connected_components()
1407
+ [[x], [z], [y]]
1408
+ sage: Sequence([x,z,x*y*z,y]).connected_components()
1409
+ [[x, z, x*y*z, y]]
1410
+ """
1411
+ # precompute the list of variables in each polynomial
1412
+ vss = [f.variables() for f in self]
1413
+
1414
+ # Use a union-find data structure to encode relationships between
1415
+ # variables, i.e., that they belong to a same polynomial
1416
+ from sage.sets.disjoint_set import DisjointSet
1417
+ DS = DisjointSet(set().union(*vss))
1418
+ for u, *vs in vss:
1419
+ for v in vs:
1420
+ DS.union(u, v)
1421
+
1422
+ Ps = {} # map root element -> polynomials in this component
1423
+ for f, vs in zip(self, vss):
1424
+ r = DS.find(vs[0])
1425
+ if r in Ps:
1426
+ Ps[r].append(f)
1427
+ else:
1428
+ Ps[r] = [f]
1429
+
1430
+ return [PolynomialSequence(self.ring(), p) for p in Ps.values()]
1431
+
1432
+ def _groebner_strategy(self):
1433
+ """
1434
+ Return the Singular Groebner Strategy object.
1435
+
1436
+ This object allows to compute normal forms efficiently, since
1437
+ all conversion overhead is avoided.
1438
+
1439
+ EXAMPLES::
1440
+
1441
+ sage: P.<x,y,z> = PolynomialRing(GF(127))
1442
+ sage: F = Sequence([x*y + z, y + z + 1])
1443
+ sage: F._groebner_strategy() # needs sage.libs.singular
1444
+ Groebner Strategy for ideal generated by 2 elements over
1445
+ Multivariate Polynomial Ring in x, y, z over Finite Field of size 127
1446
+ """
1447
+ from sage.libs.singular.groebner_strategy import GroebnerStrategy
1448
+ return GroebnerStrategy(self.ideal())
1449
+
1450
+ def maximal_degree(self):
1451
+ """
1452
+ Return the maximal degree of any polynomial in this sequence.
1453
+
1454
+ EXAMPLES::
1455
+
1456
+ sage: P.<x,y,z> = PolynomialRing(GF(7))
1457
+ sage: F = Sequence([x*y + x, x])
1458
+ sage: F.maximal_degree()
1459
+ 2
1460
+ sage: P.<x,y,z> = PolynomialRing(GF(7))
1461
+ sage: F = Sequence([], universe=P)
1462
+ sage: F.maximal_degree()
1463
+ -1
1464
+ """
1465
+ try:
1466
+ return max(f.degree() for f in self)
1467
+ except ValueError:
1468
+ return -1 # empty sequence
1469
+
1470
+ def minimal_degree(self):
1471
+ """
1472
+ Return the minimal degree of any polynomial in this sequence.
1473
+
1474
+ EXAMPLES::
1475
+
1476
+ sage: P.<x,y,z> = PolynomialRing(GF(7))
1477
+ sage: F = Sequence([x*y + x, x])
1478
+ sage: F.minimal_degree()
1479
+ 1
1480
+ sage: P.<x,y,z> = PolynomialRing(GF(7))
1481
+ sage: F = Sequence([], universe=P)
1482
+ sage: F.minimal_degree()
1483
+ -1
1484
+ """
1485
+ try:
1486
+ return min(f.degree() for f in self)
1487
+ except ValueError:
1488
+ return -1 # empty sequence
1489
+
1490
+ def __reduce__(self):
1491
+ """
1492
+ TESTS::
1493
+
1494
+ sage: P.<x,y,z> = PolynomialRing(GF(127))
1495
+ sage: F = Sequence([x*y + z, y + z + 1])
1496
+ sage: loads(dumps(F)) == F
1497
+ True
1498
+
1499
+ We check that :issue:`26354` is fixed::
1500
+
1501
+ sage: f = P.hom([y,z,x])
1502
+ sage: hash(f) == hash(loads(dumps(f)))
1503
+ True
1504
+ """
1505
+ return PolynomialSequence, (self._ring, self._parts, self._is_immutable,
1506
+ self._Sequence_generic__cr, self._Sequence_generic__cr_str)
1507
+
1508
+ @singular_gb_standard_options
1509
+ @libsingular_gb_standard_options
1510
+ def reduced(self):
1511
+ r"""
1512
+ If this sequence is `(f_1, ..., f_n)` then this method
1513
+ returns `(g_1, ..., g_s)` such that:
1514
+
1515
+ - `(f_1,...,f_n) = (g_1,...,g_s)`
1516
+
1517
+ - `LT(g_i) \neq LT(g_j)` for all `i \neq j`
1518
+
1519
+ - `LT(g_i)` does not divide `m` for all monomials `m` of
1520
+ `\{g_1,...,g_{i-1},g_{i+1},...,g_s\}`
1521
+
1522
+ - `LC(g_i) = 1` for all `i` if the coefficient ring is a field.
1523
+
1524
+ EXAMPLES::
1525
+
1526
+ sage: R.<x,y,z> = PolynomialRing(QQ)
1527
+ sage: F = Sequence([z*x+y^3,z+y^3,z+x*y])
1528
+ sage: F.reduced() # needs sage.libs.singular
1529
+ [y^3 + z, x*y + z, x*z - z]
1530
+
1531
+ Note that tail reduction for local orderings is not well-defined::
1532
+
1533
+ sage: R.<x,y,z> = PolynomialRing(QQ,order='negdegrevlex')
1534
+ sage: F = Sequence([z*x+y^3,z+y^3,z+x*y])
1535
+ sage: F.reduced() # needs sage.libs.singular
1536
+ [z + x*y, x*y - y^3, x^2*y - y^3]
1537
+
1538
+ A fixed error with nonstandard base fields::
1539
+
1540
+ sage: R.<t>=QQ['t']
1541
+ sage: K.<x,y>=R.fraction_field()['x,y']
1542
+ sage: I=t*x*K
1543
+ sage: I.basis.reduced() # needs sage.libs.singular
1544
+ [x]
1545
+
1546
+ The interreduced basis of 0 is 0::
1547
+
1548
+ sage: P.<x,y,z> = GF(2)[]
1549
+ sage: Sequence([P(0)]).reduced() # needs sage.libs.singular
1550
+ [0]
1551
+
1552
+ Leading coefficients are reduced to 1::
1553
+
1554
+ sage: P.<x,y> = QQ[]
1555
+ sage: Sequence([2*x,y]).reduced() # needs sage.libs.singular
1556
+ [x, y]
1557
+
1558
+ sage: P.<x,y> = CC[] # needs sage.rings.real_mpfr
1559
+ sage: Sequence([2*x,y]).reduced() # needs sage.libs.singular sage.rings.real_mpfr
1560
+ [x, y]
1561
+
1562
+ ALGORITHM:
1563
+
1564
+ Uses Singular's interred command or
1565
+ :func:`sage.rings.polynomial.toy_buchberger.inter_reduction`
1566
+ if conversion to Singular fails.
1567
+
1568
+ TESTS:
1569
+
1570
+ Check that :issue:`26952` is fixed::
1571
+
1572
+ sage: # needs sage.rings.padics
1573
+ sage: Qp = pAdicField(2)
1574
+ sage: R.<x,y,z> = PolynomialRing(Qp, implementation='generic')
1575
+ sage: F = Sequence([z*x+y^3,z+y^3,3*z+x*y])
1576
+ sage: F.reduced()
1577
+ [y^3 + z, x*y + (1 + 2 + O(2^20))*z, x*z - z]
1578
+ """
1579
+ from sage.rings.polynomial.multi_polynomial_ideal_libsingular import \
1580
+ interred_libsingular
1581
+ from sage.rings.polynomial.multi_polynomial_libsingular import \
1582
+ MPolynomialRing_libsingular
1583
+
1584
+ R = self.ring()
1585
+
1586
+ if isinstance(R, MPolynomialRing_libsingular):
1587
+ return PolynomialSequence(R, interred_libsingular(self), immutable=True)
1588
+ else:
1589
+ try:
1590
+ s = self._singular_().parent()
1591
+ o = s.option("get")
1592
+ s.option("redTail")
1593
+ ret = []
1594
+ for f in self._singular_().interred():
1595
+ f = R(f)
1596
+ ret.append(f.lc()**(-1) * f) # lead coeffs are not reduced by interred
1597
+ s.option("set", o)
1598
+ except TypeError:
1599
+ from sage.rings.polynomial.toy_buchberger import \
1600
+ inter_reduction
1601
+ ret = inter_reduction(self)
1602
+
1603
+ ret = sorted(ret, reverse=True)
1604
+ ret = PolynomialSequence(R, ret, immutable=True)
1605
+ return ret
1606
+
1607
+ @cached_method
1608
+ @singular_gb_standard_options
1609
+ def is_groebner(self, singular=singular):
1610
+ r"""
1611
+ Return ``True`` if the generators of this ideal (``self.gens()``)
1612
+ form a Groebner basis.
1613
+
1614
+ Let `I` be the set of generators of this ideal. The check is
1615
+ performed by trying to lift `Syz(LM(I))` to `Syz(I)` as `I`
1616
+ forms a Groebner basis if and only if for every element `S` in
1617
+ `Syz(LM(I))`:
1618
+
1619
+ .. MATH::
1620
+
1621
+ S \star G = \sum_{i=0}^{m} h_i g_i \longrightarrow_G 0.
1622
+
1623
+ EXAMPLES::
1624
+
1625
+ sage: # needs sage.libs.singular
1626
+ sage: R.<a,b,c,d,e,f,g,h,i,j> = PolynomialRing(GF(127), 10)
1627
+ sage: I = sage.rings.ideal.Cyclic(R, 4)
1628
+ sage: I.basis.is_groebner()
1629
+ False
1630
+ sage: I2 = Ideal(I.groebner_basis())
1631
+ sage: I2.basis.is_groebner()
1632
+ True
1633
+ """
1634
+ return self.ideal().basis_is_groebner()
1635
+
1636
+
1637
+ class PolynomialSequence_gf2(PolynomialSequence_generic):
1638
+ r"""
1639
+ Polynomial Sequences over `\GF{2}`.
1640
+ """
1641
+
1642
+ def eliminate_linear_variables(self, maxlength=Infinity, skip=None, return_reductors=False, use_polybori=False):
1643
+ """
1644
+ Return a new system where linear leading variables are
1645
+ eliminated if the tail of the polynomial has length at most
1646
+ ``maxlength``.
1647
+
1648
+ INPUT:
1649
+
1650
+ - ``maxlength`` -- an optional upper bound on the number of
1651
+ monomials by which a variable is replaced. If
1652
+ ``maxlength==+Infinity`` then no condition is checked.
1653
+ (default: +Infinity).
1654
+
1655
+ - ``skip`` -- an optional callable to skip eliminations. It
1656
+ must accept two parameters and return either ``True`` or
1657
+ ``False``. The two parameters are the leading term and the
1658
+ tail of a polynomial (default: ``None``).
1659
+
1660
+ - ``return_reductors`` -- if ``True`` the list of polynomials
1661
+ with linear leading terms which were used for reduction is
1662
+ also returned (default: ``False``).
1663
+
1664
+ - ``use_polybori`` -- if ``True`` then ``polybori.ll.eliminate`` is
1665
+ called. While this is typically faster than what is implemented here, it
1666
+ is less flexible (``skip`` is not supported) and may increase the
1667
+ degree (default: ``False``)
1668
+
1669
+ OUTPUT:
1670
+
1671
+ With ``return_reductors=True``, a pair of sequences of
1672
+ boolean polynomials are returned, along with the promises that:
1673
+
1674
+ 1. The union of the two sequences spans the
1675
+ same boolean ideal as the argument of the method
1676
+
1677
+ 2. The second sequence only contains linear polynomials, and
1678
+ it forms a reduced groebner basis (they all have pairwise
1679
+ distinct leading variables, and the leading variable of a
1680
+ polynomial does not occur anywhere in other polynomials).
1681
+
1682
+ 3. The leading variables of the second sequence do not occur
1683
+ anywhere in the first sequence (these variables have been
1684
+ eliminated).
1685
+
1686
+ With ``return_reductors=False``, only the first sequence is
1687
+ returned.
1688
+
1689
+ EXAMPLES::
1690
+
1691
+ sage: # needs sage.rings.polynomial.pbori
1692
+ sage: B.<a,b,c,d> = BooleanPolynomialRing()
1693
+ sage: F = Sequence([c + d + b + 1, a + c + d, a*b + c, b*c*d + c])
1694
+ sage: F.eliminate_linear_variables() # everything vanishes
1695
+ []
1696
+ sage: F.eliminate_linear_variables(maxlength=2)
1697
+ [b + c + d + 1, b*c + b*d + c, b*c*d + c]
1698
+ sage: F.eliminate_linear_variables(skip=lambda lm,tail: str(lm)=='a')
1699
+ [a + c + d, a*c + a*d + a + c, c*d + c]
1700
+
1701
+ The list of reductors can be requested by setting ``return_reductors`` to ``True``::
1702
+
1703
+ sage: # needs sage.rings.polynomial.pbori
1704
+ sage: B.<a,b,c,d> = BooleanPolynomialRing()
1705
+ sage: F = Sequence([a + b + d, a + b + c])
1706
+ sage: F, R = F.eliminate_linear_variables(return_reductors=True)
1707
+ sage: F
1708
+ []
1709
+ sage: R
1710
+ [a + b + d, c + d]
1711
+
1712
+
1713
+ If the input system is detected to be inconsistent then ``[1]`` is returned,
1714
+ and the list of reductors is empty::
1715
+
1716
+ sage: # needs sage.rings.polynomial.pbori
1717
+ sage: R.<x,y,z> = BooleanPolynomialRing()
1718
+ sage: S = Sequence([x*y*z + x*y + z*y + x*z, x + y + z + 1, x + y + z])
1719
+ sage: S.eliminate_linear_variables()
1720
+ [1]
1721
+ sage: R.<x,y,z> = BooleanPolynomialRing()
1722
+ sage: S = Sequence([x*y*z + x*y + z*y + x*z, x + y + z + 1, x + y + z])
1723
+ sage: S.eliminate_linear_variables(return_reductors=True)
1724
+ ([1], [])
1725
+
1726
+
1727
+ TESTS:
1728
+
1729
+ The function should really dispose of linear equations (:issue:`13968`)::
1730
+
1731
+ sage: R.<x,y,z> = BooleanPolynomialRing() # needs sage.rings.polynomial.pbori
1732
+ sage: S = Sequence([x + y + z + 1, y + z]) # needs sage.rings.polynomial.pbori
1733
+ sage: S.eliminate_linear_variables(return_reductors=True) # needs sage.rings.polynomial.pbori
1734
+ ([], [x + 1, y + z])
1735
+
1736
+
1737
+ The function should take care of linear variables created by previous
1738
+ substitution of linear variables ::
1739
+
1740
+ sage: R.<x,y,z> = BooleanPolynomialRing() # needs sage.rings.polynomial.pbori
1741
+ sage: S = Sequence([x*y*z + x*y + z*y + x*z, x + y + z + 1, x + y]) # needs sage.rings.polynomial.pbori
1742
+ sage: S.eliminate_linear_variables(return_reductors=True) # needs sage.rings.polynomial.pbori
1743
+ ([], [x + y, z + 1])
1744
+
1745
+ We test a case which would increase the degree with ``polybori=True``::
1746
+
1747
+ sage: # needs sage.rings.polynomial.pbori
1748
+ sage: B.<a,b,c,d> = BooleanPolynomialRing()
1749
+ sage: f = a*d + a + b*d + c*d + 1
1750
+ sage: Sequence([f, a + b*c + c+d + 1]).eliminate_linear_variables()
1751
+ [a*d + a + b*d + c*d + 1, a + b*c + c + d + 1]
1752
+ sage: B.<a,b,c,d> = BooleanPolynomialRing()
1753
+ sage: f = a*d + a + b*d + c*d + 1
1754
+ sage: Sequence([f, a + b*c + c+d + 1]).eliminate_linear_variables(use_polybori=True)
1755
+ [b*c*d + b*c + b*d + c + d]
1756
+
1757
+ .. NOTE::
1758
+
1759
+ This is called "massaging" in [BCJ2007]_.
1760
+ """
1761
+ from sage.rings.polynomial.multi_polynomial_ring_base import \
1762
+ BooleanPolynomialRing_base
1763
+
1764
+ R = self.ring()
1765
+
1766
+ if not isinstance(R, BooleanPolynomialRing_base):
1767
+ raise NotImplementedError("Only BooleanPolynomialRing's are supported.")
1768
+
1769
+ from sage.rings.polynomial.pbori.ll import (eliminate, ll_encode,
1770
+ ll_red_nf_redsb)
1771
+ from sage.rings.polynomial.pbori.pbori import gauss_on_polys
1772
+
1773
+ F = self
1774
+ reductors = []
1775
+
1776
+ if use_polybori and skip is None and maxlength == Infinity:
1777
+ # faster solution based on polybori.ll.eliminate
1778
+ while True:
1779
+ (this_step_reductors, _, higher) = eliminate(F)
1780
+ if this_step_reductors == []:
1781
+ break
1782
+ reductors.extend(this_step_reductors)
1783
+ F = higher
1784
+ else:
1785
+ # slower, more flexible solution
1786
+ if skip is None:
1787
+ def skip(lm, tail):
1788
+ return False
1789
+
1790
+ while True:
1791
+ linear = []
1792
+ higher = []
1793
+
1794
+ for f in F:
1795
+ if f.degree() == 1 and len(f) <= maxlength + 1:
1796
+ flm = f.lex_lead()
1797
+ if skip(flm, f - flm):
1798
+ higher.append(f)
1799
+ continue
1800
+ linear.append(f)
1801
+ else:
1802
+ higher.append(f)
1803
+
1804
+ if not linear:
1805
+ break
1806
+
1807
+ linear = gauss_on_polys(linear)
1808
+ if 1 in linear:
1809
+ if return_reductors:
1810
+ return PolynomialSequence(R, [R(1)]), PolynomialSequence(R, [])
1811
+ else:
1812
+ return PolynomialSequence(R, [R(1)])
1813
+ rb = ll_encode(linear)
1814
+ reductors.extend(linear)
1815
+
1816
+ F = []
1817
+ for f in higher:
1818
+ f = ll_red_nf_redsb(f, rb)
1819
+ if f != 0:
1820
+ F.append(f)
1821
+
1822
+ ret = PolynomialSequence(R, higher)
1823
+ if return_reductors:
1824
+ reduced_reductors = gauss_on_polys(reductors)
1825
+ return ret, PolynomialSequence(R, reduced_reductors)
1826
+ else:
1827
+ return ret
1828
+
1829
+ def _groebner_strategy(self):
1830
+ """
1831
+ Return the Singular Groebner Strategy object.
1832
+
1833
+ This object allows to compute normal forms efficiently, since
1834
+ all conversion overhead is avoided.
1835
+
1836
+ EXAMPLES::
1837
+
1838
+ sage: P.<x,y,z> = PolynomialRing(GF(2))
1839
+ sage: F = Sequence([x*y + z, y + z + 1])
1840
+ sage: F._groebner_strategy() # needs sage.libs.singular
1841
+ Groebner Strategy for ideal generated by 2 elements over
1842
+ Multivariate Polynomial Ring in x, y, z over Finite Field of size 2
1843
+
1844
+ sage: # needs sage.rings.polynomial.pbori
1845
+ sage: P.<x,y,z> = BooleanPolynomialRing()
1846
+ sage: F = Sequence([x*y + z, y + z + 1])
1847
+ sage: F._groebner_strategy() # needs sage.libs.singular
1848
+ <sage.rings.polynomial.pbori.pbori.GroebnerStrategy object at 0x...>
1849
+ """
1850
+ from sage.rings.polynomial.multi_polynomial_ring_base import \
1851
+ BooleanPolynomialRing_base
1852
+
1853
+ R = self.ring()
1854
+
1855
+ if not isinstance(R, BooleanPolynomialRing_base):
1856
+ from sage.libs.singular.groebner_strategy import GroebnerStrategy
1857
+ return GroebnerStrategy(self.ideal())
1858
+ else:
1859
+ from sage.rings.polynomial.pbori.pbori import GroebnerStrategy
1860
+ g = GroebnerStrategy(R)
1861
+ for p in self:
1862
+ g.add_as_you_wish(p)
1863
+ g.reduction_strategy.opt_red_tail = True
1864
+ return g
1865
+
1866
+ def solve(self, algorithm='polybori', n=1,
1867
+ eliminate_linear_variables=True, verbose=False, **kwds):
1868
+ r"""
1869
+ Find solutions of this boolean polynomial system.
1870
+
1871
+ This function provide a unified interface to several algorithms
1872
+ dedicated to solving systems of boolean equations. Depending on
1873
+ the particular nature of the system, some might be much faster
1874
+ than some others.
1875
+
1876
+ INPUT:
1877
+
1878
+ - ``self`` -- a sequence of boolean polynomials
1879
+
1880
+ - ``algorithm`` -- the method to use. Possible values are
1881
+ ``'polybori'``, ``'sat'`` and ``'exhaustive_search'``. (default:
1882
+ ``'polybori'``, since it is always available)
1883
+
1884
+ - ``n`` -- (default: 1) number of solutions to return. If
1885
+ ``n == +Infinity`` then all solutions are returned. If `n < \infty`
1886
+ then `n` solutions are returned if the equations have at least `n`
1887
+ solutions. Otherwise, all the solutions are returned.
1888
+
1889
+ - ``eliminate_linear_variables`` -- whether to eliminate
1890
+ variables that appear linearly. This reduces the number of
1891
+ variables (makes solving faster a priori), but is likely to
1892
+ make the equations denser (may make solving slower depending
1893
+ on the method).
1894
+
1895
+ - ``verbose`` -- boolean (default: ``False``); whether to display
1896
+ progress and (potentially) useful information while the computation
1897
+ runs
1898
+
1899
+ EXAMPLES:
1900
+
1901
+ Without argument, a single arbitrary solution is returned::
1902
+
1903
+ sage: # needs sage.rings.polynomial.pbori
1904
+ sage: R.<x,y,z> = BooleanPolynomialRing()
1905
+ sage: S = Sequence([x*y + z, y*z + x, x + y + z + 1])
1906
+ sage: sol = S.solve()
1907
+ sage: sol
1908
+ [{z: 0, y: 1, x: 0}]
1909
+
1910
+ We check that it is actually a solution::
1911
+
1912
+ sage: S.subs(sol[0]) # needs sage.rings.polynomial.pbori
1913
+ [0, 0, 0]
1914
+
1915
+ We obtain all solutions::
1916
+
1917
+ sage: sols = S.solve(n=Infinity) # needs sage.rings.polynomial.pbori
1918
+ sage: sols # needs sage.rings.polynomial.pbori
1919
+ [{z: 0, y: 1, x: 0}, {z: 1, y: 1, x: 1}]
1920
+ sage: [S.subs(x) for x in sols] # needs sage.rings.polynomial.pbori
1921
+ [[0, 0, 0], [0, 0, 0]]
1922
+
1923
+ We can force the use of exhaustive search if the optional
1924
+ package ``FES`` is present::
1925
+
1926
+ sage: sol = S.solve(algorithm='exhaustive_search') # optional - fes # needs sage.rings.polynomial.pbori
1927
+ sage: sol # optional - fes # needs sage.rings.polynomial.pbori
1928
+ [{z: 1, y: 1, x: 1}]
1929
+ sage: S.subs(sol[0]) # optional - fes # needs sage.rings.polynomial.pbori
1930
+ [0, 0, 0]
1931
+
1932
+ And we may use SAT-solvers if they are available::
1933
+
1934
+ sage: sol = S.solve(algorithm='sat') # optional - pycryptosat # needs sage.rings.polynomial.pbori
1935
+ sage: sol # optional - pycryptosat # needs sage.rings.polynomial.pbori
1936
+ [{z: 0, y: 1, x: 0}]
1937
+ sage: S.subs(sol[0]) # needs sage.rings.polynomial.pbori
1938
+ [0, 0, 0]
1939
+
1940
+ TESTS:
1941
+
1942
+ Make sure that variables not occurring in the equations are no problem::
1943
+
1944
+ sage: # needs sage.rings.polynomial.pbori
1945
+ sage: R.<x,y,z,t> = BooleanPolynomialRing()
1946
+ sage: S = Sequence([x*y + z, y*z + x, x + y + z + 1])
1947
+ sage: sols = S.solve(n=Infinity)
1948
+ sage: [S.subs(x) for x in sols]
1949
+ [[0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0]]
1950
+
1951
+ Not eliminating linear variables::
1952
+
1953
+ sage: sols = S.solve(n=Infinity, eliminate_linear_variables=False) # needs sage.rings.polynomial.pbori
1954
+ sage: [S.subs(x) for x in sols] # needs sage.rings.polynomial.pbori
1955
+ [[0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0]]
1956
+
1957
+ A tricky case where the linear equations are insatisfiable::
1958
+
1959
+ sage: R.<x,y,z> = BooleanPolynomialRing() # needs sage.rings.polynomial.pbori
1960
+ sage: S = Sequence([x*y*z + x*y + z*y + x*z, x + y + z + 1, x + y + z]) # needs sage.rings.polynomial.pbori
1961
+ sage: S.solve() # needs sage.rings.polynomial.pbori
1962
+ []
1963
+ """
1964
+ from sage.modules.free_module import VectorSpace
1965
+
1966
+ S = self
1967
+ R_origin = R_solving = self.ring()
1968
+ reductors = []
1969
+
1970
+ if eliminate_linear_variables:
1971
+ T, reductors = self.eliminate_linear_variables(return_reductors=True)
1972
+ if T.variables() != ():
1973
+ from sage.rings.polynomial.pbori.pbori import \
1974
+ BooleanPolynomialRing
1975
+
1976
+ R_solving = BooleanPolynomialRing(T.nvariables(), [str(_) for _ in list(T.variables())])
1977
+ S = PolynomialSequence(R_solving, [R_solving(f) for f in T])
1978
+
1979
+ if S != []:
1980
+ if algorithm == "polybori":
1981
+ I = S.ideal()
1982
+ if verbose:
1983
+ I.groebner_basis(full_prot=True, **kwds)
1984
+ else:
1985
+ I.groebner_basis(**kwds)
1986
+ solutions = I.variety()
1987
+ if len(solutions) >= n:
1988
+ solutions = solutions[:n]
1989
+
1990
+ elif algorithm == "sat":
1991
+ from sage.sat.boolean_polynomials import solve as solve_sat
1992
+ if verbose:
1993
+ solutions = solve_sat(S, n=n, s_verbosity=1, **kwds)
1994
+ else:
1995
+ solutions = solve_sat(S, n=n, **kwds)
1996
+ else:
1997
+ raise ValueError("unknown 'algorithm' value")
1998
+ else:
1999
+ solutions = []
2000
+
2001
+ if S.variables() == ():
2002
+ solved_variables = set()
2003
+ else:
2004
+ solved_variables = {R_origin(x).lm() for x in R_solving.gens()}
2005
+ eliminated_variables = {f.lex_lead() for f in reductors}
2006
+ leftover_variables = {x.lm() for x in R_origin.gens()} - solved_variables - eliminated_variables
2007
+
2008
+ def key_convert(x):
2009
+ return R_origin(x).lm()
2010
+
2011
+ if leftover_variables != set():
2012
+ partial_solutions = solutions
2013
+ solutions = []
2014
+ for sol in partial_solutions:
2015
+ for v in VectorSpace(GF(2), len(leftover_variables)):
2016
+ new_solution = KeyConvertingDict(key_convert, sol)
2017
+ for var, val in zip(leftover_variables, v):
2018
+ new_solution[var] = val
2019
+ solutions.append(new_solution)
2020
+ else:
2021
+ solutions = [KeyConvertingDict(key_convert, sol)
2022
+ for sol in solutions]
2023
+
2024
+ for r in reductors:
2025
+ for sol in solutions:
2026
+ sol[r.lm()] = r.subs(sol).constant_coefficient()
2027
+
2028
+ return solutions
2029
+
2030
+ def reduced(self):
2031
+ r"""
2032
+ If this sequence is `f_1, ..., f_n`, return `g_1, ..., g_s` such that:
2033
+
2034
+ - `(f_1,...,f_n) = (g_1,...,g_s)`
2035
+ - `LT(g_i) \neq LT(g_j)` for all `i \neq j`
2036
+ - `LT(g_i)` does not divide `m` for all monomials `m` of
2037
+ `{g_1,...,g_{i-1},g_{i+1},...,g_s}`
2038
+
2039
+ EXAMPLES::
2040
+
2041
+ sage: # needs sage.rings.polynomial.pbori
2042
+ sage: sr = mq.SR(1, 1, 1, 4, gf2=True, polybori=True)
2043
+ sage: while True: # workaround (see :issue:`31891`)
2044
+ ....: try:
2045
+ ....: F, s = sr.polynomial_system()
2046
+ ....: break
2047
+ ....: except ZeroDivisionError:
2048
+ ....: pass
2049
+ sage: g = F.reduced()
2050
+ sage: len(g) == len(set(gi.lt() for gi in g))
2051
+ True
2052
+ sage: for i in range(len(g)):
2053
+ ....: for j in range(len(g)):
2054
+ ....: if i == j:
2055
+ ....: continue
2056
+ ....: for t in list(g[j]):
2057
+ ....: assert g[i].lt() not in t.divisors()
2058
+ """
2059
+
2060
+ from sage.rings.polynomial.multi_polynomial_ring_base import \
2061
+ BooleanPolynomialRing_base
2062
+
2063
+ R = self.ring()
2064
+
2065
+ if isinstance(R, BooleanPolynomialRing_base):
2066
+ from sage.rings.polynomial.pbori.interred import \
2067
+ interred as inter_red
2068
+
2069
+ l = [p for p in self if not p == 0]
2070
+ l = sorted(inter_red(l, completely=True), reverse=True)
2071
+ return PolynomialSequence(l, R, immutable=True)
2072
+ else:
2073
+ return PolynomialSequence_generic.reduced(self)
2074
+
2075
+ def coefficients_monomials(self, order=None, sparse=True):
2076
+ """
2077
+ Return the matrix of coefficients ``A`` and
2078
+ the matching vector of monomials ``v``, such that ``A*v == vector(self)``.
2079
+
2080
+ Thus value of ``A[i,j]`` corresponds the coefficient of the
2081
+ monomial ``v[j]`` in the ``i``-th polynomial in this system.
2082
+
2083
+ Monomials are ordered w.r.t. the term ordering of ``order``
2084
+ if given; otherwise, they are ordered w.r.t. ``self.ring()``
2085
+ in reverse order, i.e., such that the smallest entry comes last.
2086
+
2087
+ INPUT:
2088
+
2089
+ - ``sparse`` -- construct a sparse matrix (default: ``True``)
2090
+ - ``order`` -- list or tuple specifying the order of monomials (default: ``None``)
2091
+
2092
+ EXAMPLES::
2093
+
2094
+ sage: # needs sage.rings.polynomial.pbori
2095
+ sage: B.<x,y,z> = BooleanPolynomialRing()
2096
+ sage: F = Sequence([x*y + y + 1, z + 1])
2097
+ sage: A, v = F.coefficients_monomials()
2098
+ sage: A
2099
+ [1 1 0 1]
2100
+ [0 0 1 1]
2101
+ sage: v
2102
+ (x*y, y, z, 1)
2103
+ sage: A*v
2104
+ (x*y + y + 1, z + 1)
2105
+
2106
+ TESTS:
2107
+
2108
+ Check that :issue:`37837` has been fixed::
2109
+
2110
+ sage: # needs sage.modules
2111
+ sage: R.<a,b,c> = PolynomialRing(GF(2), ['a', 'b', 'c'])
2112
+ sage: A, v = Sequence([a+b+c]).coefficients_monomials()
2113
+ sage: A
2114
+ [1 1 1]
2115
+ sage: v
2116
+ (a, b, c)
2117
+ sage: A*v
2118
+ (a + b + c)
2119
+ """
2120
+ from sage.modules.free_module_element import vector
2121
+ from sage.matrix.constructor import matrix
2122
+ from sage.rings.polynomial.multi_polynomial_ring_base import \
2123
+ BooleanPolynomialRing_base
2124
+
2125
+ if order is None:
2126
+ v = sorted(self.monomials(), reverse=True)
2127
+ else:
2128
+ if isinstance(order, (list, tuple)):
2129
+ v = order
2130
+ else:
2131
+ raise ValueError("order argument can only accept list or tuple")
2132
+
2133
+ R = self.ring()
2134
+ K = R.base_ring()
2135
+ y = dict(zip(v, range(len(v)))) # construct dictionary for fast lookups
2136
+ A = matrix(K, len(self), len(v), sparse=sparse)
2137
+
2138
+ if isinstance(R, BooleanPolynomialRing_base):
2139
+ one = K.one()
2140
+ for x, poly in enumerate(self):
2141
+ for m in poly:
2142
+ try:
2143
+ A[x, y[m]] = one
2144
+ except KeyError:
2145
+ raise ValueError("order argument does not contain all monomials")
2146
+ else:
2147
+ for x, poly in enumerate(self):
2148
+ for c, m in poly:
2149
+ try:
2150
+ A[x, y[m]] = c
2151
+ except KeyError:
2152
+ raise ValueError("order argument does not contain all monomials")
2153
+
2154
+ return A, vector(v)
2155
+
2156
+
2157
+ class PolynomialSequence_gf2e(PolynomialSequence_generic):
2158
+ r"""
2159
+ PolynomialSequence over `\GF{2^e}`, i.e extensions over
2160
+ `\GF(2)`.
2161
+ """
2162
+
2163
+ def weil_restriction(self):
2164
+ r"""
2165
+ Project this polynomial system to `\GF{2}`.
2166
+
2167
+ That is, compute the Weil restriction of scalars for the
2168
+ variety corresponding to this polynomial system and express it
2169
+ as a polynomial system over `\GF{2}`.
2170
+
2171
+ EXAMPLES::
2172
+
2173
+ sage: # needs sage.rings.finite_rings
2174
+ sage: k.<a> = GF(2^2)
2175
+ sage: P.<x,y> = PolynomialRing(k, 2)
2176
+ sage: a = P.base_ring().gen()
2177
+ sage: F = Sequence([x*y + 1, a*x + 1], P)
2178
+ sage: F2 = F.weil_restriction(); F2 # needs sage.libs.singular
2179
+ [x0*y0 + x1*y1 + 1, x1*y0 + x0*y1 + x1*y1, x1 + 1, x0 + x1, x0^2 + x0,
2180
+ x1^2 + x1, y0^2 + y0, y1^2 + y1]
2181
+
2182
+ Another bigger example for a small scale AES::
2183
+
2184
+ sage: # needs sage.rings.polynomial.pbori
2185
+ sage: sr = mq.SR(1, 1, 1, 4, gf2=False)
2186
+ sage: while True: # workaround (see :issue:`31891`)
2187
+ ....: try:
2188
+ ....: F, s = sr.polynomial_system()
2189
+ ....: break
2190
+ ....: except ZeroDivisionError:
2191
+ ....: pass
2192
+ sage: F
2193
+ Polynomial Sequence with 40 Polynomials in 20 Variables
2194
+ sage: F2 = F.weil_restriction(); F2 # needs sage.libs.singular
2195
+ Polynomial Sequence with 240 Polynomials in 80 Variables
2196
+ """
2197
+ from sage.rings.ideal import FieldIdeal
2198
+ J = self.ideal().weil_restriction()
2199
+ J += FieldIdeal(J.ring())
2200
+ return PolynomialSequence(J)
2201
+
2202
+
2203
+ register_unpickle_override("sage.crypto.mq.mpolynomialsystem", "MPolynomialSystem_generic", PolynomialSequence_generic)
2204
+ register_unpickle_override("sage.crypto.mq.mpolynomialsystem", "MPolynomialRoundSystem_generic", PolynomialSequence_generic)