passagemath-flint 10.6.1rc10__cp311-cp311-manylinux_2_27_aarch64.manylinux_2_28_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 (360) hide show
  1. passagemath_flint-10.6.1rc10.dist-info/METADATA +122 -0
  2. passagemath_flint-10.6.1rc10.dist-info/RECORD +360 -0
  3. passagemath_flint-10.6.1rc10.dist-info/WHEEL +6 -0
  4. passagemath_flint-10.6.1rc10.dist-info/top_level.txt +2 -0
  5. passagemath_flint.libs/libflint-3701249d.so.21.0.0 +0 -0
  6. passagemath_flint.libs/libgf2x-fbd36f80.so.3.0.0 +0 -0
  7. passagemath_flint.libs/libgfortran-8a9a71bc.so.5.0.0 +0 -0
  8. passagemath_flint.libs/libgmp-93ebf16a.so.10.5.0 +0 -0
  9. passagemath_flint.libs/libgsl-e3525837.so.28.0.0 +0 -0
  10. passagemath_flint.libs/libmpfi-ad12a86d.so.0.0.0 +0 -0
  11. passagemath_flint.libs/libmpfr-e0f11cf3.so.6.2.1 +0 -0
  12. passagemath_flint.libs/libntl-1004113e.so.44.0.1 +0 -0
  13. passagemath_flint.libs/libopenblasp-r0-4c5b64b1.3.29.so +0 -0
  14. sage/all__sagemath_flint.py +29 -0
  15. sage/combinat/all__sagemath_flint.py +1 -0
  16. sage/combinat/posets/all__sagemath_flint.py +1 -0
  17. sage/combinat/posets/hasse_cython_flint.cpython-311-aarch64-linux-gnu.so +0 -0
  18. sage/combinat/posets/hasse_cython_flint.pyx +194 -0
  19. sage/data_structures/all__sagemath_flint.py +1 -0
  20. sage/data_structures/bounded_integer_sequences.cpython-311-aarch64-linux-gnu.so +0 -0
  21. sage/data_structures/bounded_integer_sequences.pxd +62 -0
  22. sage/data_structures/bounded_integer_sequences.pyx +1418 -0
  23. sage/graphs/all__sagemath_flint.py +1 -0
  24. sage/graphs/chrompoly.cpython-311-aarch64-linux-gnu.so +0 -0
  25. sage/graphs/chrompoly.pyx +555 -0
  26. sage/graphs/matchpoly.cpython-311-aarch64-linux-gnu.so +0 -0
  27. sage/graphs/matchpoly.pyx +412 -0
  28. sage/libs/all__sagemath_flint.py +17 -0
  29. sage/libs/arb/__init__.py +1 -0
  30. sage/libs/arb/acb.pxd +154 -0
  31. sage/libs/arb/acb_calc.pxd +9 -0
  32. sage/libs/arb/acb_elliptic.pxd +25 -0
  33. sage/libs/arb/acb_hypgeom.pxd +74 -0
  34. sage/libs/arb/acb_mat.pxd +62 -0
  35. sage/libs/arb/acb_modular.pxd +17 -0
  36. sage/libs/arb/acb_poly.pxd +216 -0
  37. sage/libs/arb/arb.pxd +240 -0
  38. sage/libs/arb/arb_fmpz_poly.pxd +21 -0
  39. sage/libs/arb/arb_hypgeom.pxd +83 -0
  40. sage/libs/arb/arb_wrap.h +34 -0
  41. sage/libs/arb/arf.pxd +131 -0
  42. sage/libs/arb/arith.cpython-311-aarch64-linux-gnu.so +0 -0
  43. sage/libs/arb/arith.pyx +87 -0
  44. sage/libs/arb/bernoulli.pxd +6 -0
  45. sage/libs/arb/mag.pxd +77 -0
  46. sage/libs/arb/types.pxd +37 -0
  47. sage/libs/flint/__init__.py +1 -0
  48. sage/libs/flint/acb.pxd +270 -0
  49. sage/libs/flint/acb_calc.pxd +22 -0
  50. sage/libs/flint/acb_dft.pxd +51 -0
  51. sage/libs/flint/acb_dirichlet.pxd +112 -0
  52. sage/libs/flint/acb_elliptic.pxd +42 -0
  53. sage/libs/flint/acb_hypgeom.pxd +169 -0
  54. sage/libs/flint/acb_macros.pxd +9 -0
  55. sage/libs/flint/acb_mat.pxd +136 -0
  56. sage/libs/flint/acb_mat_macros.pxd +10 -0
  57. sage/libs/flint/acb_modular.pxd +62 -0
  58. sage/libs/flint/acb_poly.pxd +251 -0
  59. sage/libs/flint/acb_poly_macros.pxd +8 -0
  60. sage/libs/flint/acb_theta.pxd +124 -0
  61. sage/libs/flint/acf.pxd +32 -0
  62. sage/libs/flint/aprcl.pxd +84 -0
  63. sage/libs/flint/arb.pxd +382 -0
  64. sage/libs/flint/arb_calc.pxd +31 -0
  65. sage/libs/flint/arb_fmpz_poly.pxd +34 -0
  66. sage/libs/flint/arb_fpwrap.pxd +215 -0
  67. sage/libs/flint/arb_hypgeom.pxd +147 -0
  68. sage/libs/flint/arb_macros.pxd +9 -0
  69. sage/libs/flint/arb_mat.pxd +140 -0
  70. sage/libs/flint/arb_mat_macros.pxd +10 -0
  71. sage/libs/flint/arb_poly.pxd +237 -0
  72. sage/libs/flint/arf.pxd +167 -0
  73. sage/libs/flint/arith.cpython-311-aarch64-linux-gnu.so +0 -0
  74. sage/libs/flint/arith.pxd +76 -0
  75. sage/libs/flint/arith.pyx +77 -0
  76. sage/libs/flint/arith_sage.cpython-311-aarch64-linux-gnu.so +0 -0
  77. sage/libs/flint/arith_sage.pyx +308 -0
  78. sage/libs/flint/bernoulli.pxd +28 -0
  79. sage/libs/flint/bool_mat.pxd +52 -0
  80. sage/libs/flint/ca.pxd +203 -0
  81. sage/libs/flint/ca_ext.pxd +34 -0
  82. sage/libs/flint/ca_field.pxd +32 -0
  83. sage/libs/flint/ca_mat.pxd +117 -0
  84. sage/libs/flint/ca_poly.pxd +104 -0
  85. sage/libs/flint/ca_vec.pxd +46 -0
  86. sage/libs/flint/calcium.pxd +27 -0
  87. sage/libs/flint/d_mat.pxd +39 -0
  88. sage/libs/flint/d_vec.pxd +32 -0
  89. sage/libs/flint/dirichlet.pxd +57 -0
  90. sage/libs/flint/dlog.pxd +53 -0
  91. sage/libs/flint/double_extras.pxd +24 -0
  92. sage/libs/flint/double_interval.pxd +36 -0
  93. sage/libs/flint/fexpr.pxd +104 -0
  94. sage/libs/flint/fexpr_builtin.pxd +20 -0
  95. sage/libs/flint/fft.pxd +66 -0
  96. sage/libs/flint/flint.pxd +36 -0
  97. sage/libs/flint/flint_ntl_wrap.h +35 -0
  98. sage/libs/flint/flint_sage.cpython-311-aarch64-linux-gnu.so +0 -0
  99. sage/libs/flint/flint_sage.pyx +163 -0
  100. sage/libs/flint/flint_wrap.h +190 -0
  101. sage/libs/flint/fmpq.pxd +137 -0
  102. sage/libs/flint/fmpq_mat.pxd +105 -0
  103. sage/libs/flint/fmpq_mat_macros.pxd +10 -0
  104. sage/libs/flint/fmpq_mpoly.pxd +165 -0
  105. sage/libs/flint/fmpq_mpoly_factor.pxd +30 -0
  106. sage/libs/flint/fmpq_poly.pxd +241 -0
  107. sage/libs/flint/fmpq_poly_macros.pxd +9 -0
  108. sage/libs/flint/fmpq_poly_sage.cpython-311-aarch64-linux-gnu.so +0 -0
  109. sage/libs/flint/fmpq_poly_sage.pxd +31 -0
  110. sage/libs/flint/fmpq_poly_sage.pyx +48 -0
  111. sage/libs/flint/fmpq_vec.pxd +27 -0
  112. sage/libs/flint/fmpz.pxd +256 -0
  113. sage/libs/flint/fmpz_extras.pxd +32 -0
  114. sage/libs/flint/fmpz_factor.pxd +42 -0
  115. sage/libs/flint/fmpz_factor_sage.cpython-311-aarch64-linux-gnu.so +0 -0
  116. sage/libs/flint/fmpz_factor_sage.pxd +4 -0
  117. sage/libs/flint/fmpz_factor_sage.pyx +29 -0
  118. sage/libs/flint/fmpz_lll.pxd +49 -0
  119. sage/libs/flint/fmpz_macros.pxd +8 -0
  120. sage/libs/flint/fmpz_mat.pxd +184 -0
  121. sage/libs/flint/fmpz_mat_macros.pxd +10 -0
  122. sage/libs/flint/fmpz_mod.pxd +46 -0
  123. sage/libs/flint/fmpz_mod_mat.pxd +71 -0
  124. sage/libs/flint/fmpz_mod_mpoly.pxd +161 -0
  125. sage/libs/flint/fmpz_mod_mpoly_factor.pxd +28 -0
  126. sage/libs/flint/fmpz_mod_poly.pxd +249 -0
  127. sage/libs/flint/fmpz_mod_poly_factor.pxd +46 -0
  128. sage/libs/flint/fmpz_mod_vec.pxd +27 -0
  129. sage/libs/flint/fmpz_mpoly.pxd +224 -0
  130. sage/libs/flint/fmpz_mpoly_factor.pxd +29 -0
  131. sage/libs/flint/fmpz_mpoly_q.pxd +57 -0
  132. sage/libs/flint/fmpz_poly.cpython-311-aarch64-linux-gnu.so +0 -0
  133. sage/libs/flint/fmpz_poly.pxd +407 -0
  134. sage/libs/flint/fmpz_poly.pyx +19 -0
  135. sage/libs/flint/fmpz_poly_factor.pxd +33 -0
  136. sage/libs/flint/fmpz_poly_macros.pxd +8 -0
  137. sage/libs/flint/fmpz_poly_mat.pxd +71 -0
  138. sage/libs/flint/fmpz_poly_q.pxd +55 -0
  139. sage/libs/flint/fmpz_poly_sage.cpython-311-aarch64-linux-gnu.so +0 -0
  140. sage/libs/flint/fmpz_poly_sage.pxd +20 -0
  141. sage/libs/flint/fmpz_poly_sage.pyx +500 -0
  142. sage/libs/flint/fmpz_vec.pxd +80 -0
  143. sage/libs/flint/fmpzi.pxd +52 -0
  144. sage/libs/flint/fq.pxd +97 -0
  145. sage/libs/flint/fq_default.pxd +84 -0
  146. sage/libs/flint/fq_default_mat.pxd +70 -0
  147. sage/libs/flint/fq_default_poly.pxd +97 -0
  148. sage/libs/flint/fq_default_poly_factor.pxd +39 -0
  149. sage/libs/flint/fq_embed.pxd +28 -0
  150. sage/libs/flint/fq_mat.pxd +83 -0
  151. sage/libs/flint/fq_nmod.pxd +95 -0
  152. sage/libs/flint/fq_nmod_embed.pxd +28 -0
  153. sage/libs/flint/fq_nmod_mat.pxd +83 -0
  154. sage/libs/flint/fq_nmod_mpoly.pxd +130 -0
  155. sage/libs/flint/fq_nmod_mpoly_factor.pxd +28 -0
  156. sage/libs/flint/fq_nmod_poly.pxd +202 -0
  157. sage/libs/flint/fq_nmod_poly_factor.pxd +47 -0
  158. sage/libs/flint/fq_nmod_vec.pxd +33 -0
  159. sage/libs/flint/fq_poly.pxd +204 -0
  160. sage/libs/flint/fq_poly_factor.pxd +47 -0
  161. sage/libs/flint/fq_vec.pxd +33 -0
  162. sage/libs/flint/fq_zech.pxd +99 -0
  163. sage/libs/flint/fq_zech_embed.pxd +28 -0
  164. sage/libs/flint/fq_zech_mat.pxd +78 -0
  165. sage/libs/flint/fq_zech_poly.pxd +198 -0
  166. sage/libs/flint/fq_zech_poly_factor.pxd +47 -0
  167. sage/libs/flint/fq_zech_vec.pxd +33 -0
  168. sage/libs/flint/gr.pxd +174 -0
  169. sage/libs/flint/gr_generic.pxd +215 -0
  170. sage/libs/flint/gr_mat.pxd +161 -0
  171. sage/libs/flint/gr_mpoly.pxd +68 -0
  172. sage/libs/flint/gr_poly.pxd +276 -0
  173. sage/libs/flint/gr_special.pxd +237 -0
  174. sage/libs/flint/gr_vec.pxd +120 -0
  175. sage/libs/flint/hypgeom.pxd +24 -0
  176. sage/libs/flint/long_extras.pxd +23 -0
  177. sage/libs/flint/mag.pxd +131 -0
  178. sage/libs/flint/mag_macros.pxd +8 -0
  179. sage/libs/flint/mpf_mat.pxd +36 -0
  180. sage/libs/flint/mpf_vec.pxd +34 -0
  181. sage/libs/flint/mpfr_mat.pxd +27 -0
  182. sage/libs/flint/mpfr_vec.pxd +25 -0
  183. sage/libs/flint/mpn_extras.pxd +41 -0
  184. sage/libs/flint/mpoly.pxd +72 -0
  185. sage/libs/flint/nf.pxd +19 -0
  186. sage/libs/flint/nf_elem.pxd +74 -0
  187. sage/libs/flint/nmod.pxd +35 -0
  188. sage/libs/flint/nmod_mat.pxd +104 -0
  189. sage/libs/flint/nmod_mpoly.pxd +144 -0
  190. sage/libs/flint/nmod_mpoly_factor.pxd +28 -0
  191. sage/libs/flint/nmod_poly.pxd +339 -0
  192. sage/libs/flint/nmod_poly_factor.pxd +44 -0
  193. sage/libs/flint/nmod_poly_linkage.pxi +710 -0
  194. sage/libs/flint/nmod_poly_mat.pxd +76 -0
  195. sage/libs/flint/nmod_vec.pxd +40 -0
  196. sage/libs/flint/ntl_interface.pxd +17 -0
  197. sage/libs/flint/padic.pxd +93 -0
  198. sage/libs/flint/padic_mat.pxd +64 -0
  199. sage/libs/flint/padic_poly.pxd +88 -0
  200. sage/libs/flint/partitions.pxd +23 -0
  201. sage/libs/flint/perm.pxd +26 -0
  202. sage/libs/flint/profiler.pxd +24 -0
  203. sage/libs/flint/qadic.pxd +77 -0
  204. sage/libs/flint/qfb.pxd +44 -0
  205. sage/libs/flint/qqbar.pxd +172 -0
  206. sage/libs/flint/qsieve.cpython-311-aarch64-linux-gnu.so +0 -0
  207. sage/libs/flint/qsieve.pxd +41 -0
  208. sage/libs/flint/qsieve.pyx +21 -0
  209. sage/libs/flint/qsieve_sage.cpython-311-aarch64-linux-gnu.so +0 -0
  210. sage/libs/flint/qsieve_sage.pyx +67 -0
  211. sage/libs/flint/thread_pool.pxd +25 -0
  212. sage/libs/flint/types.pxd +2076 -0
  213. sage/libs/flint/ulong_extras.cpython-311-aarch64-linux-gnu.so +0 -0
  214. sage/libs/flint/ulong_extras.pxd +141 -0
  215. sage/libs/flint/ulong_extras.pyx +21 -0
  216. sage/libs/flint/ulong_extras_sage.cpython-311-aarch64-linux-gnu.so +0 -0
  217. sage/libs/flint/ulong_extras_sage.pyx +21 -0
  218. sage/matrix/all__sagemath_flint.py +1 -0
  219. sage/matrix/change_ring.cpython-311-aarch64-linux-gnu.so +0 -0
  220. sage/matrix/change_ring.pyx +43 -0
  221. sage/matrix/matrix_complex_ball_dense.cpython-311-aarch64-linux-gnu.so +0 -0
  222. sage/matrix/matrix_complex_ball_dense.pxd +14 -0
  223. sage/matrix/matrix_complex_ball_dense.pyx +973 -0
  224. sage/matrix/matrix_cyclo_dense.cpython-311-aarch64-linux-gnu.so +0 -0
  225. sage/matrix/matrix_cyclo_dense.pxd +16 -0
  226. sage/matrix/matrix_cyclo_dense.pyx +1761 -0
  227. sage/matrix/matrix_integer_dense.cpython-311-aarch64-linux-gnu.so +0 -0
  228. sage/matrix/matrix_integer_dense.pxd +32 -0
  229. sage/matrix/matrix_integer_dense.pyx +5801 -0
  230. sage/matrix/matrix_integer_dense_hnf.py +1294 -0
  231. sage/matrix/matrix_integer_dense_saturation.py +346 -0
  232. sage/matrix/matrix_integer_sparse.cpython-311-aarch64-linux-gnu.so +0 -0
  233. sage/matrix/matrix_integer_sparse.pxd +9 -0
  234. sage/matrix/matrix_integer_sparse.pyx +1090 -0
  235. sage/matrix/matrix_rational_dense.cpython-311-aarch64-linux-gnu.so +0 -0
  236. sage/matrix/matrix_rational_dense.pxd +23 -0
  237. sage/matrix/matrix_rational_dense.pyx +2995 -0
  238. sage/matrix/matrix_rational_sparse.cpython-311-aarch64-linux-gnu.so +0 -0
  239. sage/matrix/matrix_rational_sparse.pxd +11 -0
  240. sage/matrix/matrix_rational_sparse.pyx +789 -0
  241. sage/matrix/misc_flint.cpython-311-aarch64-linux-gnu.so +0 -0
  242. sage/matrix/misc_flint.pyx +109 -0
  243. sage/modular/all__sagemath_flint.py +1 -0
  244. sage/modular/modform/all__sagemath_flint.py +1 -0
  245. sage/modular/modform/eis_series_cython.cpython-311-aarch64-linux-gnu.so +0 -0
  246. sage/modular/modform/eis_series_cython.pyx +226 -0
  247. sage/modular/modsym/all__sagemath_flint.py +1 -0
  248. sage/modular/modsym/apply.cpython-311-aarch64-linux-gnu.so +0 -0
  249. sage/modular/modsym/apply.pxd +6 -0
  250. sage/modular/modsym/apply.pyx +113 -0
  251. sage/modular/modsym/heilbronn.cpython-311-aarch64-linux-gnu.so +0 -0
  252. sage/modular/modsym/heilbronn.pyx +966 -0
  253. sage/modular/pollack_stevens/all__sagemath_flint.py +1 -0
  254. sage/modular/pollack_stevens/dist.cpython-311-aarch64-linux-gnu.so +0 -0
  255. sage/modular/pollack_stevens/dist.pxd +38 -0
  256. sage/modular/pollack_stevens/dist.pyx +1439 -0
  257. sage/quivers/algebra.py +691 -0
  258. sage/quivers/algebra_elements.cpython-311-aarch64-linux-gnu.so +0 -0
  259. sage/quivers/algebra_elements.pxd +97 -0
  260. sage/quivers/algebra_elements.pxi +1324 -0
  261. sage/quivers/algebra_elements.pyx +1424 -0
  262. sage/quivers/all.py +1 -0
  263. sage/quivers/ar_quiver.py +917 -0
  264. sage/quivers/homspace.py +640 -0
  265. sage/quivers/morphism.py +1282 -0
  266. sage/quivers/path_semigroup.py +1155 -0
  267. sage/quivers/paths.cpython-311-aarch64-linux-gnu.so +0 -0
  268. sage/quivers/paths.pxd +13 -0
  269. sage/quivers/paths.pyx +809 -0
  270. sage/quivers/representation.py +2975 -0
  271. sage/rings/all__sagemath_flint.py +37 -0
  272. sage/rings/cif.py +4 -0
  273. sage/rings/complex_arb.cpython-311-aarch64-linux-gnu.so +0 -0
  274. sage/rings/complex_arb.pxd +29 -0
  275. sage/rings/complex_arb.pyx +5176 -0
  276. sage/rings/complex_interval.cpython-311-aarch64-linux-gnu.so +0 -0
  277. sage/rings/complex_interval.pxd +30 -0
  278. sage/rings/complex_interval.pyx +2475 -0
  279. sage/rings/complex_interval_field.py +711 -0
  280. sage/rings/convert/all.py +1 -0
  281. sage/rings/convert/mpfi.cpython-311-aarch64-linux-gnu.so +0 -0
  282. sage/rings/convert/mpfi.pxd +6 -0
  283. sage/rings/convert/mpfi.pyx +576 -0
  284. sage/rings/factorint_flint.cpython-311-aarch64-linux-gnu.so +0 -0
  285. sage/rings/factorint_flint.pyx +99 -0
  286. sage/rings/fraction_field_FpT.cpython-311-aarch64-linux-gnu.so +0 -0
  287. sage/rings/fraction_field_FpT.pxd +28 -0
  288. sage/rings/fraction_field_FpT.pyx +2043 -0
  289. sage/rings/imaginary_unit.py +5 -0
  290. sage/rings/monomials.py +73 -0
  291. sage/rings/number_field/S_unit_solver.py +2870 -0
  292. sage/rings/number_field/all__sagemath_flint.py +7 -0
  293. sage/rings/number_field/bdd_height.py +664 -0
  294. sage/rings/number_field/class_group.py +762 -0
  295. sage/rings/number_field/galois_group.py +1307 -0
  296. sage/rings/number_field/homset.py +612 -0
  297. sage/rings/number_field/maps.py +687 -0
  298. sage/rings/number_field/morphism.py +272 -0
  299. sage/rings/number_field/number_field.py +12820 -0
  300. sage/rings/number_field/number_field_element.cpython-311-aarch64-linux-gnu.so +0 -0
  301. sage/rings/number_field/number_field_element.pxd +59 -0
  302. sage/rings/number_field/number_field_element.pyx +5735 -0
  303. sage/rings/number_field/number_field_element_quadratic.cpython-311-aarch64-linux-gnu.so +0 -0
  304. sage/rings/number_field/number_field_element_quadratic.pxd +34 -0
  305. sage/rings/number_field/number_field_element_quadratic.pyx +3185 -0
  306. sage/rings/number_field/number_field_ideal_rel.py +925 -0
  307. sage/rings/number_field/number_field_morphisms.cpython-311-aarch64-linux-gnu.so +0 -0
  308. sage/rings/number_field/number_field_morphisms.pyx +781 -0
  309. sage/rings/number_field/number_field_rel.py +2734 -0
  310. sage/rings/number_field/order.py +2981 -0
  311. sage/rings/number_field/order_ideal.py +804 -0
  312. sage/rings/number_field/selmer_group.py +715 -0
  313. sage/rings/number_field/small_primes_of_degree_one.py +242 -0
  314. sage/rings/number_field/splitting_field.py +606 -0
  315. sage/rings/number_field/structure.py +380 -0
  316. sage/rings/number_field/unit_group.py +721 -0
  317. sage/rings/padics/all__sagemath_flint.py +3 -0
  318. sage/rings/polynomial/all__sagemath_flint.py +1 -0
  319. sage/rings/polynomial/complex_roots.py +312 -0
  320. sage/rings/polynomial/evaluation_flint.cpython-311-aarch64-linux-gnu.so +0 -0
  321. sage/rings/polynomial/evaluation_flint.pxd +7 -0
  322. sage/rings/polynomial/evaluation_flint.pyx +68 -0
  323. sage/rings/polynomial/hilbert.cpython-311-aarch64-linux-gnu.so +0 -0
  324. sage/rings/polynomial/hilbert.pyx +602 -0
  325. sage/rings/polynomial/polynomial_complex_arb.cpython-311-aarch64-linux-gnu.so +0 -0
  326. sage/rings/polynomial/polynomial_complex_arb.pxd +7 -0
  327. sage/rings/polynomial/polynomial_complex_arb.pyx +963 -0
  328. sage/rings/polynomial/polynomial_integer_dense_flint.cpython-311-aarch64-linux-gnu.so +0 -0
  329. sage/rings/polynomial/polynomial_integer_dense_flint.pxd +13 -0
  330. sage/rings/polynomial/polynomial_integer_dense_flint.pyx +1881 -0
  331. sage/rings/polynomial/polynomial_number_field.cpython-311-aarch64-linux-gnu.so +0 -0
  332. sage/rings/polynomial/polynomial_number_field.pyx +345 -0
  333. sage/rings/polynomial/polynomial_rational_flint.cpython-311-aarch64-linux-gnu.so +0 -0
  334. sage/rings/polynomial/polynomial_rational_flint.pxd +20 -0
  335. sage/rings/polynomial/polynomial_rational_flint.pyx +2598 -0
  336. sage/rings/polynomial/polynomial_zmod_flint.cpython-311-aarch64-linux-gnu.so +0 -0
  337. sage/rings/polynomial/polynomial_zmod_flint.pxd +20 -0
  338. sage/rings/polynomial/polynomial_zmod_flint.pyx +1063 -0
  339. sage/rings/polynomial/real_roots.cpython-311-aarch64-linux-gnu.so +0 -0
  340. sage/rings/polynomial/real_roots.pxd +81 -0
  341. sage/rings/polynomial/real_roots.pyx +4704 -0
  342. sage/rings/polynomial/refine_root.cpython-311-aarch64-linux-gnu.so +0 -0
  343. sage/rings/polynomial/refine_root.pyx +142 -0
  344. sage/rings/polynomial/weil/all.py +4 -0
  345. sage/rings/polynomial/weil/power_sums.h +46 -0
  346. sage/rings/polynomial/weil/weil_polynomials.cpython-311-aarch64-linux-gnu.so +0 -0
  347. sage/rings/polynomial/weil/weil_polynomials.pyx +596 -0
  348. sage/rings/qqbar.py +9025 -0
  349. sage/rings/real_arb.cpython-311-aarch64-linux-gnu.so +0 -0
  350. sage/rings/real_arb.pxd +21 -0
  351. sage/rings/real_arb.pyx +4065 -0
  352. sage/rings/real_interval_absolute.cpython-311-aarch64-linux-gnu.so +0 -0
  353. sage/rings/real_interval_absolute.pyx +1073 -0
  354. sage/rings/real_mpfi.cpython-311-aarch64-linux-gnu.so +0 -0
  355. sage/rings/real_mpfi.pyx +5428 -0
  356. sage/schemes/all__sagemath_flint.py +1 -0
  357. sage/schemes/elliptic_curves/all__sagemath_flint.py +1 -0
  358. sage/schemes/elliptic_curves/descent_two_isogeny.cpython-311-aarch64-linux-gnu.so +0 -0
  359. sage/schemes/elliptic_curves/descent_two_isogeny.pyx +1387 -0
  360. sage/schemes/elliptic_curves/descent_two_isogeny_pari.pxd +5 -0
@@ -0,0 +1,1282 @@
1
+ # sage_setup: distribution = sagemath-flint
2
+ # sage.doctest: needs sage.graphs sage.modules
3
+ """
4
+ Quiver Morphisms
5
+ """
6
+
7
+ # ****************************************************************************
8
+ # Copyright (C) 2012 Jim Stark <jstarx@gmail.com>
9
+ # 2013 Simon King <simon.king@uni-jena.de>
10
+ #
11
+ # Distributed under the terms of the GNU General Public License (GPL)
12
+ #
13
+ # This code is distributed in the hope that it will be useful,
14
+ # but WITHOUT ANY WARRANTY; without even the implied warranty
15
+ # of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
16
+ #
17
+ # See the GNU General Public License for more details; the full text
18
+ # is available at:
19
+ #
20
+ # https://www.gnu.org/licenses/
21
+ # ****************************************************************************
22
+
23
+ from sage.categories.morphism import CallMorphism
24
+ from sage.matrix.constructor import Matrix
25
+
26
+
27
+ class QuiverRepHom(CallMorphism):
28
+ r"""
29
+ A homomorphism of quiver representations (of one and the same quiver)
30
+ is given by specifying, for each vertex of the quiver, a homomorphism
31
+ of the spaces assigned to this vertex such that these homomorphisms
32
+ commute with the edge maps. The domain and codomain of the
33
+ homomorphism are required to be representations of the same quiver
34
+ over the same base ring.
35
+
36
+ INPUT:
37
+
38
+ - ``domain`` -- :class:`QuiverRep`, the domain of the homomorphism
39
+
40
+ - ``codomain`` -- :class:`QuiverRep`, the codomain of the homomorphism
41
+
42
+ - ``data`` -- dict, list, or :class:`QuiverRepElement`
43
+ (default: empty dict),
44
+ with the following meaning:
45
+
46
+ - list: ``data`` can be a list of images for the generators of
47
+ the domain. "Generators" means the output of the ``gens()``
48
+ method. An error will be generated if the map so defined
49
+ is not equivariant with respect to the action of the quiver.
50
+ - dictionary: ``data`` can be a dictionary associating to each
51
+ vertex of the quiver either a homomorphism with domain and
52
+ codomain the spaces associated to this vertex in the domain
53
+ and codomain modules respectively, or a matrix defining such
54
+ a homomorphism, or an object that sage can construct such a
55
+ matrix from. Not all vertices must be specified, unspecified
56
+ vertices are assigned the zero map, and keys not corresponding
57
+ to vertices of the quiver are ignored. An error will be
58
+ generated if these maps do not commute with the edge maps of
59
+ the domain and codomain.
60
+ - :class:`QuiverRepElement`: if the domain is a
61
+ :class:`QuiverRep_with_path_basis` then ``data`` can be a single
62
+ :class:`QuiverRepElement` belonging to the codomain. The map is
63
+ then defined by sending each path, ``p``, in the basis to ``data*p``.
64
+ If ``data`` is not an element of the codomain or the domain is not a
65
+ :class:`QuiverRep_with_path_basis` then an error will be generated.
66
+ - :class:`QuiverRepHom`: the input can also be a map `f : D \to C` such
67
+ that there is a coercion from the domain of ``self`` to ``D``
68
+ and from ``C`` to the codomain of ``self``. The composition
69
+ of these maps is the result.
70
+
71
+ OUTPUT: :class:`QuiverRepHom`
72
+
73
+ EXAMPLES::
74
+
75
+ sage: Q = DiGraph({1:{2:['a', 'b']}, 2:{3:['c']}}).path_semigroup()
76
+ sage: spaces = {1: QQ^2, 2: QQ^2, 3:QQ^1}
77
+ sage: maps = {(1, 2, 'a'): [[1, 0], [0, 0]], (1, 2, 'b'): [[0, 0], [0, 1]], (2, 3, 'c'): [[1], [1]]}
78
+ sage: M = Q.representation(QQ, spaces, maps)
79
+ sage: spaces2 = {2: QQ^1, 3: QQ^1}
80
+ sage: S = Q.representation(QQ, spaces2)
81
+
82
+ With no additional data this creates the zero map::
83
+
84
+ sage: f = S.hom(M)
85
+ sage: f.is_zero()
86
+ True
87
+
88
+ We must specify maps at the vertices to get a nonzero homomorphism.
89
+ Note that if the dimensions of the spaces assigned to the domain and
90
+ codomain of a vertex are equal then Sage will construct the identity
91
+ matrix from ``1``::
92
+
93
+ sage: maps2 = {2:[1, -1], 3:1}
94
+ sage: g = S.hom(maps2, M)
95
+
96
+ Here we create the same map by specifying images for the generators::
97
+
98
+ sage: x = M({2: (1, -1)})
99
+ sage: y = M({3: (1,)})
100
+ sage: h = S.hom([x, y], M)
101
+ sage: g == h
102
+ True
103
+
104
+ If the domain is a module of type QuiverRep_with_path_basis (for example,
105
+ the indecomposable projectives) we can create maps by specifying a single
106
+ image::
107
+
108
+ sage: Proj = Q.P(GF(7), 3)
109
+ sage: Simp = Q.S(GF(7), 3)
110
+ sage: im = Simp({3: (1,)})
111
+ sage: Proj.hom(im, Simp).is_surjective()
112
+ True
113
+ """
114
+
115
+ ###########################################################################
116
+ # #
117
+ # PRIVATE FUNCTIONS #
118
+ # These functions are not meant to be seen by the end user. #
119
+ # #
120
+ ###########################################################################
121
+
122
+ def __init__(self, domain, codomain, data={}):
123
+ """
124
+ Initialize ``self``. Type ``QuiverRepHom?`` for more information.
125
+
126
+ TESTS::
127
+
128
+ sage: Q = DiGraph({1:{2:['a', 'b']}, 2:{3:['c']}}).path_semigroup()
129
+ sage: spaces = {1: QQ^2, 2: QQ^2, 3:QQ^1}
130
+ sage: maps = {(1, 2, 'a'): [[1, 0], [0, 0]], (1, 2, 'b'): [[0, 0], [0, 1]], (2, 3, 'c'): [[1], [1]]}
131
+ sage: M = Q.representation(QQ, spaces, maps)
132
+ sage: spaces2 = {2: QQ^1, 3: QQ^1}
133
+ sage: S = Q.representation(QQ, spaces2)
134
+ sage: f = S.hom(M)
135
+ sage: f.is_zero()
136
+ True
137
+ sage: maps2 = {2:[1, -1], 3:1}
138
+ sage: g = S.hom(maps2, M)
139
+ sage: x = M({2: (1, -1)})
140
+ sage: y = M({3: (1,)})
141
+ sage: h = S.hom([x, y], M)
142
+ sage: g == h
143
+ True
144
+ sage: Proj = Q.P(GF(7), 3)
145
+ sage: Simp = Q.S(GF(7), 3)
146
+ sage: im = Simp({3: (1,)})
147
+ sage: Proj.hom(im, Simp).is_surjective()
148
+ True
149
+
150
+ ::
151
+
152
+ sage: Q = DiGraph({1:{2:['a']}}).path_semigroup()
153
+ sage: H1 = Q.P(GF(3), 2).Hom(Q.S(GF(3), 2))
154
+ sage: H2 = Q.P(GF(3), 2).Hom(Q.S(GF(3), 1))
155
+ sage: H1.an_element() in H1 # indirect doctest
156
+ True
157
+ """
158
+ # The data of a representation is held in the following private
159
+ # variables:
160
+ #
161
+ # * _quiver
162
+ # The quiver of the representation.
163
+ # * _base_ring
164
+ # The base ring of the representation.
165
+ # * _domain
166
+ # The QuiverRep object that is the domain of the homomorphism.
167
+ # * _codomain
168
+ # The QuiverRep object that is the codomain of the homomorphism.
169
+ # * _vector
170
+ # A vector in some free module over the base ring of a length such
171
+ # that each coordinate corresponds to an entry in the matrix of a
172
+ # homomorphism attached to a vertex.
173
+ #
174
+ # The variable data can also be a vector of appropriate length. When
175
+ # this is the case it will be loaded directly into _vector and then
176
+ # _assert_valid_hom is called.
177
+
178
+ from sage.quivers.representation import (
179
+ QuiverRep_with_path_basis,
180
+ QuiverRepElement,
181
+ )
182
+
183
+ self._domain = domain
184
+ self._codomain = codomain
185
+ self._quiver = domain._quiver
186
+ self._base_ring = domain.base_ring()
187
+
188
+ # Check that the quiver and base ring match
189
+ if codomain._quiver != self._quiver:
190
+ raise ValueError("the quivers of the domain and codomain must be equal")
191
+ if codomain.base_ring() != self._base_ring:
192
+ raise ValueError("the base ring of the domain and codomain must be equal")
193
+
194
+ # Get the dimensions of the spaces
195
+ mat_dims = {}
196
+ domain_dims = {}
197
+ codomain_dims = {}
198
+ for v in self._quiver:
199
+ domain_dims[v] = domain._spaces[v].dimension()
200
+ codomain_dims[v] = codomain._spaces[v].dimension()
201
+ mat_dims[v] = domain_dims[v] * codomain_dims[v]
202
+ total_dim = sum(mat_dims.values())
203
+
204
+ # Handle the case when data is a vector
205
+ if data in self._base_ring**total_dim:
206
+ self._vector = data
207
+ self._assert_valid_hom()
208
+ super().__init__(domain.Hom(codomain))
209
+ return
210
+
211
+ # If data is not a dict, create one
212
+ if isinstance(data, dict):
213
+ maps_dict = data
214
+ else:
215
+ # If data is not a list create one, then create a dict from it
216
+ if isinstance(data, list):
217
+ im_list = data
218
+ # If data is a QuiverRepHom, create a list from it
219
+ elif isinstance(data, QuiverRepHom):
220
+ f = data._domain.coerce_map_from(domain)
221
+ g = self._codomain.coerce_map_from(data._codomain)
222
+ im_list = [g(data(f(x))) for x in domain.gens()]
223
+
224
+ # The only case left is that data is a QuiverRepElement
225
+ else:
226
+ if not isinstance(data, QuiverRepElement):
227
+ raise TypeError("input data must be dictionary, list, "
228
+ "QuiverRepElement or vector")
229
+ if not isinstance(domain, QuiverRep_with_path_basis):
230
+ raise TypeError("if data is a QuiverRepElement then domain "
231
+ "must be a QuiverRep_with_path_basis.")
232
+ if data not in codomain:
233
+ raise ValueError("if data is a QuiverRepElement then it must "
234
+ "be an element of codomain")
235
+ im_list = [codomain.right_edge_action(data, p) for v in domain._quiver for p in domain._bases[v]]
236
+
237
+ # WARNING: This code assumes that the function QuiverRep.gens() returns
238
+ # the generators ordered first by vertex and then by the order of the
239
+ # gens() method of the space associated to that vertex. In particular
240
+ # this is the order that corresponds to how maps are represented via
241
+ # matrices
242
+
243
+ # Get the gens of the domain and check that im_list is the right length
244
+ dom_gens = domain.gens()
245
+ if len(im_list) != len(dom_gens):
246
+ raise ValueError(("domain is dimension {} but only {} images"
247
+ " were supplied").format(len(dom_gens), len(im_list)))
248
+
249
+ # Get the matrices of the maps
250
+ start_index = 0
251
+ maps_dict = {}
252
+ for v in self._quiver:
253
+ maps_dict[v] = []
254
+ dim = domain._spaces[v].dimension()
255
+ for i in range(start_index, start_index + dim):
256
+ if im_list[i].support() and im_list[i].support() != [v]:
257
+ # If the element does not have the correct
258
+ # support raise an error here, otherwise we
259
+ # might create a valid hom that does not map
260
+ # the generators to the supplied images
261
+ txt = "generator supported at vertex {} cannot"
262
+ txt += " map to element with support {}"
263
+ raise ValueError(txt.format(v, im_list[i].support()))
264
+ else:
265
+ # If the support works out add the images coordinates
266
+ # as a row of the matrix
267
+ maps_dict[v].append(codomain._spaces[v].coordinates(im_list[i]._elems[v]))
268
+
269
+ start_index += dim
270
+
271
+ # Get the coordinates of the vector
272
+ from sage.categories.map import Map
273
+ vector = []
274
+ for v in self._quiver:
275
+ if v in maps_dict:
276
+ if isinstance(maps_dict[v], Map):
277
+ try:
278
+ m = maps_dict[v].matrix()
279
+ except (AttributeError, ValueError):
280
+ gens_images = [codomain._spaces[v].coordinate_vector(maps_dict[v](x))
281
+ for x in domain._spaces[v].gens()]
282
+ m = Matrix(self._base_ring, domain_dims[v], codomain_dims[v], gens_images)
283
+ else:
284
+ m = Matrix(self._base_ring, domain_dims[v], codomain_dims[v], maps_dict[v])
285
+ else:
286
+ m = Matrix(self._base_ring, domain_dims[v], codomain_dims[v])
287
+ for i in range(domain_dims[v]):
288
+ vector += list(m[i])
289
+
290
+ # Wrap as a vector, check it, and return
291
+ self._vector = (self._base_ring**total_dim)(vector)
292
+ self._assert_valid_hom()
293
+ super().__init__(domain.Hom(codomain))
294
+
295
+ def _repr_(self):
296
+ """
297
+ Default string representation.
298
+
299
+ TESTS::
300
+
301
+ sage: Q = DiGraph({1:{2:['a', 'b']}, 2:{3:['c']}}).path_semigroup()
302
+ sage: spaces = {1: QQ^2, 2: QQ^2, 3:QQ^1}
303
+ sage: maps = {(1, 2, 'a'): [[1, 0], [0, 0]], (1, 2, 'b'): [[0, 0], [0, 1]], (2, 3, 'c'): [[1], [1]]}
304
+ sage: M = Q.representation(QQ, spaces, maps)
305
+ sage: spaces2 = {2: QQ^1, 3: QQ^1}
306
+ sage: S = Q.representation(QQ, spaces2)
307
+ sage: S.hom(M) # indirect doctest
308
+ Homomorphism of representations of Multi-digraph on 3 vertices
309
+ """
310
+ return "Homomorphism of representations of " + repr(self._quiver)
311
+
312
+ def _call_(self, x):
313
+ """
314
+ TESTS::
315
+
316
+ sage: Q = DiGraph({1:{2:['a', 'b']}, 2:{3:['c']}}).path_semigroup()
317
+ sage: spaces = {1: QQ^2, 2: QQ^2, 3:QQ^1}
318
+ sage: maps = {(1, 2, 'a'): [[1, 0], [0, 0]], (1, 2, 'b'): [[0, 0], [0, 1]], (2, 3, 'c'): [[1], [1]]}
319
+ sage: M = Q.representation(QQ, spaces, maps)
320
+ sage: spaces2 = {2: QQ^1, 3: QQ^1}
321
+ sage: S = Q.representation(QQ, spaces2)
322
+ sage: x = M({2: (1, -1)})
323
+ sage: y = M({3: (1,)})
324
+ sage: h = S.hom([x, y], M)
325
+ sage: h(S.gens()[0]) == x
326
+ True
327
+ sage: h(S.gens()[1]) == y
328
+ True
329
+
330
+ The following was an issue during work on :issue:`12630`::
331
+
332
+ sage: Q = DiGraph({1: {}}).path_semigroup()
333
+ sage: M = Q.I(GF(3), 1)
334
+ sage: m = M.an_element()
335
+ sage: R = M.quotient(M)
336
+ sage: R(m)
337
+ Element of quiver representation
338
+ """
339
+ from sage.quivers.representation import QuiverRepElement
340
+ # Check the input
341
+ if not isinstance(x, QuiverRepElement):
342
+ raise ValueError("QuiverRepHom can only be called on QuiverRepElement")
343
+
344
+ elements = {v: self.get_map(v)(x._elems[v]) for v in self._quiver}
345
+ return self._codomain(elements)
346
+
347
+ def __add__(left, right):
348
+ """
349
+ This function overloads the ``+`` operator.
350
+
351
+ TESTS::
352
+
353
+ sage: Q = DiGraph({1:{2:['a', 'b']}, 2:{3:['c']}}).path_semigroup()
354
+ sage: spaces = {1: QQ^2, 2: QQ^2, 3:QQ^1}
355
+ sage: maps = {(1, 2, 'a'): [[1, 0], [0, 0]], (1, 2, 'b'): [[0, 0], [0, 1]], (2, 3, 'c'): [[1], [1]]}
356
+ sage: M = Q.representation(QQ, spaces, maps)
357
+ sage: spaces2 = {2: QQ^1, 3: QQ^1}
358
+ sage: S = Q.representation(QQ, spaces2)
359
+ sage: x = M({2: (1, -1)})
360
+ sage: z = M.zero()
361
+ sage: h = S.hom([x, z], M)
362
+ sage: g = S.hom([z, z], M)
363
+ sage: f = g + h
364
+ sage: f(S.gens()[0]) == x
365
+ True
366
+ sage: f(S.gens()[1]) == z
367
+ True
368
+ """
369
+ new_vector = left._vector + right._vector
370
+ return left._domain.hom(new_vector, left._codomain)
371
+
372
+ def __iadd__(self, other):
373
+ """
374
+ This function overloads the ``+=`` operator.
375
+
376
+ TESTS::
377
+
378
+ sage: Q = DiGraph({1:{2:['a', 'b']}, 2:{3:['c']}}).path_semigroup()
379
+ sage: spaces = {1: QQ^2, 2: QQ^2, 3:QQ^1}
380
+ sage: maps = {(1, 2, 'a'): [[1, 0], [0, 0]], (1, 2, 'b'): [[0, 0], [0, 1]], (2, 3, 'c'): [[1], [1]]}
381
+ sage: M = Q.representation(QQ, spaces, maps)
382
+ sage: spaces2 = {2: QQ^1, 3: QQ^1}
383
+ sage: S = Q.representation(QQ, spaces2)
384
+ sage: x = M({2: (1, -1)})
385
+ sage: z = M.zero()
386
+ sage: h = S.hom([x, z], M)
387
+ sage: g = S.hom([z, z], M)
388
+ sage: g += h
389
+ sage: g(S.gens()[0]) == x
390
+ True
391
+ sage: g(S.gens()[1]) == z
392
+ True
393
+ """
394
+ self._vector += other._vector
395
+ return self
396
+
397
+ def __sub__(left, right):
398
+ """
399
+ This function overloads the ``-`` operator.
400
+
401
+ TESTS::
402
+
403
+ sage: Q = DiGraph({1:{2:['a', 'b']}, 2:{3:['c']}}).path_semigroup()
404
+ sage: spaces = {1: QQ^2, 2: QQ^2, 3:QQ^1}
405
+ sage: maps = {(1, 2, 'a'): [[1, 0], [0, 0]], (1, 2, 'b'): [[0, 0], [0, 1]], (2, 3, 'c'): [[1], [1]]}
406
+ sage: M = Q.representation(QQ, spaces, maps)
407
+ sage: spaces2 = {2: QQ^1, 3: QQ^1}
408
+ sage: S = Q.representation(QQ, spaces2)
409
+ sage: x = M({2: (1, -1)})
410
+ sage: y = M({3: (1,)})
411
+ sage: z = M.zero()
412
+ sage: h = S.hom([x, z], M)
413
+ sage: g = S.hom([z, y], M)
414
+ sage: f = h - g
415
+ sage: f(S.gens()[0]) == x
416
+ True
417
+ sage: f(S.gens()[1]) == -y
418
+ True
419
+ """
420
+ new_vector = left._vector - right._vector
421
+ return left._domain.hom(new_vector, left._codomain)
422
+
423
+ def __isub__(self, other):
424
+ """
425
+ This function overloads the ``-=`` operator.
426
+
427
+ TESTS::
428
+
429
+ sage: Q = DiGraph({1:{2:['a', 'b']}, 2:{3:['c']}}).path_semigroup()
430
+ sage: spaces = {1: QQ^2, 2: QQ^2, 3:QQ^1}
431
+ sage: maps = {(1, 2, 'a'): [[1, 0], [0, 0]], (1, 2, 'b'): [[0, 0], [0, 1]], (2, 3, 'c'): [[1], [1]]}
432
+ sage: M = Q.representation(QQ, spaces, maps)
433
+ sage: spaces2 = {2: QQ^1, 3: QQ^1}
434
+ sage: S = Q.representation(QQ, spaces2)
435
+ sage: x = M({2: (1, -1)})
436
+ sage: y = M({3: (1,)})
437
+ sage: z = M.zero()
438
+ sage: h = S.hom([x, z], M)
439
+ sage: g = S.hom([z, y], M)
440
+ sage: h -= g
441
+ sage: h(S.gens()[0]) == x
442
+ True
443
+ sage: h(S.gens()[1]) == -y
444
+ True
445
+ """
446
+ self._vector -= other._vector
447
+ return self
448
+
449
+ def __neg__(self):
450
+ """
451
+ This function overrides the unary ``-`` operator.
452
+
453
+ TESTS::
454
+
455
+ sage: Q = DiGraph({1:{2:['a', 'b']}, 2:{3:['c']}}).path_semigroup()
456
+ sage: spaces = {1: QQ^2, 2: QQ^2, 3:QQ^1}
457
+ sage: maps = {(1, 2, 'a'): [[1, 0], [0, 0]], (1, 2, 'b'): [[0, 0], [0, 1]], (2, 3, 'c'): [[1], [1]]}
458
+ sage: M = Q.representation(QQ, spaces, maps)
459
+ sage: spaces2 = {2: QQ^1, 3: QQ^1}
460
+ sage: S = Q.representation(QQ, spaces2)
461
+ sage: x = M({2: (1, -1)})
462
+ sage: y = M({3: (1,)})
463
+ sage: h = S.hom([x, y], M)
464
+ sage: g = -h
465
+ sage: g(S.gens()[0]) == -x
466
+ True
467
+ sage: g(S.gens()[1]) == -y
468
+ True
469
+ """
470
+ return self._domain.hom(-self._vector, self._codomain)
471
+
472
+ def __pos__(self):
473
+ """
474
+ This function overrides the unary ``+`` operator.
475
+
476
+ TESTS::
477
+
478
+ sage: Q = DiGraph({1:{2:['a', 'b']}, 2:{3:['c']}}).path_semigroup()
479
+ sage: spaces = {1: QQ^2, 2: QQ^2, 3:QQ^1}
480
+ sage: maps = {(1, 2, 'a'): [[1, 0], [0, 0]], (1, 2, 'b'): [[0, 0], [0, 1]], (2, 3, 'c'): [[1], [1]]}
481
+ sage: M = Q.representation(QQ, spaces, maps)
482
+ sage: spaces2 = {2: QQ^1, 3: QQ^1}
483
+ sage: S = Q.representation(QQ, spaces2)
484
+ sage: x = M({2: (1, -1)})
485
+ sage: y = M({3: (1,)})
486
+ sage: h = S.hom([x, y], M)
487
+ sage: g = +h
488
+ sage: g == h
489
+ True
490
+ """
491
+ return self
492
+
493
+ def __eq__(self, other):
494
+ """
495
+ This function overrides the ``==`` operator.
496
+
497
+ TESTS::
498
+
499
+ sage: Q = DiGraph({1:{2:['a', 'b']}, 2:{3:['c']}}).path_semigroup()
500
+ sage: spaces = {1: QQ^2, 2: QQ^2, 3:QQ^1}
501
+ sage: maps = {(1, 2, 'a'): [[1, 0], [0, 0]], (1, 2, 'b'): [[0, 0], [0, 1]], (2, 3, 'c'): [[1], [1]]}
502
+ sage: M = Q.representation(QQ, spaces, maps)
503
+ sage: spaces2 = {2: QQ^1, 3: QQ^1}
504
+ sage: S = Q.representation(QQ, spaces2)
505
+ sage: x = M({2: (1, -1)})
506
+ sage: y = M({3: (1,)})
507
+ sage: g = S.hom([x, y], M)
508
+ sage: h = S.hom([x, y], M)
509
+ sage: g == h
510
+ True
511
+ """
512
+ # A homomorphism can only be equal to another homomorphism between the
513
+ # same domain and codomain
514
+ if not isinstance(other, QuiverRepHom) or self._domain != other._domain or self._codomain != other._codomain:
515
+ return False
516
+
517
+ # If all that holds just check the vectors
518
+ return self._vector == other._vector
519
+
520
+ def __hash__(self):
521
+ """
522
+ Return the hash of ``self``.
523
+
524
+ EXAMPLES::
525
+
526
+ sage: Q = DiGraph({1:{2:['a', 'b']}, 2:{3:['c']}}).path_semigroup()
527
+ sage: spaces = {1: QQ^2, 2: QQ^2, 3:QQ^1}
528
+ sage: maps = {(1, 2, 'a'): [[1, 0], [0, 0]], (1, 2, 'b'): [[0, 0], [0, 1]], (2, 3, 'c'): [[1], [1]]}
529
+ sage: M = Q.representation(QQ, spaces, maps)
530
+ sage: spaces2 = {2: QQ^1, 3: QQ^1}
531
+ sage: S = Q.representation(QQ, spaces2)
532
+ sage: x = M({2: (1, -1)})
533
+ sage: y = M({3: (1,)})
534
+ sage: g = S.hom([x, y], M)
535
+ sage: H = hash(g)
536
+ """
537
+ return hash(tuple(self._vector))
538
+
539
+ def __ne__(self, other):
540
+ """
541
+ This function overrides the ``!=`` operator.
542
+
543
+ TESTS::
544
+
545
+ sage: Q = DiGraph({1:{2:['a', 'b']}, 2:{3:['c']}}).path_semigroup()
546
+ sage: spaces = {1: QQ^2, 2: QQ^2, 3:QQ^1}
547
+ sage: maps = {(1, 2, 'a'): [[1, 0], [0, 0]], (1, 2, 'b'): [[0, 0], [0, 1]], (2, 3, 'c'): [[1], [1]]}
548
+ sage: M = Q.representation(QQ, spaces, maps)
549
+ sage: spaces2 = {2: QQ^1, 3: QQ^1}
550
+ sage: S = Q.representation(QQ, spaces2)
551
+ sage: x = M({2: (1, -1)})
552
+ sage: y = M({3: (1,)})
553
+ sage: z = M.zero()
554
+ sage: g = S.hom([x, y], M)
555
+ sage: h = S.hom([x, z], M)
556
+ sage: g != h
557
+ True
558
+ """
559
+ # A homomorphism can only be equal to another homomorphism between the
560
+ # same domain and codomain
561
+ if not isinstance(other, QuiverRepHom) or self._domain != other._domain or self._codomain != other._codomain:
562
+ return True
563
+
564
+ # If all that holds just check the vectors
565
+ return self._vector != other._vector
566
+
567
+ def __bool__(self) -> bool:
568
+ """
569
+ Return whether ``self`` is the zero morphism.
570
+
571
+ EXAMPLES::
572
+
573
+ sage: Q = DiGraph({1:{2:['a', 'b']}, 2:{3:['c']}}).path_semigroup()
574
+ sage: spaces = {1: QQ^2, 2: QQ^2, 3:QQ^1}
575
+ sage: maps = {(1, 2, 'a'): [[1, 0], [0, 0]], (1, 2, 'b'): [[0, 0], [0, 1]], (2, 3, 'c'): [[1], [1]]}
576
+ sage: M = Q.representation(QQ, spaces, maps)
577
+ sage: spaces2 = {2: QQ^1, 3: QQ^1}
578
+ sage: S = Q.representation(QQ, spaces2)
579
+ sage: x = M({2: (1, -1)})
580
+ sage: y = M({3: (1,)})
581
+ sage: z = M.zero()
582
+ sage: g = S.hom([x, y], M)
583
+ sage: h = S.hom([z, z], M)
584
+ sage: bool(g)
585
+ True
586
+ sage: bool(h)
587
+ False
588
+ """
589
+ return any(self._vector)
590
+
591
+ def __mul__(self, other):
592
+ """
593
+ This function overrides the ``*`` operator.
594
+
595
+ TESTS::
596
+
597
+ sage: Q = DiGraph({1:{2:['a', 'b']}, 2:{3:['c']}}).path_semigroup()
598
+ sage: spaces2 = {2: QQ^1, 3: QQ^1}
599
+ sage: S = Q.representation(QQ, spaces2)
600
+ sage: x = S.gens()[0]
601
+ sage: y = S.gens()[1]
602
+ sage: g = S.hom([x, y], S)
603
+ sage: h = S.hom(S)
604
+ sage: (g*h).is_zero()
605
+ True
606
+ """
607
+ maps = {v: other.get_matrix(v) * self.get_matrix(v)
608
+ for v in self._quiver}
609
+ return other._domain.hom(maps, self._codomain)
610
+
611
+ ###########################################################################
612
+ # #
613
+ # WELL DEFINEDNESS FUNCTIONS #
614
+ # These functions test and assert well definedness of the #
615
+ # homomorphism. #
616
+ # #
617
+ ###########################################################################
618
+
619
+ def _assert_valid_hom(self):
620
+ """
621
+ Raise a :exc:`ValueError` if the homomorphism is not well defined.
622
+
623
+ Specifically it checks that the domain and codomains of the maps are
624
+ correct and that the edge diagrams commute.
625
+
626
+ EXAMPLES::
627
+
628
+ sage: Q = DiGraph({1:{2:['a', 'b']}, 2:{3:['c']}}).path_semigroup()
629
+ sage: spaces = {1: QQ^2, 2: QQ^2, 3:QQ^1}
630
+ sage: maps = {(1, 2, 'a'): [[1, 0], [0, 0]], (1, 2, 'b'): [[0, 0], [0, 1]], (2, 3, 'c'): [[1], [1]]}
631
+ sage: M = Q.representation(QQ, spaces, maps)
632
+ sage: spaces2 = {2: QQ^1, 3: QQ^1}
633
+ sage: S = Q.representation(QQ, spaces2)
634
+ sage: maps2 = {2:[1, -1], 3:1}
635
+ sage: g = S.hom(maps2, M) # indirect doctest
636
+ sage: f = S.hom(maps2, S) # indirect doctest
637
+ Traceback (most recent call last):
638
+ ...
639
+ TypeError: unable to convert {2: [1, -1], 3: 1} to an element of Dimension 2 QuiverHomSpace
640
+ """
641
+ # Check that the domain and codomains dimensions add correctly
642
+ totaldim = 0
643
+ for v in self._quiver:
644
+ totaldim += self._domain._spaces[v].dimension() * self._codomain._spaces[v].dimension()
645
+ if totaldim != len(self._vector):
646
+ raise ValueError("dimensions do not match domain and codomain")
647
+
648
+ # Check that the edge diagrams commute
649
+ for e in self._domain._semigroup._sorted_edges:
650
+ if self.get_matrix(e[0]) * self._codomain._maps[e].matrix() != self._domain._maps[e].matrix() * self.get_matrix(e[1]):
651
+ raise ValueError("the diagram of edge {} does not commute".format(e))
652
+
653
+ ###########################################################################
654
+ # #
655
+ # ACCESS FUNCTIONS #
656
+ # These functions are used to view the homomorphism data. #
657
+ # #
658
+ ###########################################################################
659
+
660
+ def domain(self):
661
+ """
662
+ Return the domain of the homomorphism.
663
+
664
+ OUTPUT: :class:`QuiverRep`; the domain
665
+
666
+ EXAMPLES::
667
+
668
+ sage: Q = DiGraph({1:{2:['a', 'b']}, 2:{3:['c']}}).path_semigroup()
669
+ sage: spaces = {1: QQ^2, 2: QQ^2, 3:QQ^1}
670
+ sage: maps = {(1, 2, 'a'): [[1, 0], [0, 0]], (1, 2, 'b'): [[0, 0], [0, 1]], (2, 3, 'c'): [[1], [1]]}
671
+ sage: M = Q.representation(QQ, spaces, maps)
672
+ sage: S = Q.representation(QQ)
673
+ sage: g = M.hom(S)
674
+ sage: g.domain() is M
675
+ True
676
+ """
677
+ return self._domain
678
+
679
+ def codomain(self):
680
+ """
681
+ Return the codomain of the homomorphism.
682
+
683
+ OUTPUT: :class:`QuiverRep`; the codomain
684
+
685
+ EXAMPLES::
686
+
687
+ sage: Q = DiGraph({1:{2:['a', 'b']}, 2:{3:['c']}}).path_semigroup()
688
+ sage: spaces = {1: QQ^2, 2: QQ^2, 3:QQ^1}
689
+ sage: maps = {(1, 2, 'a'): [[1, 0], [0, 0]], (1, 2, 'b'): [[0, 0], [0, 1]], (2, 3, 'c'): [[1], [1]]}
690
+ sage: M = Q.representation(QQ, spaces, maps)
691
+ sage: S = Q.representation(QQ)
692
+ sage: g = S.hom(M)
693
+ sage: g.codomain() is M
694
+ True
695
+ """
696
+ return self._codomain
697
+
698
+ def get_matrix(self, vertex):
699
+ """
700
+ Return the matrix of the homomorphism attached to vertex
701
+ ``vertex``.
702
+
703
+ INPUT:
704
+
705
+ - ``vertex`` -- integer; a vertex of the quiver
706
+
707
+ OUTPUT: the matrix representing the homomorphism associated to
708
+ the given vertex
709
+
710
+ EXAMPLES::
711
+
712
+ sage: Q = DiGraph({1:{2:['a', 'b']}, 2:{3:['c']}}).path_semigroup()
713
+ sage: I = Q.I(QQ, 3)
714
+ sage: M = I/I.radical()
715
+ sage: f = M.coerce_map_from(I)
716
+ sage: f.get_matrix(1)
717
+ [1 0]
718
+ [0 1]
719
+ """
720
+ # Get dimensions
721
+ startdim = 0
722
+ for v in self._quiver:
723
+ if v == vertex:
724
+ break
725
+ startdim += self._domain._spaces[v].dimension() * self._codomain._spaces[v].dimension()
726
+
727
+ rows = self._domain._spaces[vertex].dimension()
728
+ cols = self._codomain._spaces[vertex].dimension()
729
+
730
+ # Slice out the matrix and return
731
+ return Matrix(self._base_ring, rows, cols,
732
+ self._vector.list()[startdim:startdim + rows * cols])
733
+
734
+ def get_map(self, vertex):
735
+ """
736
+ Return the homomorphism at the given vertex ``vertex``.
737
+
738
+ INPUT:
739
+
740
+ - ``vertex`` -- integer; a vertex of the quiver
741
+
742
+ OUTPUT: the homomorphism associated to the given vertex
743
+
744
+ EXAMPLES::
745
+
746
+ sage: Q = DiGraph({1:{2:['a', 'b']}, 2:{3:['c']}}).path_semigroup()
747
+ sage: P = Q.P(QQ, 1)
748
+ sage: S = P/P.radical()
749
+ sage: f = S.coerce_map_from(P)
750
+ sage: f.get_map(1).is_bijective()
751
+ True
752
+ """
753
+ return self._domain._spaces[vertex].hom(self.get_matrix(vertex), self._codomain._spaces[vertex])
754
+
755
+ def quiver(self):
756
+ """
757
+ Return the quiver of the representations in the domain/codomain.
758
+
759
+ OUTPUT:
760
+
761
+ - :class:`DiGraph`, the quiver of the representations in the domain
762
+ and codomain
763
+
764
+ EXAMPLES::
765
+
766
+ sage: Q = DiGraph({1:{2:['a', 'b']}, 2:{3:['c']}}).path_semigroup()
767
+ sage: P = Q.P(QQ, 1)
768
+ sage: f = P.hom({1: 1, 2: 1, 3: 1}, P)
769
+ sage: f.quiver() is Q.quiver()
770
+ True
771
+ """
772
+ return self._quiver
773
+
774
+ def base_ring(self):
775
+ """
776
+ Return the base ring of the representation in the codomain.
777
+
778
+ OUTPUT: the base ring of the codomain
779
+
780
+ EXAMPLES::
781
+
782
+ sage: Q = DiGraph({1:{2:['a', 'b']}, 2:{3:['c']}}).path_semigroup()
783
+ sage: P = Q.P(QQ, 1)
784
+ sage: f = P.hom({1: 1, 2: 1, 3: 1}, P)
785
+ sage: f.base_ring() is QQ
786
+ True
787
+ """
788
+ return self._base_ring
789
+
790
+ ###########################################################################
791
+ # #
792
+ # DATA FUNCTIONS #
793
+ # These functions return data collected from the homomorphism. #
794
+ # #
795
+ ###########################################################################
796
+
797
+ def is_injective(self) -> bool:
798
+ """
799
+ Test whether the homomorphism is injective.
800
+
801
+ OUTPUT: boolean; ``True`` if the homomorphism is injective, ``False``
802
+ otherwise
803
+
804
+ EXAMPLES::
805
+
806
+ sage: Q = DiGraph({1:{2:['a', 'b']}, 2:{3:['c']}}).path_semigroup()
807
+ sage: P = Q.P(QQ, 1)
808
+ sage: f = P.hom({1: 1, 2: 1, 3: 1}, P)
809
+ sage: f.is_injective()
810
+ True
811
+ sage: g = P.hom(P)
812
+ sage: g.is_injective()
813
+ False
814
+ """
815
+ # The homomorphism is injective if and only if it is injective at every
816
+ # vertex
817
+ return not any(self.get_matrix(v).nullity() for v in self._quiver)
818
+
819
+ def is_surjective(self) -> bool:
820
+ """
821
+ Test whether the homomorphism is surjective.
822
+
823
+ OUTPUT: boolean; ``True`` if the homomorphism is surjective, ``False``
824
+ otherwise
825
+
826
+ EXAMPLES::
827
+
828
+ sage: Q = DiGraph({1:{2:['a', 'b']}, 2:{3:['c']}}).path_semigroup()
829
+ sage: P = Q.P(QQ, 1)
830
+ sage: f = P.hom({1: 1, 2: 1, 3: 1}, P)
831
+ sage: f.is_surjective()
832
+ True
833
+ sage: g = P.hom(P)
834
+ sage: g.is_surjective()
835
+ False
836
+ """
837
+ # The homomorphism is surjective if and only if it is surjective at
838
+ # every vertex
839
+ for v in self._quiver:
840
+ m = self.get_matrix(v)
841
+ if m.rank() != m.ncols():
842
+ return False
843
+
844
+ return True
845
+
846
+ def is_isomorphism(self) -> bool:
847
+ """
848
+ Test whether the homomorphism is an isomorphism.
849
+
850
+ OUTPUT: boolean; ``True`` if the homomorphism is bijective, ``False``
851
+ otherwise
852
+
853
+ EXAMPLES::
854
+
855
+ sage: Q = DiGraph({1:{2:['a', 'b']}, 2:{3:['c']}}).path_semigroup()
856
+ sage: P = Q.P(QQ, 1)
857
+ sage: f = P.hom({1: 1, 2: 1, 3: 1}, P)
858
+ sage: f.is_isomorphism()
859
+ True
860
+ sage: g = P.hom(P)
861
+ sage: g.is_isomorphism()
862
+ False
863
+ """
864
+ # It's an iso if and only if it's an iso at every vertex
865
+ return all(self.get_matrix(v).is_invertible() for v in self._quiver)
866
+
867
+ def is_zero(self) -> bool:
868
+ """
869
+ Test whether the homomorphism is the zero homomorphism.
870
+
871
+ OUTPUT: boolean; ``True`` if the homomorphism is zero, ``False``
872
+ otherwise
873
+
874
+ EXAMPLES::
875
+
876
+ sage: Q = DiGraph({1:{2:['a', 'b']}, 2:{3:['c']}}).path_semigroup()
877
+ sage: P = Q.P(QQ, 1)
878
+ sage: f = P.hom({1: 1, 2: 1, 3: 1}, P)
879
+ sage: f.is_zero()
880
+ False
881
+ sage: g = P.hom(P)
882
+ sage: g.is_zero()
883
+ True
884
+ """
885
+ # The homomorphism is zero if and only if it is zero at every vertex
886
+ return all(self.get_matrix(v).is_zero() for v in self._quiver)
887
+
888
+ def is_endomorphism(self) -> bool:
889
+ """
890
+ Test whether the homomorphism is an endomorphism.
891
+
892
+ OUTPUT: boolean; ``True`` if the domain equals the codomain, ``False``
893
+ otherwise
894
+
895
+ EXAMPLES::
896
+
897
+ sage: Q = DiGraph({1:{2:['a', 'b']}, 2:{3:['c']}}).path_semigroup()
898
+ sage: P = Q.P(QQ, 1)
899
+ sage: f = P.hom({1: 1, 2: 1, 3: 1}, P)
900
+ sage: f.is_endomorphism()
901
+ True
902
+ sage: S = P/P.radical()
903
+ sage: g = S.coerce_map_from(P)
904
+ sage: g.is_endomorphism()
905
+ False
906
+ """
907
+ return self._domain == self._codomain
908
+
909
+ def rank(self):
910
+ """
911
+ Return the rank of the homomorphism ``self`` (as a `k`-linear
912
+ map).
913
+
914
+ OUTPUT: integer; the rank
915
+
916
+ EXAMPLES::
917
+
918
+ sage: Q = DiGraph({1:{2:['a', 'b']}, 2:{3:['c']}}).path_semigroup()
919
+ sage: P = Q.P(QQ, 1)
920
+ sage: S = P/P.radical()
921
+ sage: f = S.coerce_map_from(P)
922
+ sage: assert(f.rank() == 1)
923
+ """
924
+ # The rank is the sum of the ranks at each vertex
925
+ return sum(self.get_matrix(v).rank() for v in self._quiver)
926
+
927
+ ###########################################################################
928
+ # #
929
+ # CONSTRUCTION FUNCTIONS #
930
+ # These functions create new homomorphisms, representations, and #
931
+ # elements from the given homomorphism. #
932
+ # #
933
+ ###########################################################################
934
+
935
+ def kernel(self):
936
+ """
937
+ Return the kernel of ``self``.
938
+
939
+ OUTPUT: :class:`QuiverRep`; the kernel
940
+
941
+ .. NOTE::
942
+
943
+ To get the inclusion map of the kernel, ``K``, into the
944
+ domain, ``D``, use ``D.coerce_map_from(K)``.
945
+
946
+ EXAMPLES::
947
+
948
+ sage: Q = DiGraph({1:{2:['a', 'b']}, 2:{3:['c']}}).path_semigroup()
949
+ sage: spaces = {1: QQ^2, 2: QQ^2, 3:QQ^1}
950
+ sage: maps = {(1, 2, 'a'): [[1, 0], [0, 0]], (1, 2, 'b'): [[0, 0], [0, 1]], (2, 3, 'c'): [[1], [1]]}
951
+ sage: M = Q.representation(QQ, spaces, maps)
952
+ sage: spaces2 = {2: QQ^2, 3: QQ^1}
953
+ sage: N = Q.representation(QQ, spaces2, {(2, 3, 'c'): [[1], [0]]})
954
+ sage: maps2 = {2:[[1, 0], [0, 0]], 3:1}
955
+ sage: g = N.hom(maps2, M)
956
+ sage: g.kernel().dimension_vector()
957
+ (0, 1, 0)
958
+ """
959
+ spaces = {v: self.get_map(v).kernel() for v in self._quiver}
960
+ return self._domain._submodule(spaces)
961
+
962
+ def image(self):
963
+ """
964
+ Return the image of ``self``.
965
+
966
+ OUTPUT: :class:`QuiverRep`; the image
967
+
968
+ .. NOTE::
969
+
970
+ To get the inclusion map of the image, ``I``, into the
971
+ codomain, ``C``, use ``C.coerce_map_from(I)``.
972
+
973
+ EXAMPLES::
974
+
975
+ sage: Q = DiGraph({1:{2:['a', 'b']}, 2:{3:['c']}}).path_semigroup()
976
+ sage: spaces = {1: QQ^2, 2: QQ^2, 3:QQ^1}
977
+ sage: maps = {(1, 2, 'a'): [[1, 0], [0, 0]], (1, 2, 'b'): [[0, 0], [0, 1]], (2, 3, 'c'): [[1], [1]]}
978
+ sage: M = Q.representation(QQ, spaces, maps)
979
+ sage: spaces2 = {2: QQ^2, 3: QQ^1}
980
+ sage: N = Q.representation(QQ, spaces2, {(2, 3, 'c'): [[1], [0]]})
981
+ sage: maps2 = {2:[[1, 0], [0, 0]], 3:1}
982
+ sage: g = N.hom(maps2, M)
983
+ sage: g.image().dimension_vector()
984
+ (0, 1, 1)
985
+ """
986
+ spaces = {v: self.get_map(v).image() for v in self._quiver}
987
+ return self._codomain._submodule(spaces)
988
+
989
+ def cokernel(self):
990
+ """
991
+ Return the cokernel of ``self``.
992
+
993
+ OUTPUT: :class:`QuiverRep`; the cokernel
994
+
995
+ .. NOTE::
996
+
997
+ To get the factor map of the codomain, ``D``, onto the
998
+ cokernel, ``C``, use ``C.coerce_map_from(D)``.
999
+
1000
+ EXAMPLES::
1001
+
1002
+ sage: Q = DiGraph({1:{2:['a', 'b']}, 2:{3:['c']}}).path_semigroup()
1003
+ sage: spaces = {1: QQ^2, 2: QQ^2, 3:QQ^1}
1004
+ sage: maps = {(1, 2, 'a'): [[1, 0], [0, 0]], (1, 2, 'b'): [[0, 0], [0, 1]], (2, 3, 'c'): [[1], [1]]}
1005
+ sage: M = Q.representation(QQ, spaces, maps)
1006
+ sage: spaces2 = {2: QQ^2, 3: QQ^1}
1007
+ sage: N = Q.representation(QQ, spaces2, {(2, 3, 'c'): [[1], [0]]})
1008
+ sage: maps2 = {2:[[1, 0], [0, 0]], 3:1}
1009
+ sage: g = N.hom(maps2, M)
1010
+ sage: g.cokernel().dimension_vector()
1011
+ (2, 1, 0)
1012
+ """
1013
+ return self._codomain.quotient(self.image())
1014
+
1015
+ def linear_dual(self):
1016
+ r"""
1017
+ Compute the linear dual `Df : DN \to DM` of
1018
+ ``self`` = `f : M \to N` where `D(-) = Hom_k(-, k)`.
1019
+
1020
+ OUTPUT: :class:`QuiverRepHom`; the map `Df : DN \to DM`
1021
+
1022
+ .. NOTE::
1023
+
1024
+ If `e` is an edge of the quiver `Q` and `g` is an element of
1025
+ `Hom_k(N, k)` then we let `(ga)(m) = g(ma)`. This gives
1026
+ `Hom_k(N, k)` its structure as a module over the opposite
1027
+ quiver ``Q.reverse()``. The map `Hom_k(N, k) \to Hom_k(M, k)`
1028
+ returned sends `g` to `gf`.
1029
+
1030
+ EXAMPLES::
1031
+
1032
+ sage: Q = DiGraph({1:{2:['a', 'b']}, 2:{3:['c']}}).path_semigroup()
1033
+ sage: P = Q.P(QQ, 1)
1034
+ sage: S = P/P.radical()
1035
+ sage: f = S.coerce_map_from(P)
1036
+
1037
+ The dual of a surjective map is injective and vice versa::
1038
+
1039
+ sage: f.is_surjective()
1040
+ True
1041
+ sage: g = f.linear_dual()
1042
+ sage: g.is_injective()
1043
+ True
1044
+
1045
+ The dual of a right module is a left module for the same quiver, Sage
1046
+ represents this as a right module for the opposite quiver::
1047
+
1048
+ sage: g.quiver().path_semigroup() is Q.reverse()
1049
+ True
1050
+
1051
+ The double dual of a map is the original representation::
1052
+
1053
+ sage: g.linear_dual() == f
1054
+ True
1055
+ """
1056
+ # The effect of the functor D is that it just transposes the matrix of
1057
+ # a hom
1058
+ maps = {v: self.get_matrix(v).transpose() for v in self._quiver}
1059
+ return self._codomain.linear_dual().hom(maps, self._domain.linear_dual())
1060
+
1061
+ def algebraic_dual(self):
1062
+ r"""
1063
+ Compute the algebraic dual `f^t : N^t \to M^t` of
1064
+ ``self`` = `f : M \to N` where `(-)^t = Hom_Q(-, kQ)`.
1065
+
1066
+ OUTPUT: :class:`QuiverRepHom`; the map `f^t : N^t \to M^t`
1067
+
1068
+ .. NOTE::
1069
+
1070
+ If `e` is an edge of the quiver `Q` and `g` is an element of
1071
+ `Hom_Q(N, kQ)` then we let `(ge)(m) = eg(m)`. This gives
1072
+ `Hom_Q(N, kQ)` its structure as a module over the opposite
1073
+ quiver ``Q.reverse()``. The map
1074
+ `Hom_Q(N, kQ) \to Hom_Q(M, kQ)` returned sends `g` to `gf`.
1075
+
1076
+ EXAMPLES::
1077
+
1078
+ sage: Q = DiGraph({1:{2:['a'], 3:['b','c','d']}, 2:{4:['e','f']}, 3:{4:['g']}, 5:{2:['h','i']}}).path_semigroup()
1079
+ sage: P1 = Q.P(QQ, 4)
1080
+ sage: P1.algebraic_dual()
1081
+ Representation with dimension vector (5, 2, 1, 1, 4)
1082
+
1083
+ The algebraic dual of an indecomposable projective is the indecomposable
1084
+ projective of the same vertex in the opposite quiver. ::
1085
+
1086
+ sage: Q.reverse().P(QQ, 4)
1087
+ Representation with dimension vector (5, 2, 1, 1, 4)
1088
+ """
1089
+ # Get the domain, its basis, and the codomain
1090
+ domain, domain_gens = self._codomain.algebraic_dual(True)
1091
+ codomain, co_domain_gens = self._domain.algebraic_dual(True)
1092
+
1093
+ # Find the images in the domain and create the module
1094
+ # H = QuiverHomSpace(self._domain, self._quiver.free_module(self._base_ring))
1095
+ im_gens = [codomain({v: (g * self)._vector})
1096
+ for v in self._quiver for g in domain_gens[v]]
1097
+ return domain.hom(im_gens, codomain)
1098
+
1099
+ def direct_sum(self, maps, return_maps=False, pinch=None):
1100
+ r"""
1101
+ Return the direct sum of ``self`` with the maps in the list ``maps``.
1102
+
1103
+ INPUT:
1104
+
1105
+ - ``maps`` -- :class:`QuiverRepHom` or list of :class:`QuiverRepHom`'s
1106
+
1107
+ - ``return_maps`` -- boolean (default: ``False``); if ``False``, then
1108
+ the return value is a :class:`QuiverRepHom` which is the direct sum
1109
+ of ``self`` with the :class:`QuiverRepHoms` in ``maps``.
1110
+ If ``True``, then the return value is a tuple of length either 3
1111
+ or 5. The first entry of the tuple is the QuiverRepHom giving
1112
+ the direct sum. If ``pinch`` is either ``None`` or
1113
+ ``'codomain'`` then the next two entries in the tuple are lists
1114
+ giving respectively the inclusion and the projection maps for
1115
+ the factors of the direct sum. Summands are ordered as given
1116
+ in maps with ``self`` as the zeroth summand. If ``pinch`` is
1117
+ either ``None`` or ``'domain'`` then the next two entries in the
1118
+ tuple are the inclusion and projection maps for the codomain.
1119
+ Thus if ``pinch`` is ``None`` then the tuple will have length 5.
1120
+ If ``pinch`` is either ``'domain'`` or ``'codomain'`` then the
1121
+ tuple will have length 3.
1122
+
1123
+ - ``pinch`` -- string or ``None`` (default: ``None``); if this is
1124
+ equal to ``'domain'``, then the domains of ``self`` and the
1125
+ given maps must be equal. The direct sum of `f: A \to B` and
1126
+ `g: A \to C` returned is then the map `A \to B \oplus C` defined
1127
+ by sending `x` to `(f(x), g(x))`. If ``pinch`` equals
1128
+ ``'codomain'``, then the codomains of ``self`` and the given
1129
+ maps must be equal. The direct sum of `f: A \to C` and
1130
+ `g: B \to C` returned is then the map `A \oplus B \to C` defined
1131
+ by sending `(x, y)` to `f(x) + g(y)`. Finally, if ``pinch`` is
1132
+ anything other than ``'domain'`` or ``'codomain'``, then the
1133
+ direct sum of `f: A \to B` and `g: C \to D` returned is the map
1134
+ `A \oplus C \to B \oplus D` defined by sending `(x, y)` to
1135
+ `(f(x), g(y))`.
1136
+
1137
+ OUTPUT: :class:`QuiverRepHom` or tuple
1138
+
1139
+ EXAMPLES::
1140
+
1141
+ sage: Q = DiGraph({1:{2:['a', 'b']}}).path_semigroup()
1142
+ sage: P1 = Q.P(GF(3), 1)
1143
+ sage: P2 = Q.P(GF(3), 2)
1144
+ sage: S1 = P1/P1.radical()
1145
+ sage: S2 = P2/P2.radical()
1146
+ sage: pi1 = S1.coerce_map_from(P1)
1147
+ sage: pi2 = S2.coerce_map_from(P2)
1148
+ sage: f = pi1.direct_sum(pi2)
1149
+ sage: f.domain().dimension_vector() == Q.free_module(GF(3)).dimension_vector()
1150
+ True
1151
+ sage: f.is_surjective()
1152
+ True
1153
+ sage: id = P1.Hom(P1).identity()
1154
+ sage: g = pi1.direct_sum(id, pinch='domain')
1155
+ sage: g.is_surjective()
1156
+ False
1157
+ """
1158
+ # Get the list of maps to be summed
1159
+ if isinstance(maps, QuiverRepHom):
1160
+ maplist = [self, maps]
1161
+ else:
1162
+ maplist = [self] + maps
1163
+
1164
+ # Check that the quivers/base rings are the same. If pinching also
1165
+ # check that the domain/codomains are correct
1166
+ for x in maplist:
1167
+ if not isinstance(x, QuiverRepHom):
1168
+ raise TypeError("maps must be a QuiverRepHom or list of QuiverRepHoms")
1169
+ if self._quiver is not x._quiver:
1170
+ raise ValueError("cannot direct sum maps from different quivers")
1171
+ if self._base_ring is not x._base_ring:
1172
+ raise ValueError("base rings must be identical")
1173
+ if pinch == 'domain' and self._domain is not x._domain:
1174
+ raise ValueError("cannot pinch maps, domains do not agree")
1175
+ if pinch == 'codomain' and self._codomain is not x._codomain:
1176
+ raise ValueError("cannot pinch maps, codomains do not agree")
1177
+
1178
+ # Get the sums and their maps
1179
+ if pinch == 'domain':
1180
+ domain = self._domain
1181
+ else:
1182
+ domain, d_incl, d_proj = self._domain.direct_sum([x._domain for x in maplist[1:]], return_maps=True)
1183
+ if pinch == 'codomain':
1184
+ codomain = self._codomain
1185
+ else:
1186
+ codomain, c_incl, c_proj = self._codomain.direct_sum([x._codomain for x in maplist[1:]], return_maps=True)
1187
+
1188
+ # Start with the zero map
1189
+ result = domain.hom(codomain)
1190
+
1191
+ # Add each factor
1192
+ for i in range(len(maplist)):
1193
+ if pinch == 'domain':
1194
+ result += c_incl[i] * maplist[i]
1195
+ elif pinch == 'codomain':
1196
+ result += maplist[i] * d_proj[i]
1197
+ else:
1198
+ result += c_incl[i] * maplist[i] * d_proj[i]
1199
+
1200
+ # Return the results
1201
+ if return_maps:
1202
+ if pinch == 'domain':
1203
+ return (result, c_incl, c_proj)
1204
+ elif pinch == 'codomain':
1205
+ return (result, d_incl, d_proj)
1206
+ else:
1207
+ return (result, d_incl, d_proj, c_incl, c_proj)
1208
+ else:
1209
+ return result
1210
+
1211
+ def lift(self, x):
1212
+ """
1213
+ Given an element `x` of the image, return an element of the domain
1214
+ that maps onto it under ``self``.
1215
+
1216
+ INPUT:
1217
+
1218
+ - ``x`` -- :class:`QuiverRepElement`
1219
+
1220
+ OUTPUT: :class:`QuiverRepElement`
1221
+
1222
+ EXAMPLES::
1223
+
1224
+ sage: Q = DiGraph({1:{2:['a','b']}, 2:{3:['c','d']}}).path_semigroup()
1225
+ sage: P = Q.P(QQ, 3)
1226
+ sage: S = P/P.radical()
1227
+ sage: proj = S.coerce_map_from(P)
1228
+ sage: x = S.an_element()
1229
+ sage: y = proj.lift(x)
1230
+ sage: proj(y) == x
1231
+ True
1232
+ sage: zero = S.hom(S, {})
1233
+ sage: zero.lift(x)
1234
+ Traceback (most recent call last):
1235
+ ...
1236
+ ValueError: element is not in the image
1237
+ """
1238
+ # Lift at each vertex
1239
+ elems = {v: self.get_map(v).lift(x._elems[v]) for v in self._quiver}
1240
+ return self._domain(elems)
1241
+
1242
+ ###########################################################################
1243
+ # #
1244
+ # ADDITIONAL OPERATIONS #
1245
+ # These functions operations that are not implemented via binary #
1246
+ # operators. #
1247
+ # #
1248
+ ###########################################################################
1249
+
1250
+ def scalar_mult(self, scalar):
1251
+ r"""
1252
+ Return the result of the scalar multiplication ``scalar * self``,
1253
+ where ``scalar`` is an element of the base ring `k`.
1254
+
1255
+ EXAMPLES::
1256
+
1257
+ sage: Q = DiGraph({1:{2:['a','b']}}).path_semigroup()
1258
+ sage: M = Q.P(QQ, 1)
1259
+ sage: f = M.Hom(M).an_element()
1260
+ sage: x = M.an_element()
1261
+ sage: g = f.scalar_mult(6)
1262
+ sage: g(x) == 6*f(x)
1263
+ True
1264
+ """
1265
+ return self._domain.hom(scalar * self._vector, self._codomain)
1266
+
1267
+ def iscalar_mult(self, scalar):
1268
+ """
1269
+ Multiply ``self`` by ``scalar`` in place.
1270
+
1271
+ EXAMPLES::
1272
+
1273
+ sage: Q = DiGraph({1:{2:['a','b']}}).path_semigroup()
1274
+ sage: M = Q.P(QQ, 1)
1275
+ sage: f = M.Hom(M).an_element()
1276
+ sage: x = M.an_element()
1277
+ sage: y = f(x)
1278
+ sage: f.iscalar_mult(6)
1279
+ sage: f(x) == 6*y
1280
+ True
1281
+ """
1282
+ self._vector *= scalar