passagemath-schemes 10.6.47__cp312-cp312-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.
- passagemath_schemes/.dylibs/libflint.22.0.dylib +0 -0
- passagemath_schemes/.dylibs/libgmp.10.dylib +0 -0
- passagemath_schemes/.dylibs/libgmpxx.4.dylib +0 -0
- passagemath_schemes/.dylibs/libmpfr.6.dylib +0 -0
- passagemath_schemes/__init__.py +3 -0
- passagemath_schemes-10.6.47.dist-info/METADATA +204 -0
- passagemath_schemes-10.6.47.dist-info/METADATA.bak +205 -0
- passagemath_schemes-10.6.47.dist-info/RECORD +311 -0
- passagemath_schemes-10.6.47.dist-info/WHEEL +6 -0
- passagemath_schemes-10.6.47.dist-info/top_level.txt +3 -0
- sage/all__sagemath_schemes.py +23 -0
- sage/databases/all__sagemath_schemes.py +7 -0
- sage/databases/cremona.py +1723 -0
- sage/dynamics/all__sagemath_schemes.py +2 -0
- sage/dynamics/arithmetic_dynamics/affine_ds.py +1083 -0
- sage/dynamics/arithmetic_dynamics/all.py +14 -0
- sage/dynamics/arithmetic_dynamics/berkovich_ds.py +1101 -0
- sage/dynamics/arithmetic_dynamics/dynamical_semigroup.py +1543 -0
- sage/dynamics/arithmetic_dynamics/endPN_automorphism_group.py +2426 -0
- sage/dynamics/arithmetic_dynamics/endPN_minimal_model.py +1169 -0
- sage/dynamics/arithmetic_dynamics/generic_ds.py +663 -0
- sage/dynamics/arithmetic_dynamics/product_projective_ds.py +339 -0
- sage/dynamics/arithmetic_dynamics/projective_ds.py +9558 -0
- sage/dynamics/arithmetic_dynamics/projective_ds_helper.cpython-312-darwin.so +0 -0
- sage/dynamics/arithmetic_dynamics/projective_ds_helper.pyx +301 -0
- sage/dynamics/arithmetic_dynamics/wehlerK3.py +2576 -0
- sage/lfunctions/all.py +18 -0
- sage/lfunctions/dokchitser.py +745 -0
- sage/lfunctions/pari.py +818 -0
- sage/lfunctions/zero_sums.cpython-312-darwin.so +0 -0
- sage/lfunctions/zero_sums.pyx +1847 -0
- sage/modular/abvar/abvar.py +5135 -0
- sage/modular/abvar/abvar_ambient_jacobian.py +413 -0
- sage/modular/abvar/abvar_newform.py +244 -0
- sage/modular/abvar/all.py +8 -0
- sage/modular/abvar/constructor.py +186 -0
- sage/modular/abvar/cuspidal_subgroup.py +371 -0
- sage/modular/abvar/finite_subgroup.py +896 -0
- sage/modular/abvar/homology.py +720 -0
- sage/modular/abvar/homspace.py +998 -0
- sage/modular/abvar/lseries.py +415 -0
- sage/modular/abvar/morphism.py +935 -0
- sage/modular/abvar/torsion_point.py +274 -0
- sage/modular/abvar/torsion_subgroup.py +740 -0
- sage/modular/all.py +43 -0
- sage/modular/arithgroup/all.py +20 -0
- sage/modular/arithgroup/arithgroup_element.cpython-312-darwin.so +0 -0
- sage/modular/arithgroup/arithgroup_element.pyx +474 -0
- sage/modular/arithgroup/arithgroup_generic.py +1402 -0
- sage/modular/arithgroup/arithgroup_perm.py +2692 -0
- sage/modular/arithgroup/congroup.cpython-312-darwin.so +0 -0
- sage/modular/arithgroup/congroup.pyx +334 -0
- sage/modular/arithgroup/congroup_gamma.py +363 -0
- sage/modular/arithgroup/congroup_gamma0.py +692 -0
- sage/modular/arithgroup/congroup_gamma1.py +653 -0
- sage/modular/arithgroup/congroup_gammaH.py +1469 -0
- sage/modular/arithgroup/congroup_generic.py +628 -0
- sage/modular/arithgroup/congroup_sl2z.py +267 -0
- sage/modular/arithgroup/farey_symbol.cpython-312-darwin.so +0 -0
- sage/modular/arithgroup/farey_symbol.pyx +1066 -0
- sage/modular/arithgroup/tests.py +418 -0
- sage/modular/btquotients/all.py +4 -0
- sage/modular/btquotients/btquotient.py +3753 -0
- sage/modular/btquotients/pautomorphicform.py +2570 -0
- sage/modular/buzzard.py +100 -0
- sage/modular/congroup.py +29 -0
- sage/modular/congroup_element.py +13 -0
- sage/modular/cusps.py +1109 -0
- sage/modular/cusps_nf.py +1270 -0
- sage/modular/dims.py +569 -0
- sage/modular/dirichlet.py +3310 -0
- sage/modular/drinfeld_modform/all.py +2 -0
- sage/modular/drinfeld_modform/element.py +446 -0
- sage/modular/drinfeld_modform/ring.py +773 -0
- sage/modular/drinfeld_modform/tutorial.py +236 -0
- sage/modular/etaproducts.py +1065 -0
- sage/modular/hecke/algebra.py +746 -0
- sage/modular/hecke/all.py +20 -0
- sage/modular/hecke/ambient_module.py +1019 -0
- sage/modular/hecke/degenmap.py +119 -0
- sage/modular/hecke/element.py +325 -0
- sage/modular/hecke/hecke_operator.py +780 -0
- sage/modular/hecke/homspace.py +206 -0
- sage/modular/hecke/module.py +1767 -0
- sage/modular/hecke/morphism.py +174 -0
- sage/modular/hecke/submodule.py +989 -0
- sage/modular/hypergeometric_misc.cpython-312-darwin.so +0 -0
- sage/modular/hypergeometric_misc.pxd +4 -0
- sage/modular/hypergeometric_misc.pyx +166 -0
- sage/modular/hypergeometric_motive.py +2017 -0
- sage/modular/local_comp/all.py +2 -0
- sage/modular/local_comp/liftings.py +292 -0
- sage/modular/local_comp/local_comp.py +1071 -0
- sage/modular/local_comp/smoothchar.py +1825 -0
- sage/modular/local_comp/type_space.py +748 -0
- sage/modular/modform/all.py +30 -0
- sage/modular/modform/ambient.py +815 -0
- sage/modular/modform/ambient_R.py +177 -0
- sage/modular/modform/ambient_eps.py +306 -0
- sage/modular/modform/ambient_g0.py +124 -0
- sage/modular/modform/ambient_g1.py +204 -0
- sage/modular/modform/constructor.py +545 -0
- sage/modular/modform/cuspidal_submodule.py +708 -0
- sage/modular/modform/defaults.py +14 -0
- sage/modular/modform/eis_series.py +505 -0
- sage/modular/modform/eisenstein_submodule.py +663 -0
- sage/modular/modform/element.py +4131 -0
- sage/modular/modform/find_generators.py +59 -0
- sage/modular/modform/half_integral.py +154 -0
- sage/modular/modform/hecke_operator_on_qexp.py +247 -0
- sage/modular/modform/j_invariant.py +47 -0
- sage/modular/modform/l_series_gross_zagier.py +133 -0
- sage/modular/modform/l_series_gross_zagier_coeffs.cpython-312-darwin.so +0 -0
- sage/modular/modform/l_series_gross_zagier_coeffs.pyx +177 -0
- sage/modular/modform/notes.py +45 -0
- sage/modular/modform/numerical.py +514 -0
- sage/modular/modform/periods.py +14 -0
- sage/modular/modform/ring.py +1257 -0
- sage/modular/modform/space.py +1860 -0
- sage/modular/modform/submodule.py +118 -0
- sage/modular/modform/tests.py +64 -0
- sage/modular/modform/theta.py +110 -0
- sage/modular/modform/vm_basis.py +381 -0
- sage/modular/modform/weight1.py +220 -0
- sage/modular/modform_hecketriangle/abstract_ring.py +1932 -0
- sage/modular/modform_hecketriangle/abstract_space.py +2528 -0
- sage/modular/modform_hecketriangle/all.py +30 -0
- sage/modular/modform_hecketriangle/analytic_type.py +590 -0
- sage/modular/modform_hecketriangle/constructor.py +416 -0
- sage/modular/modform_hecketriangle/element.py +351 -0
- sage/modular/modform_hecketriangle/functors.py +752 -0
- sage/modular/modform_hecketriangle/graded_ring.py +541 -0
- sage/modular/modform_hecketriangle/graded_ring_element.py +2225 -0
- sage/modular/modform_hecketriangle/hecke_triangle_group_element.py +3352 -0
- sage/modular/modform_hecketriangle/hecke_triangle_groups.py +1432 -0
- sage/modular/modform_hecketriangle/readme.py +1214 -0
- sage/modular/modform_hecketriangle/series_constructor.py +580 -0
- sage/modular/modform_hecketriangle/space.py +1037 -0
- sage/modular/modform_hecketriangle/subspace.py +423 -0
- sage/modular/modsym/all.py +17 -0
- sage/modular/modsym/ambient.py +3846 -0
- sage/modular/modsym/boundary.py +1420 -0
- sage/modular/modsym/element.py +336 -0
- sage/modular/modsym/g1list.py +178 -0
- sage/modular/modsym/ghlist.py +182 -0
- sage/modular/modsym/hecke_operator.py +73 -0
- sage/modular/modsym/manin_symbol.cpython-312-darwin.so +0 -0
- sage/modular/modsym/manin_symbol.pxd +5 -0
- sage/modular/modsym/manin_symbol.pyx +497 -0
- sage/modular/modsym/manin_symbol_list.py +1295 -0
- sage/modular/modsym/modsym.py +400 -0
- sage/modular/modsym/modular_symbols.py +384 -0
- sage/modular/modsym/p1list_nf.py +1241 -0
- sage/modular/modsym/relation_matrix.py +591 -0
- sage/modular/modsym/relation_matrix_pyx.cpython-312-darwin.so +0 -0
- sage/modular/modsym/relation_matrix_pyx.pyx +108 -0
- sage/modular/modsym/space.py +2468 -0
- sage/modular/modsym/subspace.py +455 -0
- sage/modular/modsym/tests.py +375 -0
- sage/modular/multiple_zeta.py +2632 -0
- sage/modular/multiple_zeta_F_algebra.py +786 -0
- sage/modular/overconvergent/all.py +6 -0
- sage/modular/overconvergent/genus0.py +1878 -0
- sage/modular/overconvergent/hecke_series.py +1187 -0
- sage/modular/overconvergent/weightspace.py +778 -0
- sage/modular/pollack_stevens/all.py +4 -0
- sage/modular/pollack_stevens/distributions.py +874 -0
- sage/modular/pollack_stevens/fund_domain.py +1572 -0
- sage/modular/pollack_stevens/manin_map.py +859 -0
- sage/modular/pollack_stevens/modsym.py +1593 -0
- sage/modular/pollack_stevens/padic_lseries.py +417 -0
- sage/modular/pollack_stevens/sigma0.py +534 -0
- sage/modular/pollack_stevens/space.py +1076 -0
- sage/modular/quasimodform/all.py +3 -0
- sage/modular/quasimodform/element.py +845 -0
- sage/modular/quasimodform/ring.py +828 -0
- sage/modular/quatalg/all.py +3 -0
- sage/modular/quatalg/brandt.py +1642 -0
- sage/modular/ssmod/all.py +8 -0
- sage/modular/ssmod/ssmod.py +827 -0
- sage/rings/all__sagemath_schemes.py +1 -0
- sage/rings/polynomial/all__sagemath_schemes.py +1 -0
- sage/rings/polynomial/binary_form_reduce.py +585 -0
- sage/schemes/all.py +41 -0
- sage/schemes/berkovich/all.py +6 -0
- sage/schemes/berkovich/berkovich_cp_element.py +2582 -0
- sage/schemes/berkovich/berkovich_space.py +748 -0
- sage/schemes/curves/affine_curve.py +2928 -0
- sage/schemes/curves/all.py +33 -0
- sage/schemes/curves/closed_point.py +434 -0
- sage/schemes/curves/constructor.py +381 -0
- sage/schemes/curves/curve.py +542 -0
- sage/schemes/curves/plane_curve_arrangement.py +1283 -0
- sage/schemes/curves/point.py +463 -0
- sage/schemes/curves/projective_curve.py +3026 -0
- sage/schemes/curves/zariski_vankampen.py +1932 -0
- sage/schemes/cyclic_covers/all.py +2 -0
- sage/schemes/cyclic_covers/charpoly_frobenius.py +320 -0
- sage/schemes/cyclic_covers/constructor.py +137 -0
- sage/schemes/cyclic_covers/cycliccover_finite_field.py +1309 -0
- sage/schemes/cyclic_covers/cycliccover_generic.py +310 -0
- sage/schemes/elliptic_curves/BSD.py +1036 -0
- sage/schemes/elliptic_curves/Qcurves.py +592 -0
- sage/schemes/elliptic_curves/addition_formulas_ring.py +94 -0
- sage/schemes/elliptic_curves/all.py +49 -0
- sage/schemes/elliptic_curves/cardinality.py +609 -0
- sage/schemes/elliptic_curves/cm.py +1102 -0
- sage/schemes/elliptic_curves/constructor.py +1552 -0
- sage/schemes/elliptic_curves/ec_database.py +175 -0
- sage/schemes/elliptic_curves/ell_curve_isogeny.py +3972 -0
- sage/schemes/elliptic_curves/ell_egros.py +459 -0
- sage/schemes/elliptic_curves/ell_field.py +2836 -0
- sage/schemes/elliptic_curves/ell_finite_field.py +3359 -0
- sage/schemes/elliptic_curves/ell_generic.py +3760 -0
- sage/schemes/elliptic_curves/ell_local_data.py +1207 -0
- sage/schemes/elliptic_curves/ell_modular_symbols.py +775 -0
- sage/schemes/elliptic_curves/ell_number_field.py +4220 -0
- sage/schemes/elliptic_curves/ell_padic_field.py +107 -0
- sage/schemes/elliptic_curves/ell_point.py +4787 -0
- sage/schemes/elliptic_curves/ell_rational_field.py +7368 -0
- sage/schemes/elliptic_curves/ell_tate_curve.py +671 -0
- sage/schemes/elliptic_curves/ell_torsion.py +436 -0
- sage/schemes/elliptic_curves/ell_wp.py +352 -0
- sage/schemes/elliptic_curves/formal_group.py +760 -0
- sage/schemes/elliptic_curves/gal_reps.py +1459 -0
- sage/schemes/elliptic_curves/gal_reps_number_field.py +1669 -0
- sage/schemes/elliptic_curves/gp_simon.py +152 -0
- sage/schemes/elliptic_curves/heegner.py +7335 -0
- sage/schemes/elliptic_curves/height.py +2109 -0
- sage/schemes/elliptic_curves/hom.py +1406 -0
- sage/schemes/elliptic_curves/hom_composite.py +934 -0
- sage/schemes/elliptic_curves/hom_frobenius.py +522 -0
- sage/schemes/elliptic_curves/hom_scalar.py +531 -0
- sage/schemes/elliptic_curves/hom_sum.py +682 -0
- sage/schemes/elliptic_curves/hom_velusqrt.py +1290 -0
- sage/schemes/elliptic_curves/homset.py +271 -0
- sage/schemes/elliptic_curves/isogeny_class.py +1521 -0
- sage/schemes/elliptic_curves/isogeny_small_degree.py +2797 -0
- sage/schemes/elliptic_curves/jacobian.py +237 -0
- sage/schemes/elliptic_curves/kodaira_symbol.py +344 -0
- sage/schemes/elliptic_curves/kraus.py +1014 -0
- sage/schemes/elliptic_curves/lseries_ell.py +943 -0
- sage/schemes/elliptic_curves/mod5family.py +105 -0
- sage/schemes/elliptic_curves/mod_poly.py +197 -0
- sage/schemes/elliptic_curves/mod_sym_num.cpython-312-darwin.so +0 -0
- sage/schemes/elliptic_curves/mod_sym_num.pyx +3796 -0
- sage/schemes/elliptic_curves/modular_parametrization.py +305 -0
- sage/schemes/elliptic_curves/padic_lseries.py +1793 -0
- sage/schemes/elliptic_curves/padics.py +1816 -0
- sage/schemes/elliptic_curves/period_lattice.py +2234 -0
- sage/schemes/elliptic_curves/period_lattice_region.cpython-312-darwin.so +0 -0
- sage/schemes/elliptic_curves/period_lattice_region.pyx +722 -0
- sage/schemes/elliptic_curves/saturation.py +715 -0
- sage/schemes/elliptic_curves/sha_tate.py +1158 -0
- sage/schemes/elliptic_curves/weierstrass_morphism.py +1117 -0
- sage/schemes/elliptic_curves/weierstrass_transform.py +200 -0
- sage/schemes/hyperelliptic_curves/all.py +6 -0
- sage/schemes/hyperelliptic_curves/constructor.py +291 -0
- sage/schemes/hyperelliptic_curves/hyperelliptic_finite_field.py +1914 -0
- sage/schemes/hyperelliptic_curves/hyperelliptic_g2.py +192 -0
- sage/schemes/hyperelliptic_curves/hyperelliptic_generic.py +954 -0
- sage/schemes/hyperelliptic_curves/hyperelliptic_padic_field.py +1332 -0
- sage/schemes/hyperelliptic_curves/hyperelliptic_rational_field.py +84 -0
- sage/schemes/hyperelliptic_curves/invariants.py +410 -0
- sage/schemes/hyperelliptic_curves/jacobian_endomorphism_utils.py +315 -0
- sage/schemes/hyperelliptic_curves/jacobian_g2.py +32 -0
- sage/schemes/hyperelliptic_curves/jacobian_generic.py +419 -0
- sage/schemes/hyperelliptic_curves/jacobian_homset.py +186 -0
- sage/schemes/hyperelliptic_curves/jacobian_morphism.py +875 -0
- sage/schemes/hyperelliptic_curves/kummer_surface.py +99 -0
- sage/schemes/hyperelliptic_curves/mestre.py +302 -0
- sage/schemes/hyperelliptic_curves/monsky_washnitzer.py +3871 -0
- sage/schemes/jacobians/abstract_jacobian.py +277 -0
- sage/schemes/jacobians/all.py +2 -0
- sage/schemes/overview.py +161 -0
- sage/schemes/plane_conics/all.py +22 -0
- sage/schemes/plane_conics/con_field.py +1296 -0
- sage/schemes/plane_conics/con_finite_field.py +158 -0
- sage/schemes/plane_conics/con_number_field.py +456 -0
- sage/schemes/plane_conics/con_rational_field.py +406 -0
- sage/schemes/plane_conics/con_rational_function_field.py +580 -0
- sage/schemes/plane_conics/constructor.py +249 -0
- sage/schemes/plane_quartics/all.py +2 -0
- sage/schemes/plane_quartics/quartic_constructor.py +71 -0
- sage/schemes/plane_quartics/quartic_generic.py +73 -0
- sage/schemes/riemann_surfaces/all.py +1 -0
- sage/schemes/riemann_surfaces/riemann_surface.py +4117 -0
- sage_wheels/share/cremona/cremona_mini.db +0 -0
- sage_wheels/share/ellcurves/rank0 +30427 -0
- sage_wheels/share/ellcurves/rank1 +31871 -0
- sage_wheels/share/ellcurves/rank10 +6 -0
- sage_wheels/share/ellcurves/rank11 +6 -0
- sage_wheels/share/ellcurves/rank12 +1 -0
- sage_wheels/share/ellcurves/rank14 +1 -0
- sage_wheels/share/ellcurves/rank15 +1 -0
- sage_wheels/share/ellcurves/rank17 +1 -0
- sage_wheels/share/ellcurves/rank19 +1 -0
- sage_wheels/share/ellcurves/rank2 +2388 -0
- sage_wheels/share/ellcurves/rank20 +1 -0
- sage_wheels/share/ellcurves/rank21 +1 -0
- sage_wheels/share/ellcurves/rank22 +1 -0
- sage_wheels/share/ellcurves/rank23 +1 -0
- sage_wheels/share/ellcurves/rank24 +1 -0
- sage_wheels/share/ellcurves/rank28 +1 -0
- sage_wheels/share/ellcurves/rank3 +836 -0
- sage_wheels/share/ellcurves/rank4 +10 -0
- sage_wheels/share/ellcurves/rank5 +5 -0
- sage_wheels/share/ellcurves/rank6 +5 -0
- sage_wheels/share/ellcurves/rank7 +5 -0
- sage_wheels/share/ellcurves/rank8 +6 -0
- 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)
|