passagemath-schemes 10.6.40__cp314-cp314-macosx_13_0_arm64.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.

Potentially problematic release.


This version of passagemath-schemes might be problematic. Click here for more details.

Files changed (314) hide show
  1. passagemath_schemes/.dylibs/libflint.22.0.dylib +0 -0
  2. passagemath_schemes/.dylibs/libgmp.10.dylib +0 -0
  3. passagemath_schemes/.dylibs/libgmpxx.4.dylib +0 -0
  4. passagemath_schemes/.dylibs/libmpfr.6.dylib +0 -0
  5. passagemath_schemes/__init__.py +3 -0
  6. passagemath_schemes-10.6.40.dist-info/METADATA +204 -0
  7. passagemath_schemes-10.6.40.dist-info/METADATA.bak +205 -0
  8. passagemath_schemes-10.6.40.dist-info/RECORD +314 -0
  9. passagemath_schemes-10.6.40.dist-info/WHEEL +6 -0
  10. passagemath_schemes-10.6.40.dist-info/top_level.txt +3 -0
  11. sage/all__sagemath_schemes.py +23 -0
  12. sage/databases/all__sagemath_schemes.py +7 -0
  13. sage/databases/cremona.py +1723 -0
  14. sage/dynamics/all__sagemath_schemes.py +2 -0
  15. sage/dynamics/arithmetic_dynamics/affine_ds.py +1083 -0
  16. sage/dynamics/arithmetic_dynamics/all.py +14 -0
  17. sage/dynamics/arithmetic_dynamics/berkovich_ds.py +1101 -0
  18. sage/dynamics/arithmetic_dynamics/dynamical_semigroup.py +1543 -0
  19. sage/dynamics/arithmetic_dynamics/endPN_automorphism_group.py +2426 -0
  20. sage/dynamics/arithmetic_dynamics/endPN_minimal_model.py +1169 -0
  21. sage/dynamics/arithmetic_dynamics/generic_ds.py +663 -0
  22. sage/dynamics/arithmetic_dynamics/product_projective_ds.py +339 -0
  23. sage/dynamics/arithmetic_dynamics/projective_ds.py +9558 -0
  24. sage/dynamics/arithmetic_dynamics/projective_ds_helper.cpython-314-darwin.so +0 -0
  25. sage/dynamics/arithmetic_dynamics/projective_ds_helper.pyx +301 -0
  26. sage/dynamics/arithmetic_dynamics/wehlerK3.py +2576 -0
  27. sage/lfunctions/all.py +18 -0
  28. sage/lfunctions/dokchitser.py +745 -0
  29. sage/lfunctions/pari.py +818 -0
  30. sage/lfunctions/zero_sums.cpython-314-darwin.so +0 -0
  31. sage/lfunctions/zero_sums.pyx +1847 -0
  32. sage/modular/abvar/abvar.py +5135 -0
  33. sage/modular/abvar/abvar_ambient_jacobian.py +413 -0
  34. sage/modular/abvar/abvar_newform.py +244 -0
  35. sage/modular/abvar/all.py +8 -0
  36. sage/modular/abvar/constructor.py +186 -0
  37. sage/modular/abvar/cuspidal_subgroup.py +371 -0
  38. sage/modular/abvar/finite_subgroup.py +896 -0
  39. sage/modular/abvar/homology.py +720 -0
  40. sage/modular/abvar/homspace.py +998 -0
  41. sage/modular/abvar/lseries.py +415 -0
  42. sage/modular/abvar/morphism.py +935 -0
  43. sage/modular/abvar/torsion_point.py +274 -0
  44. sage/modular/abvar/torsion_subgroup.py +740 -0
  45. sage/modular/all.py +43 -0
  46. sage/modular/arithgroup/all.py +20 -0
  47. sage/modular/arithgroup/arithgroup_element.cpython-314-darwin.so +0 -0
  48. sage/modular/arithgroup/arithgroup_element.pyx +474 -0
  49. sage/modular/arithgroup/arithgroup_generic.py +1402 -0
  50. sage/modular/arithgroup/arithgroup_perm.py +2692 -0
  51. sage/modular/arithgroup/congroup.cpython-314-darwin.so +0 -0
  52. sage/modular/arithgroup/congroup.pyx +334 -0
  53. sage/modular/arithgroup/congroup_gamma.py +363 -0
  54. sage/modular/arithgroup/congroup_gamma0.py +692 -0
  55. sage/modular/arithgroup/congroup_gamma1.py +653 -0
  56. sage/modular/arithgroup/congroup_gammaH.py +1469 -0
  57. sage/modular/arithgroup/congroup_generic.py +628 -0
  58. sage/modular/arithgroup/congroup_sl2z.py +267 -0
  59. sage/modular/arithgroup/farey_symbol.cpython-314-darwin.so +0 -0
  60. sage/modular/arithgroup/farey_symbol.pyx +1066 -0
  61. sage/modular/arithgroup/tests.py +418 -0
  62. sage/modular/btquotients/all.py +4 -0
  63. sage/modular/btquotients/btquotient.py +3753 -0
  64. sage/modular/btquotients/pautomorphicform.py +2570 -0
  65. sage/modular/buzzard.py +100 -0
  66. sage/modular/congroup.py +29 -0
  67. sage/modular/congroup_element.py +13 -0
  68. sage/modular/cusps.py +1109 -0
  69. sage/modular/cusps_nf.py +1270 -0
  70. sage/modular/dims.py +569 -0
  71. sage/modular/dirichlet.py +3310 -0
  72. sage/modular/drinfeld_modform/all.py +2 -0
  73. sage/modular/drinfeld_modform/element.py +446 -0
  74. sage/modular/drinfeld_modform/ring.py +773 -0
  75. sage/modular/drinfeld_modform/tutorial.py +236 -0
  76. sage/modular/etaproducts.py +1065 -0
  77. sage/modular/hecke/algebra.py +746 -0
  78. sage/modular/hecke/all.py +20 -0
  79. sage/modular/hecke/ambient_module.py +1019 -0
  80. sage/modular/hecke/degenmap.py +119 -0
  81. sage/modular/hecke/element.py +325 -0
  82. sage/modular/hecke/hecke_operator.py +780 -0
  83. sage/modular/hecke/homspace.py +206 -0
  84. sage/modular/hecke/module.py +1767 -0
  85. sage/modular/hecke/morphism.py +174 -0
  86. sage/modular/hecke/submodule.py +989 -0
  87. sage/modular/hypergeometric_misc.cpython-314-darwin.so +0 -0
  88. sage/modular/hypergeometric_misc.pxd +4 -0
  89. sage/modular/hypergeometric_misc.pyx +166 -0
  90. sage/modular/hypergeometric_motive.py +2017 -0
  91. sage/modular/local_comp/all.py +2 -0
  92. sage/modular/local_comp/liftings.py +292 -0
  93. sage/modular/local_comp/local_comp.py +1071 -0
  94. sage/modular/local_comp/smoothchar.py +1825 -0
  95. sage/modular/local_comp/type_space.py +748 -0
  96. sage/modular/modform/all.py +30 -0
  97. sage/modular/modform/ambient.py +815 -0
  98. sage/modular/modform/ambient_R.py +177 -0
  99. sage/modular/modform/ambient_eps.py +306 -0
  100. sage/modular/modform/ambient_g0.py +124 -0
  101. sage/modular/modform/ambient_g1.py +204 -0
  102. sage/modular/modform/constructor.py +545 -0
  103. sage/modular/modform/cuspidal_submodule.py +708 -0
  104. sage/modular/modform/defaults.py +14 -0
  105. sage/modular/modform/eis_series.py +505 -0
  106. sage/modular/modform/eisenstein_submodule.py +663 -0
  107. sage/modular/modform/element.py +4131 -0
  108. sage/modular/modform/find_generators.py +59 -0
  109. sage/modular/modform/half_integral.py +154 -0
  110. sage/modular/modform/hecke_operator_on_qexp.py +247 -0
  111. sage/modular/modform/j_invariant.py +47 -0
  112. sage/modular/modform/l_series_gross_zagier.py +133 -0
  113. sage/modular/modform/l_series_gross_zagier_coeffs.cpython-314-darwin.so +0 -0
  114. sage/modular/modform/l_series_gross_zagier_coeffs.pyx +177 -0
  115. sage/modular/modform/notes.py +45 -0
  116. sage/modular/modform/numerical.py +514 -0
  117. sage/modular/modform/periods.py +14 -0
  118. sage/modular/modform/ring.py +1257 -0
  119. sage/modular/modform/space.py +1860 -0
  120. sage/modular/modform/submodule.py +118 -0
  121. sage/modular/modform/tests.py +64 -0
  122. sage/modular/modform/theta.py +110 -0
  123. sage/modular/modform/vm_basis.py +381 -0
  124. sage/modular/modform/weight1.py +220 -0
  125. sage/modular/modform_hecketriangle/abstract_ring.py +1932 -0
  126. sage/modular/modform_hecketriangle/abstract_space.py +2528 -0
  127. sage/modular/modform_hecketriangle/all.py +30 -0
  128. sage/modular/modform_hecketriangle/analytic_type.py +590 -0
  129. sage/modular/modform_hecketriangle/constructor.py +416 -0
  130. sage/modular/modform_hecketriangle/element.py +351 -0
  131. sage/modular/modform_hecketriangle/functors.py +752 -0
  132. sage/modular/modform_hecketriangle/graded_ring.py +541 -0
  133. sage/modular/modform_hecketriangle/graded_ring_element.py +2225 -0
  134. sage/modular/modform_hecketriangle/hecke_triangle_group_element.py +3352 -0
  135. sage/modular/modform_hecketriangle/hecke_triangle_groups.py +1432 -0
  136. sage/modular/modform_hecketriangle/readme.py +1214 -0
  137. sage/modular/modform_hecketriangle/series_constructor.py +580 -0
  138. sage/modular/modform_hecketriangle/space.py +1037 -0
  139. sage/modular/modform_hecketriangle/subspace.py +423 -0
  140. sage/modular/modsym/all.py +17 -0
  141. sage/modular/modsym/ambient.py +3846 -0
  142. sage/modular/modsym/boundary.py +1420 -0
  143. sage/modular/modsym/element.py +336 -0
  144. sage/modular/modsym/g1list.py +178 -0
  145. sage/modular/modsym/ghlist.py +182 -0
  146. sage/modular/modsym/hecke_operator.py +73 -0
  147. sage/modular/modsym/manin_symbol.cpython-314-darwin.so +0 -0
  148. sage/modular/modsym/manin_symbol.pxd +5 -0
  149. sage/modular/modsym/manin_symbol.pyx +497 -0
  150. sage/modular/modsym/manin_symbol_list.py +1295 -0
  151. sage/modular/modsym/modsym.py +400 -0
  152. sage/modular/modsym/modular_symbols.py +384 -0
  153. sage/modular/modsym/p1list.cpython-314-darwin.so +0 -0
  154. sage/modular/modsym/p1list.pxd +29 -0
  155. sage/modular/modsym/p1list.pyx +1372 -0
  156. sage/modular/modsym/p1list_nf.py +1241 -0
  157. sage/modular/modsym/relation_matrix.py +591 -0
  158. sage/modular/modsym/relation_matrix_pyx.cpython-314-darwin.so +0 -0
  159. sage/modular/modsym/relation_matrix_pyx.pyx +108 -0
  160. sage/modular/modsym/space.py +2468 -0
  161. sage/modular/modsym/subspace.py +455 -0
  162. sage/modular/modsym/tests.py +375 -0
  163. sage/modular/multiple_zeta.py +2632 -0
  164. sage/modular/multiple_zeta_F_algebra.py +786 -0
  165. sage/modular/overconvergent/all.py +6 -0
  166. sage/modular/overconvergent/genus0.py +1878 -0
  167. sage/modular/overconvergent/hecke_series.py +1187 -0
  168. sage/modular/overconvergent/weightspace.py +778 -0
  169. sage/modular/pollack_stevens/all.py +4 -0
  170. sage/modular/pollack_stevens/distributions.py +874 -0
  171. sage/modular/pollack_stevens/fund_domain.py +1572 -0
  172. sage/modular/pollack_stevens/manin_map.py +859 -0
  173. sage/modular/pollack_stevens/modsym.py +1593 -0
  174. sage/modular/pollack_stevens/padic_lseries.py +417 -0
  175. sage/modular/pollack_stevens/sigma0.py +534 -0
  176. sage/modular/pollack_stevens/space.py +1076 -0
  177. sage/modular/quasimodform/all.py +3 -0
  178. sage/modular/quasimodform/element.py +845 -0
  179. sage/modular/quasimodform/ring.py +828 -0
  180. sage/modular/quatalg/all.py +3 -0
  181. sage/modular/quatalg/brandt.py +1642 -0
  182. sage/modular/ssmod/all.py +8 -0
  183. sage/modular/ssmod/ssmod.py +827 -0
  184. sage/rings/all__sagemath_schemes.py +1 -0
  185. sage/rings/polynomial/all__sagemath_schemes.py +1 -0
  186. sage/rings/polynomial/binary_form_reduce.py +585 -0
  187. sage/schemes/all.py +41 -0
  188. sage/schemes/berkovich/all.py +6 -0
  189. sage/schemes/berkovich/berkovich_cp_element.py +2582 -0
  190. sage/schemes/berkovich/berkovich_space.py +748 -0
  191. sage/schemes/curves/affine_curve.py +2928 -0
  192. sage/schemes/curves/all.py +33 -0
  193. sage/schemes/curves/closed_point.py +434 -0
  194. sage/schemes/curves/constructor.py +381 -0
  195. sage/schemes/curves/curve.py +542 -0
  196. sage/schemes/curves/plane_curve_arrangement.py +1283 -0
  197. sage/schemes/curves/point.py +463 -0
  198. sage/schemes/curves/projective_curve.py +3026 -0
  199. sage/schemes/curves/zariski_vankampen.py +1932 -0
  200. sage/schemes/cyclic_covers/all.py +2 -0
  201. sage/schemes/cyclic_covers/charpoly_frobenius.py +320 -0
  202. sage/schemes/cyclic_covers/constructor.py +137 -0
  203. sage/schemes/cyclic_covers/cycliccover_finite_field.py +1309 -0
  204. sage/schemes/cyclic_covers/cycliccover_generic.py +310 -0
  205. sage/schemes/elliptic_curves/BSD.py +1036 -0
  206. sage/schemes/elliptic_curves/Qcurves.py +592 -0
  207. sage/schemes/elliptic_curves/addition_formulas_ring.py +94 -0
  208. sage/schemes/elliptic_curves/all.py +49 -0
  209. sage/schemes/elliptic_curves/cardinality.py +609 -0
  210. sage/schemes/elliptic_curves/cm.py +1102 -0
  211. sage/schemes/elliptic_curves/constructor.py +1552 -0
  212. sage/schemes/elliptic_curves/ec_database.py +175 -0
  213. sage/schemes/elliptic_curves/ell_curve_isogeny.py +3972 -0
  214. sage/schemes/elliptic_curves/ell_egros.py +459 -0
  215. sage/schemes/elliptic_curves/ell_field.py +2836 -0
  216. sage/schemes/elliptic_curves/ell_finite_field.py +3359 -0
  217. sage/schemes/elliptic_curves/ell_generic.py +3760 -0
  218. sage/schemes/elliptic_curves/ell_local_data.py +1207 -0
  219. sage/schemes/elliptic_curves/ell_modular_symbols.py +775 -0
  220. sage/schemes/elliptic_curves/ell_number_field.py +4220 -0
  221. sage/schemes/elliptic_curves/ell_padic_field.py +107 -0
  222. sage/schemes/elliptic_curves/ell_point.py +4787 -0
  223. sage/schemes/elliptic_curves/ell_rational_field.py +7368 -0
  224. sage/schemes/elliptic_curves/ell_tate_curve.py +671 -0
  225. sage/schemes/elliptic_curves/ell_torsion.py +436 -0
  226. sage/schemes/elliptic_curves/ell_wp.py +352 -0
  227. sage/schemes/elliptic_curves/formal_group.py +760 -0
  228. sage/schemes/elliptic_curves/gal_reps.py +1459 -0
  229. sage/schemes/elliptic_curves/gal_reps_number_field.py +1669 -0
  230. sage/schemes/elliptic_curves/gp_simon.py +152 -0
  231. sage/schemes/elliptic_curves/heegner.py +7335 -0
  232. sage/schemes/elliptic_curves/height.py +2109 -0
  233. sage/schemes/elliptic_curves/hom.py +1406 -0
  234. sage/schemes/elliptic_curves/hom_composite.py +934 -0
  235. sage/schemes/elliptic_curves/hom_frobenius.py +522 -0
  236. sage/schemes/elliptic_curves/hom_scalar.py +531 -0
  237. sage/schemes/elliptic_curves/hom_sum.py +682 -0
  238. sage/schemes/elliptic_curves/hom_velusqrt.py +1290 -0
  239. sage/schemes/elliptic_curves/homset.py +271 -0
  240. sage/schemes/elliptic_curves/isogeny_class.py +1521 -0
  241. sage/schemes/elliptic_curves/isogeny_small_degree.py +2797 -0
  242. sage/schemes/elliptic_curves/jacobian.py +237 -0
  243. sage/schemes/elliptic_curves/kodaira_symbol.py +344 -0
  244. sage/schemes/elliptic_curves/kraus.py +1014 -0
  245. sage/schemes/elliptic_curves/lseries_ell.py +943 -0
  246. sage/schemes/elliptic_curves/mod5family.py +105 -0
  247. sage/schemes/elliptic_curves/mod_poly.py +197 -0
  248. sage/schemes/elliptic_curves/mod_sym_num.cpython-314-darwin.so +0 -0
  249. sage/schemes/elliptic_curves/mod_sym_num.pyx +3796 -0
  250. sage/schemes/elliptic_curves/modular_parametrization.py +305 -0
  251. sage/schemes/elliptic_curves/padic_lseries.py +1793 -0
  252. sage/schemes/elliptic_curves/padics.py +1816 -0
  253. sage/schemes/elliptic_curves/period_lattice.py +2234 -0
  254. sage/schemes/elliptic_curves/period_lattice_region.cpython-314-darwin.so +0 -0
  255. sage/schemes/elliptic_curves/period_lattice_region.pyx +722 -0
  256. sage/schemes/elliptic_curves/saturation.py +715 -0
  257. sage/schemes/elliptic_curves/sha_tate.py +1158 -0
  258. sage/schemes/elliptic_curves/weierstrass_morphism.py +1117 -0
  259. sage/schemes/elliptic_curves/weierstrass_transform.py +200 -0
  260. sage/schemes/hyperelliptic_curves/all.py +6 -0
  261. sage/schemes/hyperelliptic_curves/constructor.py +291 -0
  262. sage/schemes/hyperelliptic_curves/hyperelliptic_finite_field.py +1914 -0
  263. sage/schemes/hyperelliptic_curves/hyperelliptic_g2.py +192 -0
  264. sage/schemes/hyperelliptic_curves/hyperelliptic_generic.py +954 -0
  265. sage/schemes/hyperelliptic_curves/hyperelliptic_padic_field.py +1332 -0
  266. sage/schemes/hyperelliptic_curves/hyperelliptic_rational_field.py +84 -0
  267. sage/schemes/hyperelliptic_curves/invariants.py +410 -0
  268. sage/schemes/hyperelliptic_curves/jacobian_endomorphism_utils.py +315 -0
  269. sage/schemes/hyperelliptic_curves/jacobian_g2.py +32 -0
  270. sage/schemes/hyperelliptic_curves/jacobian_generic.py +419 -0
  271. sage/schemes/hyperelliptic_curves/jacobian_homset.py +186 -0
  272. sage/schemes/hyperelliptic_curves/jacobian_morphism.py +875 -0
  273. sage/schemes/hyperelliptic_curves/kummer_surface.py +99 -0
  274. sage/schemes/hyperelliptic_curves/mestre.py +302 -0
  275. sage/schemes/hyperelliptic_curves/monsky_washnitzer.py +3871 -0
  276. sage/schemes/jacobians/abstract_jacobian.py +277 -0
  277. sage/schemes/jacobians/all.py +2 -0
  278. sage/schemes/overview.py +161 -0
  279. sage/schemes/plane_conics/all.py +22 -0
  280. sage/schemes/plane_conics/con_field.py +1296 -0
  281. sage/schemes/plane_conics/con_finite_field.py +158 -0
  282. sage/schemes/plane_conics/con_number_field.py +456 -0
  283. sage/schemes/plane_conics/con_rational_field.py +406 -0
  284. sage/schemes/plane_conics/con_rational_function_field.py +580 -0
  285. sage/schemes/plane_conics/constructor.py +249 -0
  286. sage/schemes/plane_quartics/all.py +2 -0
  287. sage/schemes/plane_quartics/quartic_constructor.py +71 -0
  288. sage/schemes/plane_quartics/quartic_generic.py +73 -0
  289. sage/schemes/riemann_surfaces/all.py +1 -0
  290. sage/schemes/riemann_surfaces/riemann_surface.py +4117 -0
  291. sage_wheels/share/cremona/cremona_mini.db +0 -0
  292. sage_wheels/share/ellcurves/rank0 +30427 -0
  293. sage_wheels/share/ellcurves/rank1 +31871 -0
  294. sage_wheels/share/ellcurves/rank10 +6 -0
  295. sage_wheels/share/ellcurves/rank11 +6 -0
  296. sage_wheels/share/ellcurves/rank12 +1 -0
  297. sage_wheels/share/ellcurves/rank14 +1 -0
  298. sage_wheels/share/ellcurves/rank15 +1 -0
  299. sage_wheels/share/ellcurves/rank17 +1 -0
  300. sage_wheels/share/ellcurves/rank19 +1 -0
  301. sage_wheels/share/ellcurves/rank2 +2388 -0
  302. sage_wheels/share/ellcurves/rank20 +1 -0
  303. sage_wheels/share/ellcurves/rank21 +1 -0
  304. sage_wheels/share/ellcurves/rank22 +1 -0
  305. sage_wheels/share/ellcurves/rank23 +1 -0
  306. sage_wheels/share/ellcurves/rank24 +1 -0
  307. sage_wheels/share/ellcurves/rank28 +1 -0
  308. sage_wheels/share/ellcurves/rank3 +836 -0
  309. sage_wheels/share/ellcurves/rank4 +10 -0
  310. sage_wheels/share/ellcurves/rank5 +5 -0
  311. sage_wheels/share/ellcurves/rank6 +5 -0
  312. sage_wheels/share/ellcurves/rank7 +5 -0
  313. sage_wheels/share/ellcurves/rank8 +6 -0
  314. sage_wheels/share/ellcurves/rank9 +7 -0
@@ -0,0 +1,1283 @@
1
+ # sage_setup: distribution = sagemath-schemes
2
+ r"""
3
+ Affine and Projective Plane Curve Arrangements
4
+
5
+ We create classes :class:`AffinePlaneCurveArrangements`
6
+ and :class:`ProjectivePlaneCurveArrangements`
7
+ following the properties of :class:`HyperplaneArrangements`::
8
+
9
+ sage: H.<x, y> = AffinePlaneCurveArrangements(QQ)
10
+ sage: C = H(3*x + 2*y - x^2 + y^3 - 7); C
11
+ Arrangement (y^3 - x^2 + 3*x + 2*y - 7) in Affine Space of dimension 2 over Rational Field
12
+
13
+ The individual curves will be in :class:`AffinePlaneCurve` or in :class:`ProjectivePlaneCurve`::
14
+
15
+ sage: C[0].parent()
16
+ <class 'sage.schemes.curves.affine_curve.IntegralAffinePlaneCurve_with_category'>
17
+
18
+ The default base field is `\QQ`, the rational numbers.
19
+ Number fields are also possible (also with fixed embeddings in
20
+ `\QQbar`)::
21
+
22
+ sage: # needs sage.rings.number_field
23
+ sage: x = polygen(QQ, 'x')
24
+ sage: NF.<a> = NumberField(x^4 - 5 * x^2 + 5, embedding=1.90)
25
+ sage: H.<y,z> = AffinePlaneCurveArrangements(NF)
26
+ sage: A = H(y^2 - a * z, y^2 + a * z); A
27
+ Arrangement (y^2 + (-a)*z, y^2 + a*z) in Affine Space of dimension 2
28
+ over Number Field in a with defining polynomial
29
+ x^4 - 5*x^2 + 5 with a = 1.902113032590308?
30
+ sage: A.base_ring()
31
+ Number Field in a with defining polynomial x^4 - 5*x^2 + 5
32
+ with a = 1.902113032590308?
33
+
34
+
35
+ AUTHORS:
36
+
37
+ - Enrique Artal (2023-10): initial version
38
+ """
39
+
40
+ # *****************************************************************************
41
+ # Copyright (C) 2023 Enrique Artal <artal@unizar.es>
42
+ #
43
+ # This program is free software: you can redistribute it and/or modify
44
+ # it under the terms of the GNU General Public License as published by
45
+ # the Free Software Foundation, either version 2 of the License, or
46
+ # (at your option) any later version.
47
+ # https://www.gnu.org/licenses/
48
+ # *****************************************************************************
49
+ from itertools import combinations
50
+ from typing import Any
51
+
52
+ from sage.categories.sets_cat import Sets
53
+ from sage.misc.abstract_method import abstract_method
54
+ from sage.misc.cachefunc import cached_method
55
+ from sage.misc.lazy_import import lazy_import
56
+ from sage.misc.misc_c import prod
57
+ from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing
58
+ from sage.rings.qqbar import QQbar
59
+ from sage.rings.ring import _Fields
60
+ from sage.schemes.affine.affine_space import AffineSpace
61
+ from sage.schemes.curves.affine_curve import AffinePlaneCurve
62
+ from sage.schemes.curves.constructor import Curve
63
+ from sage.schemes.curves.projective_curve import ProjectiveSpace, ProjectivePlaneCurve
64
+ from sage.structure.category_object import normalize_names
65
+ from sage.structure.parent import Parent
66
+ from sage.structure.element import Element
67
+ from sage.structure.richcmp import richcmp
68
+ from sage.structure.unique_representation import UniqueRepresentation
69
+
70
+ lazy_import('sage.groups.free_group', 'FreeGroup')
71
+ lazy_import('sage.schemes.curves.zariski_vankampen', ['braid_monodromy', 'fundamental_group_arrangement'])
72
+
73
+
74
+ class PlaneCurveArrangementElement(Element):
75
+ """
76
+ An ordered plane curve arrangement.
77
+ """
78
+ def __init__(self, parent, curves, check=True) -> None:
79
+ """
80
+ Construct a plane curve arrangement.
81
+
82
+ INPUT:
83
+
84
+ - ``parent`` -- the parent :class:`PlaneCurveArrangements`
85
+
86
+ - ``curves`` -- tuple of curves
87
+
88
+ EXAMPLES::
89
+
90
+ sage: H.<x, y> = AffinePlaneCurveArrangements(QQ)
91
+ sage: elt = H(x, y); elt
92
+ Arrangement (x, y) in Affine Space of dimension 2 over Rational Field
93
+ sage: TestSuite(elt).run()
94
+ sage: H.<x, y, z> = ProjectivePlaneCurveArrangements(QQ)
95
+ sage: elt = H(x, y); elt
96
+ Arrangement (x, y) in Projective Space of dimension 2 over Rational Field
97
+ sage: TestSuite(elt).run()
98
+ """
99
+ super().__init__(parent)
100
+ self._curves = tuple(curves)
101
+ if check:
102
+ affine = all(isinstance(h, AffinePlaneCurve) for h in curves)
103
+ projective = all(isinstance(h, ProjectivePlaneCurve) for h in curves)
104
+ if not (affine or projective):
105
+ raise ValueError("not all elements are curves")
106
+ if not all(h.ambient_space() is parent.ambient_space()
107
+ for h in curves):
108
+ raise ValueError("not all curves are in the same ambient space")
109
+
110
+ def __getitem__(self, i):
111
+ """
112
+ Return the `i`-th curve.
113
+
114
+ INPUT:
115
+
116
+ - ``i`` -- integer
117
+
118
+ EXAMPLES::
119
+
120
+ sage: H.<x, y> = AffinePlaneCurveArrangements(QQ)
121
+ sage: H(y^2 - x, y^3 + 2 * x^2, x^4 + y^4 + 1)
122
+ Arrangement (y^2 - x, y^3 + 2*x^2, x^4 + y^4 + 1)
123
+ in Affine Space of dimension 2 over Rational Field
124
+ """
125
+ return self._curves[i]
126
+
127
+ def __hash__(self) -> int:
128
+ r"""
129
+ TESTS::
130
+
131
+ sage: H.<x, y> = AffinePlaneCurveArrangements(QQ)
132
+ sage: H((x * y, x + y +1)).__hash__() # random
133
+ -4938643871296220686
134
+ """
135
+ return hash(self.curves())
136
+
137
+ def ncurves(self) -> int:
138
+ r"""
139
+ Return the number of curves in the arrangement.
140
+
141
+ OUTPUT: integer
142
+
143
+ EXAMPLES::
144
+
145
+ sage: H.<x, y, z> = ProjectivePlaneCurveArrangements(QQ)
146
+ sage: h = H((x * y, x + y + z))
147
+ sage: h.ncurves()
148
+ 2
149
+ sage: len(h) # equivalent
150
+ 2
151
+ """
152
+ return len(self._curves)
153
+
154
+ __len__ = ncurves
155
+
156
+ def curves(self) -> tuple:
157
+ r"""
158
+ Return the curves in the arrangement as a tuple.
159
+
160
+ OUTPUT: a tuple
161
+
162
+ EXAMPLES::
163
+
164
+ sage: H.<x, y> = AffinePlaneCurveArrangements(QQ)
165
+ sage: h = H((x * y, x + y + 1))
166
+ sage: h.curves()
167
+ (Affine Plane Curve over Rational Field defined by x*y,
168
+ Affine Plane Curve over Rational Field defined by x + y + 1)
169
+
170
+ Note that the curves can be indexed as if they were a list::
171
+
172
+ sage: h[1]
173
+ Affine Plane Curve over Rational Field defined by x + y + 1
174
+ """
175
+ return self._curves
176
+
177
+ def _repr_(self) -> str:
178
+ r"""
179
+ String representation for a curve arrangement.
180
+
181
+ OUTPUT: string
182
+
183
+ EXAMPLES::
184
+
185
+ sage: H.<x, y> = AffinePlaneCurveArrangements(QQ)
186
+ sage: h = H([x * y, x + y + 1, x^3 - y^5, x^2 * y^2 + x^5 + y^5, (x^2 + y^2)^3 + (x^3 + y^3 - 1)^2])
187
+ sage: h
188
+ Arrangement of 5 curves in Affine Space of dimension 2 over Rational Field
189
+ sage: H(())
190
+ Arrangement () in Affine Space of dimension 2 over Rational Field
191
+ sage: H.<x, y, z> = ProjectivePlaneCurveArrangements(QQ)
192
+ sage: h = H([x * y, x + y + z, x^3 * z^2 - y^5, x^2 * y^2 * z + x^5 + y^5, (x^2 + y^2)^3 + (x^3 + y^3 - z^3)^2])
193
+ sage: h
194
+ Arrangement of 5 curves in Projective Space of dimension 2 over Rational Field
195
+ """
196
+ if not self:
197
+ return 'Empty curve arrangement in {}'.format(self.parent().ambient_space())
198
+ elif len(self) < 5:
199
+ curves = ', '.join(h.defining_polynomial()._repr_()
200
+ for h in self._curves)
201
+ return 'Arrangement ({}) in {}'.format(curves,
202
+ self.parent().ambient_space())
203
+ return 'Arrangement of {} curves in {}'.format(len(self),
204
+ self.parent().ambient_space())
205
+
206
+ def _richcmp_(self, other, op) -> bool:
207
+ """
208
+ Compare two curve arrangements.
209
+
210
+ EXAMPLES::
211
+
212
+ sage: H.<x, y> = AffinePlaneCurveArrangements(QQ)
213
+ sage: H(x) == H(y)
214
+ False
215
+ sage: H(x) == H(2 * x)
216
+ True
217
+
218
+ TESTS::
219
+
220
+ sage: H(x) == 0
221
+ False
222
+ """
223
+ return richcmp(self._curves, other._curves, op)
224
+
225
+ def union(self, other):
226
+ r"""
227
+ The union of ``self`` with ``other``.
228
+
229
+ INPUT:
230
+
231
+ - ``other`` -- a curve arrangement or something that can
232
+ be converted into a curve arrangement
233
+
234
+ OUTPUT: a new curve arrangement
235
+
236
+ EXAMPLES::
237
+
238
+ sage: H.<x, y> = AffinePlaneCurveArrangements(QQ)
239
+ sage: h = H([x * y, x + y + 1, x^3 - y^5, x^2 * y^2 + x^5 + y^5, (x^2 + y^2)^3 + (x^3 + y^3 - 1)^2])
240
+ sage: C = Curve(x^8 - y^8 -x^4 * y^4)
241
+ sage: h1 = h.union(C); h1
242
+ Arrangement of 6 curves in Affine Space of dimension 2 over Rational Field
243
+ sage: h1 == h1.union(C)
244
+ True
245
+ """
246
+ P = self.parent()
247
+ other_h = P(other)
248
+ curves0 = self._curves + other_h._curves
249
+ curves = []
250
+ for h in curves0:
251
+ if h not in curves:
252
+ curves.append(h)
253
+ result = P(*curves)
254
+ return result
255
+
256
+ add_curves = union
257
+
258
+ __or__ = union
259
+
260
+ def deletion(self, curves):
261
+ r"""
262
+ Return the curve arrangement obtained by removing ``curves``.
263
+
264
+ INPUT:
265
+
266
+ - ``curves`` -- a curve or curve arrangement
267
+
268
+ OUTPUT:
269
+
270
+ A new curve arrangement with the given curve(s)
271
+ ``h`` removed.
272
+
273
+ EXAMPLES::
274
+
275
+ sage: H.<x, y> = AffinePlaneCurveArrangements(QQ)
276
+ sage: h = H([x * y, x + y + 1, x^3 - y^5, x^2 * y^2 + x^5 + y^5, (x^2 + y^2)^3 + (x^3 + y^3 - 1)^2])
277
+ sage: C = h[-1]
278
+ sage: h.deletion(C)
279
+ Arrangement (x*y, x + y + 1, -y^5 + x^3, x^5 + y^5 + x^2*y^2)
280
+ in Affine Space of dimension 2 over Rational Field
281
+ sage: h.deletion(x)
282
+ Traceback (most recent call last):
283
+ ...
284
+ ValueError: curve is not in the arrangement
285
+ """
286
+ parent = self.parent()
287
+ curves = parent(curves)
288
+ planes = list(self)
289
+ for curve in curves:
290
+ try:
291
+ planes.remove(curve)
292
+ except ValueError:
293
+ raise ValueError('curve is not in the arrangement')
294
+ return parent(planes)
295
+
296
+ def change_ring(self, base_ring):
297
+ """
298
+ Return curve arrangement over the new base ring.
299
+
300
+ INPUT:
301
+
302
+ - ``base_ring`` -- the new base ring; must be a field for
303
+ curve arrangements
304
+
305
+ OUTPUT:
306
+
307
+ The curve arrangement obtained by changing the base
308
+ field, as a new curve arrangement.
309
+
310
+ EXAMPLES::
311
+
312
+ sage: # needs sage.rings.number_field
313
+ sage: H.<x, y> = AffinePlaneCurveArrangements(QQ)
314
+ sage: A = H(y^2 - x^3, x, y, y^2 + x * y + x^2)
315
+ sage: K.<a> = CyclotomicField(3)
316
+ sage: A.change_ring(K)
317
+ Arrangement (-x^3 + y^2, x, y, x^2 + x*y + y^2) in Affine Space of
318
+ dimension 2 over Cyclotomic Field of order 3 and degree 2
319
+ """
320
+ parent = self.parent().change_ring(base_ring)
321
+ curves = tuple(c.change_ring(base_ring) for c in self)
322
+ return parent(curves)
323
+
324
+ @cached_method
325
+ def coordinate_ring(self):
326
+ """
327
+ Return the coordinate ring of ``self``.
328
+
329
+ OUTPUT: the coordinate ring of the curve arrangement
330
+
331
+ EXAMPLES::
332
+
333
+ sage: L.<x, y> = AffinePlaneCurveArrangements(QQ)
334
+ sage: C = L(x, y)
335
+ sage: C.coordinate_ring()
336
+ Multivariate Polynomial Ring in x, y over Rational Field
337
+ sage: P.<x, y, z> = ProjectivePlaneCurveArrangements(QQ)
338
+ sage: C = P(x, y)
339
+ sage: C.coordinate_ring()
340
+ Multivariate Polynomial Ring in x, y, z over Rational Field
341
+ """
342
+ return self._curves[0].defining_polynomial().parent()
343
+
344
+ def defining_polynomials(self) -> tuple:
345
+ r"""
346
+ Return the defining polynomials of the elements of ``self``.
347
+
348
+ EXAMPLES::
349
+
350
+ sage: H.<x, y> = AffinePlaneCurveArrangements(QQ)
351
+ sage: A = H(y^2 - x^3, x, y, y^2 + x * y + x^2)
352
+ sage: A.defining_polynomials()
353
+ (-x^3 + y^2, x, y, x^2 + x*y + y^2)
354
+ """
355
+ return tuple([h.defining_polynomial() for h in self._curves])
356
+
357
+ def defining_polynomial(self, simplified=True):
358
+ r"""
359
+ Return the defining polynomial of the union of the curves in ``self``.
360
+
361
+ EXAMPLES::
362
+
363
+ sage: H.<x, y> = AffinePlaneCurveArrangements(QQ)
364
+ sage: A = H(y ** 2 + x ** 2, x, y)
365
+ sage: prod(A.defining_polynomials()) == A.defining_polynomial()
366
+ True
367
+ """
368
+ return prod(self.defining_polynomials())
369
+
370
+ def have_common_factors(self) -> bool:
371
+ r"""
372
+ Check if the curves have common factors.
373
+
374
+ EXAMPLES::
375
+
376
+ sage: H.<x, y> = AffinePlaneCurveArrangements(QQ)
377
+ sage: A = H(x * y, x^2 + x* y^3)
378
+ sage: A.have_common_factors()
379
+ True
380
+ sage: H(x * y, x + y^3).have_common_factors()
381
+ False
382
+ """
383
+ L = [c.defining_polynomial() for c in self._curves]
384
+ C = combinations(L, 2)
385
+ return any(f1.gcd(f2).degree() > 0 for f1, f2 in C)
386
+
387
+ def reduce(self, clean=False, verbose=False):
388
+ r"""
389
+ Replace the curves by their reduction.
390
+
391
+ INPUT:
392
+
393
+ - ``clean`` -- boolean (default: ``False``); if ``False``
394
+ and there are common factors it returns ``None`` and
395
+ a warning message. If ``True``, the common factors are kept
396
+ only in the first occurrence.
397
+
398
+ EXAMPLES::
399
+
400
+ sage: H.<x, y> = AffinePlaneCurveArrangements(QQ)
401
+ sage: A = H(y^2, (x + y)^3 * (x^2 + x * y + y^2))
402
+ sage: A.reduce()
403
+ Arrangement (y, x^3 + 2*x^2*y + 2*x*y^2 + y^3) in Affine Space
404
+ of dimension 2 over Rational Field
405
+ sage: C = H(x*y, x*(y + 1))
406
+ sage: C.reduce(verbose=True)
407
+ Some curves have common components
408
+ sage: C.reduce(clean=True)
409
+ Arrangement (x*y, y + 1) in Affine Space of dimension 2
410
+ over Rational Field
411
+ sage: C = H(x*y, x)
412
+ sage: C.reduce(clean=True)
413
+ Arrangement (x*y) in Affine Space of dimension 2 over Rational Field
414
+ """
415
+ P = self.parent()
416
+ L = [self._curves[0].defining_polynomial().radical()]
417
+ for c in self._curves[1:]:
418
+ g = c.defining_polynomial().radical()
419
+ for f in L:
420
+ d = g.gcd(f)
421
+ if d.degree() > 0 and not clean:
422
+ if verbose:
423
+ print("Some curves have common components")
424
+ return None
425
+ g //= d
426
+ if g.degree() > 0:
427
+ L.append(g)
428
+ return P(*L)
429
+
430
+
431
+ class AffinePlaneCurveArrangementElement(PlaneCurveArrangementElement):
432
+ """
433
+ An ordered affine plane curve arrangement.
434
+ """
435
+ def __init__(self, parent, curves, check=True) -> None:
436
+ """
437
+ Construct an ordered affine plane curve arrangement.
438
+
439
+ INPUT:
440
+
441
+ - ``parent`` -- the parent :class:`AffinePlaneCurveArrangements`
442
+
443
+ - ``curves`` -- tuple of curves
444
+
445
+ EXAMPLES::
446
+
447
+ sage: H.<x, y> = AffinePlaneCurveArrangements(QQ)
448
+ sage: elt = H(x, y); elt
449
+ Arrangement (x, y) in Affine Space of dimension 2 over Rational Field
450
+ sage: TestSuite(elt).run()
451
+ """
452
+ Element.__init__(self, parent)
453
+ self._curves = tuple(curves)
454
+ if check:
455
+ if not all(isinstance(h, AffinePlaneCurve) for h in curves):
456
+ raise ValueError("not all elements are curves")
457
+ if not all(h.ambient_space() is self.parent().ambient_space()
458
+ for h in curves):
459
+ raise ValueError("not all curves are in the same ambient space")
460
+ self._braid_monodromy_non_vertical = None
461
+ self._braid_monodromy_vertical = None
462
+ self._strands_nonvertical = None
463
+ self._strands_vertical = None
464
+ self._fundamental_group_nonsimpl_nonvertical = None
465
+ self._fundamental_group_nonsimpl_vertical = None
466
+ self._fundamental_group_simpl_nonvertical = None
467
+ self._fundamental_group_simpl_vertical = None
468
+ self._meridians_nonsimpl_nonvertical = None
469
+ self._meridians_nonsimpl_vertical = None
470
+ self._meridians_simpl_nonvertical = None
471
+ self._meridians_simpl_vertical = None
472
+ self._vertical_lines_in_braid_mon = None
473
+
474
+ def fundamental_group(self, simplified=True, vertical=True,
475
+ projective=False):
476
+ r"""
477
+ Return the fundamental group of the complement of the union
478
+ of affine plane curves in `\CC^2`.
479
+
480
+ INPUT:
481
+
482
+ - ``vertical`` -- boolean (default: ``True``); if ``True``, there
483
+ are no vertical asymptotes, and there are vertical lines, then a
484
+ simplified braid :func:`braid_monodromy` is used
485
+
486
+ - ``simplified`` -- boolean (default: ``True``); if it is ``True``, the
487
+ group is simplified
488
+
489
+ - ``projective`` -- boolean (default: ``False``); to be used in the
490
+ method for projective curves
491
+
492
+ OUTPUT: a finitely presented group
493
+
494
+ .. NOTE::
495
+
496
+ This functionality requires the ``sirocco`` package to be installed.
497
+
498
+ EXAMPLES::
499
+
500
+ sage: # needs sirocco
501
+ sage: H.<x, y> = AffinePlaneCurveArrangements(QQ)
502
+ sage: A = H(y^2 + x, y + x - 1, x)
503
+ sage: A.fundamental_group()
504
+ Finitely presented group
505
+ < x0, x1, x2 | x2*x0*x2^-1*x0^-1, x1*x0*x1^-1*x0^-1, (x2*x1)^2*(x2^-1*x1^-1)^2 >
506
+ sage: A.meridians()
507
+ {0: [x1, x2*x1*x2^-1], 1: [x0], 2: [x2],
508
+ 3: [x1^-1*x2^-1*x1^-1*x0^-1]}
509
+ sage: G = A.fundamental_group(simplified=False)
510
+ sage: G.sorted_presentation()
511
+ Finitely presented group
512
+ < x0, x1, x2, x3 | x3^-1*x2^-1*x3*x0*x1*x0^-1,
513
+ x3^-1*x1^-1*x3*x0*x1*x0^-1*x2^-1*x0^-1*(x2*x0)^2*x1^-1*x0^-1,
514
+ x3^-1*x0^-1*x3*x0*x1*x0^-1*x2^-1*x0*x2*x0*x1^-1*x0^-1,
515
+ x2^-1*x0^-1*x2*x0, x1^-1*x0^-1*x1*x0 >
516
+ sage: A.meridians(simplified=False)
517
+ {0: [x1, x2], 1: [x0], 2: [x3], 3: [x3^-1*x2^-1*x1^-1*x0^-1]}
518
+ sage: A.fundamental_group(vertical=False)
519
+ Finitely presented group
520
+ < x0, x1, x2 | x2*x1^-1*x2^-1*x1, x1*x0*x1^-1*x0^-1, (x0*x2)^2*(x0^-1*x2^-1)^2 >
521
+ sage: A.meridians(vertical=False)
522
+ {0: [x2, x0*x2*x0^-1], 1: [x1], 2: [x0], 3: [x0*x2^-1*x0^-1*x2^-1*x1^-1*x0^-1]}
523
+ sage: G = A.fundamental_group(simplified=False, vertical=False)
524
+ sage: G.sorted_presentation()
525
+ Finitely presented group
526
+ < x0, x1, x2, x3 | x3^-1*x2^-1*x1^-1*x2*x3*x2^-1*x1*x2,
527
+ x3^-1*x2^-1*x1^-1*x2*x3*x2^-1*x1*x2,
528
+ (x3^-1*x2^-1*x0^-1*x2)^2*(x3*x2^-1*x0*x2)^2,
529
+ x3^-1*x2^-1*x0^-1*x2*x3^-1*x2^-1*x0*x2*x3*x2,
530
+ x1^-1*x0^-1*x1*x0 >
531
+ sage: A.meridians(simplified=False, vertical=False)
532
+ {0: [x2, x3], 1: [x1], 2: [x0], 3: [x3^-1*x2^-1*x1^-1*x0^-1]}
533
+ sage: A = H(x * y^2 + x + y, y + x -1, x, y)
534
+ sage: G = A.fundamental_group()
535
+ sage: G.sorted_presentation()
536
+ Finitely presented group
537
+ < x0, x1, x2, x3 | x3^-1*x2^-1*x3*x2, x3^-1*x1^-1*x3*x1,
538
+ x3^-1*x0^-1*x3*x0, x2^-1*x1^-1*x2*x1,
539
+ x2^-1*x0^-1*x2*x0, x1^-1*x0^-1*x1*x0 >
540
+ """
541
+ if simplified and vertical:
542
+ computed = self._fundamental_group_simpl_vertical
543
+ elif simplified and not vertical:
544
+ computed = self._fundamental_group_simpl_nonvertical
545
+ elif not simplified and vertical:
546
+ computed = self._fundamental_group_nonsimpl_vertical
547
+ else:
548
+ computed = self._fundamental_group_nonsimpl_nonvertical
549
+ if computed:
550
+ return computed
551
+ K = self.base_ring()
552
+ R = self.coordinate_ring()
553
+ if not K.is_subring(QQbar):
554
+ raise TypeError('the base field is not in QQbar')
555
+ C = self.reduce()
556
+ L = C.defining_polynomials()
557
+ if vertical:
558
+ bm = self._braid_monodromy_vertical
559
+ else:
560
+ bm = self._braid_monodromy_non_vertical
561
+ if bm is not None: # bm could be []
562
+ if not vertical:
563
+ st = self._strands_nonvertical
564
+ d1 = prod(L).degree()
565
+ bd = (bm, st, {}, d1)
566
+ else:
567
+ st = self._strands_vertical
568
+ d1 = prod(L).degree(R.gen(1))
569
+ bd = (bm, st, self._vertical_lines_in_braid_mon, d1)
570
+ else:
571
+ bd = None
572
+ G, dic = fundamental_group_arrangement(L, simplified=simplified,
573
+ puiseux=True,
574
+ projective=projective,
575
+ vertical=vertical,
576
+ braid_data=bd)
577
+ if simplified and vertical:
578
+ self._fundamental_group_simpl_vertical = G
579
+ self._meridians_simpl_vertical = dic
580
+ elif simplified and not vertical:
581
+ self._fundamental_group_simpl_nonvertical = G
582
+ self._meridians_simpl_nonvertical = dic
583
+ elif not simplified and vertical:
584
+ self._fundamental_group_nonsimpl_vertical = G
585
+ self._meridians_nonsimpl_vertical = dic
586
+ else:
587
+ self._fundamental_group_nonsimpl_nonvertical = G
588
+ self._meridians_nonsimpl_nonvertical = dic
589
+ return G
590
+
591
+ def meridians(self, simplified=True, vertical=True) -> dict:
592
+ r"""
593
+ Return the meridians of each irreducible component.
594
+
595
+ OUTPUT:
596
+
597
+ A dictionary which associates the index of each curve with its meridians,
598
+ including the line at infinity if it can be omputed
599
+
600
+ .. NOTE::
601
+
602
+ This functionality requires the ``sirocco`` package to be installed
603
+ and :meth:`AffinePlaneCurveArrangements.fundamental_group` with the same options,
604
+ where some examples are shown.
605
+
606
+ EXAMPLES::
607
+
608
+ sage: # needs sirocco
609
+ sage: H.<x, y> = AffinePlaneCurveArrangements(QQ)
610
+ sage: A = H(x-1, y, x, y - 1)
611
+ sage: A.fundamental_group()
612
+ Finitely presented group
613
+ < x0, x1, x2, x3 | x2*x0*x2^-1*x0^-1, x2*x1*x2^-1*x1^-1,
614
+ x3*x0*x3^-1*x0^-1, x3*x1*x3^-1*x1^-1 >
615
+ sage: A.meridians()
616
+ {0: [x2], 1: [x0], 2: [x3], 3: [x1], 4: [x3^-1*x2^-1*x1^-1*x0^-1]}
617
+ """
618
+ if simplified and vertical:
619
+ computed = self._meridians_simpl_vertical
620
+ elif simplified and not vertical:
621
+ computed = self._meridians_simpl_nonvertical
622
+ elif not simplified and vertical:
623
+ computed = self._meridians_nonsimpl_vertical
624
+ else:
625
+ computed = self._meridians_nonsimpl_nonvertical
626
+ if computed:
627
+ return dict(computed)
628
+ self.fundamental_group(simplified=simplified, vertical=vertical)
629
+ if simplified and vertical:
630
+ return dict(self._meridians_simpl_vertical)
631
+ elif simplified and not vertical:
632
+ return dict(self._meridians_group_simpl_nonvertical)
633
+ elif not simplified and vertical:
634
+ return dict(self._meridians_nonsimpl_vertical)
635
+ else:
636
+ return dict(self._meridians_nonsimpl_nonvertical)
637
+
638
+ def braid_monodromy(self, vertical=True):
639
+ r"""
640
+ Return the braid monodromy of the complement of the union
641
+ of affine plane curves in `\CC^2`.
642
+
643
+ If there are vertical asymptotes a change of variable is done.
644
+
645
+ INPUT:
646
+
647
+ - ``vertical`` -- boolean (default: ``True``); if it is ``True``, there
648
+ are no vertical asymptotes, and there are vertical lines, then a
649
+ simplified :func:`braid_monodromy` is computed.
650
+
651
+ OUTPUT:
652
+
653
+ A braid monodromy with dictionaries identifying strands with components
654
+ and braids with vertical lines.
655
+
656
+ .. NOTE::
657
+
658
+ This functionality requires the ``sirocco`` package to be installed.
659
+
660
+ EXAMPLES::
661
+
662
+ sage: # needs sirocco
663
+ sage: H.<x, y> = AffinePlaneCurveArrangements(QQ)
664
+ sage: A = H(y^2 + x, y + x - 1, x)
665
+ sage: A.braid_monodromy(vertical=False)
666
+ [s1*s0*(s1*s2*s1)^2*s2*(s1^-1*s2^-1)^2*s1^-1*s0^-1*s1^-1,
667
+ s1*s0*(s1*s2)^2*s2*s1^-1*s2^-1*s1^-1*s0^-1*s1^-1,
668
+ s1*s0*s1*s2*(s1*s2^-1)^2*s0*s1*s2*s1*s0*s2^-1*s1^-3*s2*s1^-1*s2^-1*s1^-1*s0^-1*s1^-1,
669
+ s1*s0*s1*s2*s1*s2^-1*s1^4*s2*s1^-1*s2^-1*s1^-1*s0^-1*s1^-1,
670
+ s1*s0*s1*s2*s1*s2^-1*s1^-1*s2*s0^-1*s1^-1]
671
+ sage: A.braid_monodromy(vertical=True)
672
+ [s1*s0*s1*s0^-1*s1^-1*s0, s0^-1*s1*s0*s1^-1*s0, s0^-1*s1^2*s0]
673
+ """
674
+ if vertical:
675
+ computed = self._braid_monodromy_vertical
676
+ else:
677
+ computed = self._braid_monodromy_non_vertical
678
+ if computed is not None:
679
+ return computed
680
+ K = self.base_ring()
681
+ if not K.is_subring(QQbar):
682
+ raise TypeError('the base field is not in QQbar')
683
+ L = self.defining_polynomials()
684
+ bm, dic, dv, d1 = braid_monodromy(prod(L), arrangement=L,
685
+ vertical=vertical)
686
+ if vertical:
687
+ self._braid_monodromy_vertical = bm
688
+ self._strands_vertical = dic
689
+ self._vertical_lines_in_braid_mon = dv
690
+ else:
691
+ self._braid_monodromy_non_vertical = bm
692
+ self._strands_nonvertical = dic
693
+ return bm
694
+
695
+ def strands(self):
696
+ r"""
697
+ Return the strands for each member of the arrangement.
698
+
699
+ OUTPUT:
700
+
701
+ A dictionary which associates to the index of each strand
702
+ its associated component if the braid monodromy has been
703
+ calculated with ``vertical=False``.
704
+
705
+ .. NOTE::
706
+
707
+ This functionality requires the ``sirocco`` package to be installed.
708
+
709
+ EXAMPLES::
710
+
711
+ sage: # needs sirocco
712
+ sage: H.<x, y> = AffinePlaneCurveArrangements(QQ)
713
+ sage: A = H(y^2 + x, y + x - 1, x)
714
+ sage: bm = A.braid_monodromy()
715
+ sage: A.strands()
716
+ {0: 2, 1: 1, 2: 0, 3: 0}
717
+ """
718
+ if not self._strands_nonvertical:
719
+ self._braid_monodromy = self.braid_monodromy(vertical=False)
720
+ return self._strands_nonvertical
721
+
722
+ def vertical_strands(self):
723
+ r"""
724
+ Return the strands if the braid monodromy has been computed with
725
+ the vertical option.
726
+
727
+ OUTPUT:
728
+
729
+ A dictionary which associates to the index of each strand
730
+ its associated component if the braid monodromy has been
731
+ calculated with ``vertical=True``.
732
+
733
+ .. NOTE::
734
+
735
+ This functionality requires the ``sirocco`` package to be installed.
736
+
737
+ EXAMPLES::
738
+
739
+ sage: # needs sirocco
740
+ sage: H.<x, y> = AffinePlaneCurveArrangements(QQ)
741
+ sage: A = H(y^2 + x, y + x - 1, x)
742
+ sage: A.vertical_strands()
743
+ {0: 1, 1: 0, 2: 0}
744
+ sage: A.braid_monodromy(vertical=True)
745
+ [s1*s0*s1*s0^-1*s1^-1*s0, s0^-1*s1*s0*s1^-1*s0, s0^-1*s1^2*s0]
746
+ """
747
+ if not self._strands_vertical:
748
+ self.braid_monodromy(vertical=True)
749
+ return self._strands_vertical
750
+
751
+ def vertical_lines_in_braid_monodromy(self):
752
+ r"""
753
+ Return the vertical lines in the arrangement.
754
+
755
+ OUTPUT:
756
+
757
+ A dictionary which associates the index of a braid
758
+ to the index of the vertical line associated to the braid.
759
+
760
+ .. NOTE::
761
+
762
+ This functionality requires the ``sirocco`` package to be installed.
763
+
764
+ EXAMPLES::
765
+
766
+ sage: # needs sirocco
767
+ sage: H.<x, y> = AffinePlaneCurveArrangements(QQ)
768
+ sage: A = H(y^2 + x, y + x - 1, x)
769
+ sage: A.vertical_lines_in_braid_monodromy()
770
+ {1: 2}
771
+ sage: A.braid_monodromy(vertical=True)
772
+ [s1*s0*s1*s0^-1*s1^-1*s0, s0^-1*s1*s0*s1^-1*s0, s0^-1*s1^2*s0]
773
+ """
774
+ if not self._vertical_lines_in_braid_mon:
775
+ self.braid_monodromy(vertical=True)
776
+ return self._vertical_lines_in_braid_mon
777
+
778
+
779
+ class ProjectivePlaneCurveArrangementElement(PlaneCurveArrangementElement):
780
+ """
781
+ An ordered projective plane curve arrangement.
782
+ """
783
+ def __init__(self, parent, curves, check=True):
784
+ """
785
+ Construct an ordered projective plane curve arrangement.
786
+
787
+ INPUT:
788
+
789
+ - ``parent`` -- the parent :class:`ProjectivePlaneCurveArrangements`
790
+
791
+ - ``curves`` -- tuple of curves
792
+
793
+ EXAMPLES::
794
+
795
+ sage: H.<x, y, z> = ProjectivePlaneCurveArrangements(QQ)
796
+ sage: elt = H(x, y, z); elt
797
+ Arrangement (x, y, z) in Projective Space of dimension 2 over Rational Field
798
+ sage: TestSuite(elt).run()
799
+ """
800
+ Element.__init__(self, parent)
801
+ self._curves = tuple(curves)
802
+ if check:
803
+ if not all(isinstance(h, ProjectivePlaneCurve) for h in curves):
804
+ raise ValueError("not all elements are curves")
805
+ if not all(h.ambient_space() is self.parent().ambient_space()
806
+ for h in curves):
807
+ raise ValueError("not all curves are in the same ambient space")
808
+ self._fundamental_group_nonsimpl = None
809
+ self._fundamental_group_simpl = None
810
+ self._meridians_nonsimpl = None
811
+ self._meridians_simpl = None
812
+
813
+ def fundamental_group(self, simplified=True):
814
+ r"""
815
+ Return the fundamental group of the complement of the union
816
+ of an arrangement of projective plane curves
817
+ in the projective plane.
818
+
819
+ INPUT:
820
+
821
+ - ``simplified`` -- boolean (default: ``True``); set if the group
822
+ is simplified
823
+
824
+ OUTPUT: a finitely presented group
825
+
826
+ .. NOTE::
827
+
828
+ This functionality requires the ``sirocco`` package to be installed.
829
+
830
+ EXAMPLES::
831
+
832
+ sage: # needs sirocco
833
+ sage: H.<x, y, z> = ProjectivePlaneCurveArrangements(QQ)
834
+ sage: H(z).fundamental_group()
835
+ Finitely presented group < | >
836
+ sage: H(x*y).fundamental_group()
837
+ Finitely presented group < x | >
838
+ sage: A = H(y^2 + x*z, y + x - z, x)
839
+ sage: A.fundamental_group().sorted_presentation()
840
+ Finitely presented group < x0, x1 | x1^-1*x0^-1*x1*x0 >
841
+ sage: A.meridians()
842
+ {0: [x1], 1: [x0], 2: [x0^-1*x1^-2]}
843
+ sage: G = A.fundamental_group(simplified=False)
844
+ sage: G.sorted_presentation()
845
+ Finitely presented group
846
+ < x0, x1, x2, x3 | x3^-1*x2^-1*x1^-1*x0^-1, x3^-1*x2^-1*x3*x0*x1*x0^-1,
847
+ x3^-1*x1^-1*x3*x0*x1*x0^-1*x2^-1*x0^-1*(x2*x0)^2*x1^-1*x0^-1,
848
+ x3^-1*x0^-1*x3*x0*x1*x0^-1*x2^-1*x0*x2*x0*x1^-1*x0^-1,
849
+ x2^-1*x0^-1*x2*x0, x1^-1*x0^-1*x1*x0 >
850
+ sage: A.meridians(simplified=False)
851
+ {0: [x1, x2], 1: [x0], 2: [x3]}
852
+ sage: A = H(y^2 + x*z, z, x)
853
+ sage: A.fundamental_group()
854
+ Finitely presented group < x0, x1 | (x1*x0)^2*(x1^-1*x0^-1)^2 >
855
+ sage: A = H(y^2 + x*z, z*x, y)
856
+ sage: A.fundamental_group()
857
+ Finitely presented group
858
+ < x0, x1, x2 | x2*x0*x1*x0^-1*x2^-1*x1^-1,
859
+ x1*(x2*x0)^2*x2^-1*x1^-1*x0^-1*x2^-1*x0^-1 >
860
+ """
861
+ if simplified:
862
+ computed = self._fundamental_group_simpl
863
+ else:
864
+ computed = self._fundamental_group_nonsimpl
865
+ if computed:
866
+ return computed
867
+ H = self.parent()
868
+ K = self.base_ring()
869
+ R = self.coordinate_ring()
870
+ x, y, z = R.gens()
871
+ if not K.is_subring(QQbar):
872
+ raise TypeError('the base field is not in QQbar')
873
+ C = self.reduce()
874
+ n = len(C)
875
+ infinity = Curve(z)
876
+ infinity_in_C = infinity in C
877
+ if infinity_in_C and n == 1:
878
+ G = FreeGroup(0) / []
879
+ if simplified:
880
+ self._fundamental_group_simpl = G
881
+ self._meridians_simpl = {0: [G.one()]}
882
+ else:
883
+ self._fundamental_group_nonsimpl = G
884
+ self._meridians_nonsimpl = {0: [G.one()]}
885
+ return G
886
+ if infinity_in_C:
887
+ j = C.curves().index(infinity)
888
+ C = H(C.curves()[:j] + C.curves()[j + 1:])
889
+ infinity_divides = False
890
+ for j, c in enumerate(C):
891
+ g = c.defining_polynomial()
892
+ infinity_divides = z.divides(g)
893
+ if infinity_divides:
894
+ h = R(g / z)
895
+ C = H(C.curves()[:j] + (h, ) + C.curves()[j + 1:])
896
+ break
897
+ affine = AffinePlaneCurveArrangements(K, names=('u', 'v'))
898
+ u, v = affine.gens()
899
+ affines = [f.defining_polynomial().subs({x: u, y: v, z: 1}) for f in C]
900
+ changes = any(g.degree(v) < g.degree() > 1 for g in affines)
901
+ while changes:
902
+ affines = [f.subs({u: u + v}) for f in affines]
903
+ changes = any(g.degree(v) < g.degree() > 1 for g in affines)
904
+ C_affine = affine(affines)
905
+ proj = not (infinity_divides or infinity_in_C)
906
+ G = C_affine.fundamental_group(simplified=simplified, vertical=True,
907
+ projective=proj)
908
+ dic = C_affine.meridians(simplified=simplified, vertical=True)
909
+ if infinity_in_C:
910
+ dic1 = {}
911
+ for k in range(j):
912
+ dic1[k] = dic[k]
913
+ dic1[j] = dic[n - 1]
914
+ for k in range(j + 1, n):
915
+ dic1[k] = dic[k - 1]
916
+ elif infinity_divides:
917
+ dic1 = {k: dic[k] for k in range(n)}
918
+ dic1[j] += dic[n]
919
+ else:
920
+ dic1 = dic
921
+ if simplified:
922
+ self._fundamental_group_simpl = G
923
+ self._meridians_simpl = dic1
924
+ else:
925
+ self._fundamental_group_nonsimpl = G
926
+ self._meridians_nonsimpl = dic1
927
+ return G
928
+
929
+ def meridians(self, simplified=True) -> dict:
930
+ r"""
931
+ Return the meridians of each irreducible component.
932
+
933
+ OUTPUT:
934
+
935
+ A dictionary which associates the index of each curve with
936
+ its meridians, including the line at infinity if it can be
937
+ computed
938
+
939
+ .. NOTE::
940
+
941
+ This function requires the ``sirocco`` package to be installed and
942
+ :func:`ProjectivePlaneCurveArrangements.fundamental_group`
943
+ with the same options, where some examples are shown.
944
+
945
+ EXAMPLES::
946
+
947
+ sage: # needs sirocco
948
+ sage: H.<x, y, z> = ProjectivePlaneCurveArrangements(QQ)
949
+ sage: A = H(y^2 + x*z, y + x - z, x)
950
+ sage: A.fundamental_group().sorted_presentation()
951
+ Finitely presented group < x0, x1 | x1^-1*x0^-1*x1*x0 >
952
+ sage: A.meridians()
953
+ {0: [x1], 1: [x0], 2: [x0^-1*x1^-2]}
954
+ sage: A = H(y^2 + x*z, z, x)
955
+ sage: A.fundamental_group()
956
+ Finitely presented group < x0, x1 | (x1*x0)^2*(x1^-1*x0^-1)^2 >
957
+ sage: A.meridians()
958
+ {0: [x0, x1*x0*x1^-1], 1: [x0^-1*x1^-1*x0^-1], 2: [x1]}
959
+ sage: A = H(y^2 + x*z, z*x, y)
960
+ sage: A.fundamental_group()
961
+ Finitely presented group < x0, x1, x2 | x2*x0*x1*x0^-1*x2^-1*x1^-1,
962
+ x1*(x2*x0)^2*x2^-1*x1^-1*x0^-1*x2^-1*x0^-1 >
963
+ sage: A.meridians()
964
+ {0: [x0, x2*x0*x2^-1], 1: [x2, x0^-1*x2^-1*x1^-1*x0^-1], 2: [x1]}
965
+ """
966
+ if simplified:
967
+ computed = self._meridians_simpl
968
+ else:
969
+ computed = self._meridians_nonsimpl
970
+ if computed:
971
+ return dict(computed)
972
+ self._fundamental_group(simplified=simplified)
973
+ if simplified:
974
+ return dict(self._meridians_simpl)
975
+ else:
976
+ return dict(self._meridians_nonsimpl)
977
+
978
+
979
+ class PlaneCurveArrangements(UniqueRepresentation, Parent):
980
+ """
981
+ Plane curve arrangements.
982
+
983
+ INPUT:
984
+
985
+ - ``base_ring`` -- ring; the base ring
986
+
987
+ - ``names`` -- tuple of strings; the variable names
988
+
989
+ EXAMPLES::
990
+
991
+ sage: H.<x, y> = AffinePlaneCurveArrangements(QQ)
992
+ sage: H(x, y^2, x-1, y-1)
993
+ Arrangement (x, y^2, x - 1, y - 1) in Affine Space
994
+ of dimension 2 over Rational Field
995
+ """
996
+ Element = PlaneCurveArrangementElement
997
+
998
+ @staticmethod
999
+ def __classcall__(cls, base, names: tuple[str, ...] = ()):
1000
+ """
1001
+ Normalize the inputs to ensure a unique representation.
1002
+
1003
+ TESTS::
1004
+
1005
+ sage: H.<x, y> = AffinePlaneCurveArrangements(QQ)
1006
+ sage: K = AffinePlaneCurveArrangements(QQ, names=('x', 'y'))
1007
+ sage: H is K
1008
+ True
1009
+ """
1010
+ names = normalize_names(len(names), names)
1011
+ return super().__classcall__(cls, base, names)
1012
+
1013
+ def __init__(self, base_ring, names: tuple[str, ...] = ()):
1014
+ """
1015
+ Initialize ``self``.
1016
+
1017
+ TESTS::
1018
+
1019
+ sage: H.<x, y> = AffinePlaneCurveArrangements(QQ)
1020
+ sage: TestSuite(H).run()
1021
+ """
1022
+ if base_ring not in _Fields:
1023
+ raise ValueError('base ring must be a field')
1024
+ super().__init__(base_ring, names=names, category=Sets())
1025
+ self._embedded = None
1026
+ if len(names) == 2:
1027
+ self._embedded = 'affine'
1028
+ elif len(names) == 3:
1029
+ self._embedded = 'projective'
1030
+
1031
+ def coordinate_ring(self):
1032
+ """
1033
+ Return the coordinate ring.
1034
+
1035
+ OUTPUT: the coordinate ring of the curve arrangement
1036
+
1037
+ EXAMPLES::
1038
+
1039
+ sage: L.<x, y> = AffinePlaneCurveArrangements(QQ)
1040
+ sage: L.coordinate_ring()
1041
+ Multivariate Polynomial Ring in x, y over Rational Field
1042
+ """
1043
+ return PolynomialRing(self.base_ring(), self.variable_names())
1044
+
1045
+ def change_ring(self, base_ring):
1046
+ """
1047
+ Return curve arrangements over a different base ring.
1048
+
1049
+ INPUT:
1050
+
1051
+ - ``base_ring`` -- a ring; the new base ring
1052
+
1053
+ OUTPUT:
1054
+
1055
+ A new :class:`PlaneCurveArrangements` instance over the new
1056
+ base ring
1057
+
1058
+ EXAMPLES::
1059
+
1060
+ sage: L.<x, y> = AffinePlaneCurveArrangements(QQ)
1061
+ sage: L.change_ring(RR).base_ring()
1062
+ Real Field with 53 bits of precision
1063
+
1064
+ TESTS::
1065
+
1066
+ sage: L.change_ring(QQ) is L
1067
+ True
1068
+ """
1069
+ # return self.__class__(base_ring, names=self.variable_names())
1070
+ # line below is ugly but line above does not work
1071
+ return self.__reduce__()[1][0](base_ring, names=self.variable_names())
1072
+
1073
+ @abstract_method
1074
+ def ambient_space(self):
1075
+ """
1076
+ Return the ambient space.
1077
+
1078
+ EXAMPLES::
1079
+
1080
+ sage: L.<x, y> = PlaneCurveArrangements(QQ)
1081
+ Traceback (most recent call last):
1082
+ ...
1083
+ NotImplementedError: <abstract method ambient_space at 0x...>
1084
+ sage: L.<x, y> = AffinePlaneCurveArrangements(QQ)
1085
+ sage: L.ambient_space()
1086
+ Affine Space of dimension 2 over Rational Field
1087
+ sage: L.<x, y, z> = ProjectivePlaneCurveArrangements(QQ)
1088
+ sage: L.ambient_space()
1089
+ Projective Space of dimension 2 over Rational Field
1090
+ """
1091
+
1092
+ def _repr_(self):
1093
+ """
1094
+ Return a string representation.
1095
+
1096
+ OUTPUT: string
1097
+
1098
+ EXAMPLES::
1099
+
1100
+ sage: L.<x, y> = AffinePlaneCurveArrangements(QQ); L
1101
+ Curve arrangements in Affine Space of dimension 2 over Rational Field
1102
+ """
1103
+ return 'Curve arrangements in {}'.format(self.ambient_space())
1104
+
1105
+ def _element_constructor_(self, *args, **kwds):
1106
+ """
1107
+ Construct an element of ``self``.
1108
+
1109
+ INPUT:
1110
+
1111
+ - ``*args`` -- positional arguments, each defining a curve
1112
+
1113
+ EXAMPLES::
1114
+
1115
+ sage: L.<x, y> = AffinePlaneCurveArrangements(QQ)
1116
+ sage: A = L(x, y); A
1117
+ Arrangement (x, y) in Affine Space of dimension 2 over Rational Field
1118
+ sage: L([x, y]) == A
1119
+ True
1120
+ sage: L(Curve(x), Curve(y)) == A
1121
+ True
1122
+ sage: L(y, x) == A
1123
+ False
1124
+ """
1125
+ if len(args) == 1:
1126
+ if not isinstance(args[0], (tuple, list)):
1127
+ arg = (args[0], )
1128
+ else:
1129
+ arg = tuple(args[0])
1130
+ else:
1131
+ arg = tuple(args)
1132
+ ambient_space = self.ambient_space()
1133
+ R = ambient_space.coordinate_ring()
1134
+ curves: tuple[Any, ...] = ()
1135
+ for h in arg:
1136
+ try:
1137
+ ambient = h.ambient_space()
1138
+ if ambient == ambient_space:
1139
+ curves += (h, )
1140
+ else:
1141
+ raise TypeError('the curves do not have the same ambient space')
1142
+ except AttributeError:
1143
+ try:
1144
+ h = R(h)
1145
+ curves += (Curve(h), )
1146
+ except TypeError:
1147
+ raise TypeError('elements are not curves')
1148
+ return self.element_class(self, curves)
1149
+
1150
+ def _an_element_(self):
1151
+ """
1152
+ Return an element of ``self``.
1153
+
1154
+ TESTS::
1155
+
1156
+ sage: H.<t, s> = AffinePlaneCurveArrangements(QQ)
1157
+ sage: H._an_element_()
1158
+ Arrangement (t) in Affine Space of dimension 2 over Rational Field
1159
+ sage: H.<t, s, r> = ProjectivePlaneCurveArrangements(QQ)
1160
+ sage: H._an_element_()
1161
+ Arrangement (t) in Projective Space of dimension 2 over Rational Field
1162
+ """
1163
+ return self(self.gen(0))
1164
+
1165
+ @cached_method
1166
+ def ngens(self):
1167
+ """
1168
+ Return the number of variables, i.e. 2 or 3, kept for completeness.
1169
+
1170
+ OUTPUT: integer, 2 or 3, depending if the arrangement is projective or affine
1171
+
1172
+ EXAMPLES::
1173
+
1174
+ sage: L.<x, y> = AffinePlaneCurveArrangements(QQ)
1175
+ sage: L.ngens()
1176
+ 2
1177
+ sage: L.<x, y, z> = ProjectivePlaneCurveArrangements(QQ)
1178
+ sage: L.ngens()
1179
+ 3
1180
+ """
1181
+ return len(self.variable_names())
1182
+
1183
+ def gens(self) -> tuple:
1184
+ """
1185
+ Return the coordinates.
1186
+
1187
+ OUTPUT: a tuple of linear expressions, one for each linear variable
1188
+
1189
+ EXAMPLES::
1190
+
1191
+ sage: L = AffinePlaneCurveArrangements(QQ, ('x', 'y'))
1192
+ sage: L.gens()
1193
+ (x, y)
1194
+ sage: L = ProjectivePlaneCurveArrangements(QQ, ('x', 'y', 'z'))
1195
+ sage: L.gens()
1196
+ (x, y, z)
1197
+ """
1198
+ return self.ambient_space().gens()
1199
+
1200
+ def gen(self, i):
1201
+ """
1202
+ Return the `i`-th coordinate.
1203
+
1204
+ INPUT:
1205
+
1206
+ - ``i`` -- integer
1207
+
1208
+ OUTPUT: a variable
1209
+
1210
+ EXAMPLES::
1211
+
1212
+ sage: L.<x, y> = AffinePlaneCurveArrangements(QQ)
1213
+ sage: L.gen(1)
1214
+ y
1215
+ sage: L.<x, y, z> = ProjectivePlaneCurveArrangements(QQ)
1216
+ sage: L.gen(2)
1217
+ z
1218
+ """
1219
+ return self.gens()[i]
1220
+
1221
+
1222
+ class AffinePlaneCurveArrangements(PlaneCurveArrangements):
1223
+ """
1224
+ Affine curve arrangements.
1225
+
1226
+ INPUT:
1227
+
1228
+ - ``base_ring`` -- ring; the base ring
1229
+
1230
+ - ``names`` -- tuple of strings; the variable names
1231
+
1232
+ EXAMPLES::
1233
+
1234
+ sage: H.<x, y> = AffinePlaneCurveArrangements(QQ)
1235
+ sage: H(x, y^2, x-1, y-1)
1236
+ Arrangement (x, y^2, x - 1, y - 1) in Affine Space
1237
+ of dimension 2 over Rational Field
1238
+ """
1239
+ Element = AffinePlaneCurveArrangementElement
1240
+
1241
+ def ambient_space(self):
1242
+ """
1243
+ Return the ambient space.
1244
+
1245
+ EXAMPLES::
1246
+
1247
+ sage: L.<x, y> = AffinePlaneCurveArrangements(QQ)
1248
+ sage: L.ambient_space()
1249
+ Affine Space of dimension 2 over Rational Field
1250
+ """
1251
+ return AffineSpace(self.base_ring(), 2, self._names)
1252
+
1253
+
1254
+ class ProjectivePlaneCurveArrangements(PlaneCurveArrangements):
1255
+ """
1256
+ Projective curve arrangements.
1257
+
1258
+ INPUT:
1259
+
1260
+ - ``base_ring`` -- ring; the base ring
1261
+
1262
+ - ``names`` -- tuple of strings; the variable names
1263
+
1264
+ EXAMPLES::
1265
+
1266
+ sage: H.<x, y, z> = ProjectivePlaneCurveArrangements(QQ)
1267
+ sage: H(x, y^2, x-z, y-z)
1268
+ Arrangement (x, y^2, x - z, y - z) in Projective Space
1269
+ of dimension 2 over Rational Field
1270
+ """
1271
+ Element = ProjectivePlaneCurveArrangementElement
1272
+
1273
+ def ambient_space(self):
1274
+ """
1275
+ Return the ambient space.
1276
+
1277
+ EXAMPLES::
1278
+
1279
+ sage: L.<x, y, z> = ProjectivePlaneCurveArrangements(QQ)
1280
+ sage: L.ambient_space()
1281
+ Projective Space of dimension 2 over Rational Field
1282
+ """
1283
+ return ProjectiveSpace(self.base_ring(), 2, self._names)