passagemath-polyhedra 10.6.31rc3__cp314-cp314-musllinux_1_2_x86_64.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-polyhedra might be problematic. Click here for more details.
- passagemath_polyhedra-10.6.31rc3.dist-info/METADATA +367 -0
- passagemath_polyhedra-10.6.31rc3.dist-info/METADATA.bak +369 -0
- passagemath_polyhedra-10.6.31rc3.dist-info/RECORD +208 -0
- passagemath_polyhedra-10.6.31rc3.dist-info/WHEEL +5 -0
- passagemath_polyhedra-10.6.31rc3.dist-info/top_level.txt +2 -0
- passagemath_polyhedra.libs/libgcc_s-0cd532bd.so.1 +0 -0
- passagemath_polyhedra.libs/libgmp-0e7fc84e.so.10.5.0 +0 -0
- passagemath_polyhedra.libs/libgomp-8949ffbe.so.1.0.0 +0 -0
- passagemath_polyhedra.libs/libstdc++-5d72f927.so.6.0.33 +0 -0
- sage/all__sagemath_polyhedra.py +50 -0
- sage/game_theory/all.py +8 -0
- sage/game_theory/catalog.py +6 -0
- sage/game_theory/catalog_normal_form_games.py +923 -0
- sage/game_theory/cooperative_game.py +844 -0
- sage/game_theory/matching_game.py +1181 -0
- sage/game_theory/normal_form_game.py +2697 -0
- sage/game_theory/parser.py +275 -0
- sage/geometry/all__sagemath_polyhedra.py +22 -0
- sage/geometry/cone.py +6940 -0
- sage/geometry/cone_catalog.py +847 -0
- sage/geometry/cone_critical_angles.py +1027 -0
- sage/geometry/convex_set.py +1119 -0
- sage/geometry/fan.py +3743 -0
- sage/geometry/fan_isomorphism.py +389 -0
- sage/geometry/fan_morphism.py +1884 -0
- sage/geometry/hasse_diagram.py +202 -0
- sage/geometry/hyperplane_arrangement/affine_subspace.py +390 -0
- sage/geometry/hyperplane_arrangement/all.py +1 -0
- sage/geometry/hyperplane_arrangement/arrangement.py +3895 -0
- sage/geometry/hyperplane_arrangement/check_freeness.py +145 -0
- sage/geometry/hyperplane_arrangement/hyperplane.py +773 -0
- sage/geometry/hyperplane_arrangement/library.py +825 -0
- sage/geometry/hyperplane_arrangement/ordered_arrangement.py +642 -0
- sage/geometry/hyperplane_arrangement/plot.py +520 -0
- sage/geometry/integral_points.py +35 -0
- sage/geometry/integral_points_generic_dense.cpython-314-x86_64-linux-musl.so +0 -0
- sage/geometry/integral_points_generic_dense.pyx +7 -0
- sage/geometry/lattice_polytope.py +5894 -0
- sage/geometry/linear_expression.py +773 -0
- sage/geometry/newton_polygon.py +767 -0
- sage/geometry/point_collection.cpython-314-x86_64-linux-musl.so +0 -0
- sage/geometry/point_collection.pyx +1008 -0
- sage/geometry/polyhedral_complex.py +2616 -0
- sage/geometry/polyhedron/all.py +8 -0
- sage/geometry/polyhedron/backend_cdd.py +460 -0
- sage/geometry/polyhedron/backend_cdd_rdf.py +231 -0
- sage/geometry/polyhedron/backend_field.py +347 -0
- sage/geometry/polyhedron/backend_normaliz.py +2503 -0
- sage/geometry/polyhedron/backend_number_field.py +168 -0
- sage/geometry/polyhedron/backend_polymake.py +765 -0
- sage/geometry/polyhedron/backend_ppl.py +582 -0
- sage/geometry/polyhedron/base.py +1206 -0
- sage/geometry/polyhedron/base0.py +1444 -0
- sage/geometry/polyhedron/base1.py +886 -0
- sage/geometry/polyhedron/base2.py +812 -0
- sage/geometry/polyhedron/base3.py +1845 -0
- sage/geometry/polyhedron/base4.py +1262 -0
- sage/geometry/polyhedron/base5.py +2700 -0
- sage/geometry/polyhedron/base6.py +1741 -0
- sage/geometry/polyhedron/base7.py +997 -0
- sage/geometry/polyhedron/base_QQ.py +1258 -0
- sage/geometry/polyhedron/base_RDF.py +98 -0
- sage/geometry/polyhedron/base_ZZ.py +934 -0
- sage/geometry/polyhedron/base_mutable.py +215 -0
- sage/geometry/polyhedron/base_number_field.py +122 -0
- sage/geometry/polyhedron/cdd_file_format.py +155 -0
- sage/geometry/polyhedron/combinatorial_polyhedron/all.py +1 -0
- sage/geometry/polyhedron/combinatorial_polyhedron/base.cpython-314-x86_64-linux-musl.so +0 -0
- sage/geometry/polyhedron/combinatorial_polyhedron/base.pxd +76 -0
- sage/geometry/polyhedron/combinatorial_polyhedron/base.pyx +3859 -0
- sage/geometry/polyhedron/combinatorial_polyhedron/combinatorial_face.cpython-314-x86_64-linux-musl.so +0 -0
- sage/geometry/polyhedron/combinatorial_polyhedron/combinatorial_face.pxd +39 -0
- sage/geometry/polyhedron/combinatorial_polyhedron/combinatorial_face.pyx +1038 -0
- sage/geometry/polyhedron/combinatorial_polyhedron/conversions.cpython-314-x86_64-linux-musl.so +0 -0
- sage/geometry/polyhedron/combinatorial_polyhedron/conversions.pxd +9 -0
- sage/geometry/polyhedron/combinatorial_polyhedron/conversions.pyx +501 -0
- sage/geometry/polyhedron/combinatorial_polyhedron/face_data_structure.pxd +207 -0
- sage/geometry/polyhedron/combinatorial_polyhedron/face_iterator.cpython-314-x86_64-linux-musl.so +0 -0
- sage/geometry/polyhedron/combinatorial_polyhedron/face_iterator.pxd +102 -0
- sage/geometry/polyhedron/combinatorial_polyhedron/face_iterator.pyx +2274 -0
- sage/geometry/polyhedron/combinatorial_polyhedron/face_list_data_structure.cpython-314-x86_64-linux-musl.so +0 -0
- sage/geometry/polyhedron/combinatorial_polyhedron/face_list_data_structure.pxd +370 -0
- sage/geometry/polyhedron/combinatorial_polyhedron/face_list_data_structure.pyx +84 -0
- sage/geometry/polyhedron/combinatorial_polyhedron/list_of_faces.cpython-314-x86_64-linux-musl.so +0 -0
- sage/geometry/polyhedron/combinatorial_polyhedron/list_of_faces.pxd +31 -0
- sage/geometry/polyhedron/combinatorial_polyhedron/list_of_faces.pyx +587 -0
- sage/geometry/polyhedron/combinatorial_polyhedron/polyhedron_face_lattice.cpython-314-x86_64-linux-musl.so +0 -0
- sage/geometry/polyhedron/combinatorial_polyhedron/polyhedron_face_lattice.pxd +52 -0
- sage/geometry/polyhedron/combinatorial_polyhedron/polyhedron_face_lattice.pyx +560 -0
- sage/geometry/polyhedron/constructor.py +773 -0
- sage/geometry/polyhedron/double_description.py +753 -0
- sage/geometry/polyhedron/double_description_inhomogeneous.py +564 -0
- sage/geometry/polyhedron/face.py +1060 -0
- sage/geometry/polyhedron/generating_function.py +1810 -0
- sage/geometry/polyhedron/lattice_euclidean_group_element.py +178 -0
- sage/geometry/polyhedron/library.py +3502 -0
- sage/geometry/polyhedron/misc.py +121 -0
- sage/geometry/polyhedron/modules/all.py +1 -0
- sage/geometry/polyhedron/modules/formal_polyhedra_module.py +155 -0
- sage/geometry/polyhedron/palp_database.py +447 -0
- sage/geometry/polyhedron/parent.py +1279 -0
- sage/geometry/polyhedron/plot.py +1986 -0
- sage/geometry/polyhedron/ppl_lattice_polygon.py +556 -0
- sage/geometry/polyhedron/ppl_lattice_polytope.py +1257 -0
- sage/geometry/polyhedron/representation.py +1723 -0
- sage/geometry/pseudolines.py +515 -0
- sage/geometry/relative_interior.py +445 -0
- sage/geometry/toric_plotter.py +1103 -0
- sage/geometry/triangulation/all.py +2 -0
- sage/geometry/triangulation/base.cpython-314-x86_64-linux-musl.so +0 -0
- sage/geometry/triangulation/base.pyx +963 -0
- sage/geometry/triangulation/data.h +147 -0
- sage/geometry/triangulation/data.pxd +4 -0
- sage/geometry/triangulation/element.py +914 -0
- sage/geometry/triangulation/functions.h +10 -0
- sage/geometry/triangulation/functions.pxd +4 -0
- sage/geometry/triangulation/point_configuration.py +2256 -0
- sage/geometry/triangulation/triangulations.h +49 -0
- sage/geometry/triangulation/triangulations.pxd +7 -0
- sage/geometry/voronoi_diagram.py +319 -0
- sage/interfaces/all__sagemath_polyhedra.py +1 -0
- sage/interfaces/polymake.py +2028 -0
- sage/numerical/all.py +13 -0
- sage/numerical/all__sagemath_polyhedra.py +11 -0
- sage/numerical/backends/all.py +1 -0
- sage/numerical/backends/all__sagemath_polyhedra.py +1 -0
- sage/numerical/backends/cvxopt_backend.cpython-314-x86_64-linux-musl.so +0 -0
- sage/numerical/backends/cvxopt_backend.pyx +1006 -0
- sage/numerical/backends/cvxopt_backend_test.py +19 -0
- sage/numerical/backends/cvxopt_sdp_backend.cpython-314-x86_64-linux-musl.so +0 -0
- sage/numerical/backends/cvxopt_sdp_backend.pyx +382 -0
- sage/numerical/backends/cvxpy_backend.cpython-314-x86_64-linux-musl.so +0 -0
- sage/numerical/backends/cvxpy_backend.pxd +41 -0
- sage/numerical/backends/cvxpy_backend.pyx +934 -0
- sage/numerical/backends/cvxpy_backend_test.py +13 -0
- sage/numerical/backends/generic_backend_test.py +24 -0
- sage/numerical/backends/interactivelp_backend.cpython-314-x86_64-linux-musl.so +0 -0
- sage/numerical/backends/interactivelp_backend.pxd +36 -0
- sage/numerical/backends/interactivelp_backend.pyx +1231 -0
- sage/numerical/backends/interactivelp_backend_test.py +12 -0
- sage/numerical/backends/logging_backend.py +391 -0
- sage/numerical/backends/matrix_sdp_backend.cpython-314-x86_64-linux-musl.so +0 -0
- sage/numerical/backends/matrix_sdp_backend.pxd +15 -0
- sage/numerical/backends/matrix_sdp_backend.pyx +478 -0
- sage/numerical/backends/ppl_backend.cpython-314-x86_64-linux-musl.so +0 -0
- sage/numerical/backends/ppl_backend.pyx +1126 -0
- sage/numerical/backends/ppl_backend_test.py +13 -0
- sage/numerical/backends/scip_backend.cpython-314-x86_64-linux-musl.so +0 -0
- sage/numerical/backends/scip_backend.pxd +22 -0
- sage/numerical/backends/scip_backend.pyx +1289 -0
- sage/numerical/backends/scip_backend_test.py +13 -0
- sage/numerical/interactive_simplex_method.py +5338 -0
- sage/numerical/knapsack.py +665 -0
- sage/numerical/linear_functions.cpython-314-x86_64-linux-musl.so +0 -0
- sage/numerical/linear_functions.pxd +31 -0
- sage/numerical/linear_functions.pyx +1648 -0
- sage/numerical/linear_tensor.py +470 -0
- sage/numerical/linear_tensor_constraints.py +448 -0
- sage/numerical/linear_tensor_element.cpython-314-x86_64-linux-musl.so +0 -0
- sage/numerical/linear_tensor_element.pxd +6 -0
- sage/numerical/linear_tensor_element.pyx +459 -0
- sage/numerical/mip.cpython-314-x86_64-linux-musl.so +0 -0
- sage/numerical/mip.pxd +40 -0
- sage/numerical/mip.pyx +3667 -0
- sage/numerical/sdp.cpython-314-x86_64-linux-musl.so +0 -0
- sage/numerical/sdp.pxd +39 -0
- sage/numerical/sdp.pyx +1433 -0
- sage/rings/all__sagemath_polyhedra.py +3 -0
- sage/rings/polynomial/all__sagemath_polyhedra.py +10 -0
- sage/rings/polynomial/omega.py +982 -0
- sage/schemes/all__sagemath_polyhedra.py +2 -0
- sage/schemes/toric/all.py +10 -0
- sage/schemes/toric/chow_group.py +1248 -0
- sage/schemes/toric/divisor.py +2082 -0
- sage/schemes/toric/divisor_class.cpython-314-x86_64-linux-musl.so +0 -0
- sage/schemes/toric/divisor_class.pyx +322 -0
- sage/schemes/toric/fano_variety.py +1606 -0
- sage/schemes/toric/homset.py +650 -0
- sage/schemes/toric/ideal.py +451 -0
- sage/schemes/toric/library.py +1322 -0
- sage/schemes/toric/morphism.py +1958 -0
- sage/schemes/toric/points.py +1032 -0
- sage/schemes/toric/sheaf/all.py +1 -0
- sage/schemes/toric/sheaf/constructor.py +302 -0
- sage/schemes/toric/sheaf/klyachko.py +921 -0
- sage/schemes/toric/toric_subscheme.py +905 -0
- sage/schemes/toric/variety.py +3460 -0
- sage/schemes/toric/weierstrass.py +1078 -0
- sage/schemes/toric/weierstrass_covering.py +457 -0
- sage/schemes/toric/weierstrass_higher.py +288 -0
- sage_wheels/share/reflexive_polytopes/Full2d/zzdb.info +10 -0
- sage_wheels/share/reflexive_polytopes/Full2d/zzdb.v03 +0 -0
- sage_wheels/share/reflexive_polytopes/Full2d/zzdb.v04 +0 -0
- sage_wheels/share/reflexive_polytopes/Full2d/zzdb.v05 +1 -0
- sage_wheels/share/reflexive_polytopes/Full2d/zzdb.v06 +1 -0
- sage_wheels/share/reflexive_polytopes/Full3d/zzdb.info +22 -0
- sage_wheels/share/reflexive_polytopes/Full3d/zzdb.v04 +0 -0
- sage_wheels/share/reflexive_polytopes/Full3d/zzdb.v05 +0 -0
- sage_wheels/share/reflexive_polytopes/Full3d/zzdb.v06 +0 -0
- sage_wheels/share/reflexive_polytopes/Full3d/zzdb.v07 +0 -0
- sage_wheels/share/reflexive_polytopes/Full3d/zzdb.v08 +0 -0
- sage_wheels/share/reflexive_polytopes/Full3d/zzdb.v09 +0 -0
- sage_wheels/share/reflexive_polytopes/Full3d/zzdb.v10 +0 -0
- sage_wheels/share/reflexive_polytopes/Full3d/zzdb.v11 +1 -0
- sage_wheels/share/reflexive_polytopes/Full3d/zzdb.v12 +1 -0
- sage_wheels/share/reflexive_polytopes/Full3d/zzdb.v13 +1 -0
- sage_wheels/share/reflexive_polytopes/reflexive_polytopes_2d +80 -0
- sage_wheels/share/reflexive_polytopes/reflexive_polytopes_3d +37977 -0
|
@@ -0,0 +1,2082 @@
|
|
|
1
|
+
# sage_setup: distribution = sagemath-polyhedra
|
|
2
|
+
# sage.doctest: needs palp sage.geometry.polyhedron sage.graphs
|
|
3
|
+
r"""
|
|
4
|
+
Toric divisors and divisor classes
|
|
5
|
+
|
|
6
|
+
Let `X` be a :class:`toric variety
|
|
7
|
+
<sage.schemes.toric.variety.ToricVariety_field>` corresponding to a
|
|
8
|
+
:class:`rational polyhedral fan <sage.geometry.fan.RationalPolyhedralFan>`
|
|
9
|
+
`\Sigma`. A :class:`toric divisor <ToricDivisor_generic>` `D` is a T-Weil
|
|
10
|
+
divisor over a given coefficient ring (usually `\ZZ` or `\QQ`), i.e. a formal
|
|
11
|
+
linear combination of torus-invariant subvarieties of `X` of codimension one.
|
|
12
|
+
In homogeneous coordinates `[z_0:\cdots:z_k]`, these are the subvarieties
|
|
13
|
+
`\{z_i=0\}`. Note that there is a finite number of such subvarieties, one for
|
|
14
|
+
each ray of `\Sigma`. We generally identify
|
|
15
|
+
|
|
16
|
+
* Toric divisor `D`,
|
|
17
|
+
|
|
18
|
+
* Sheaf `\mathcal{O}(D)` (if `D` is Cartier, it is a line bundle),
|
|
19
|
+
|
|
20
|
+
* Support function `\phi_D` (if `D` is `\QQ`-Cartier, it is a function
|
|
21
|
+
linear on each cone of `\Sigma`).
|
|
22
|
+
|
|
23
|
+
EXAMPLES:
|
|
24
|
+
|
|
25
|
+
We start with an illustration of basic divisor arithmetic::
|
|
26
|
+
|
|
27
|
+
sage: dP6 = toric_varieties.dP6()
|
|
28
|
+
sage: Dx,Du,Dy,Dv,Dz,Dw = dP6.toric_divisor_group().gens()
|
|
29
|
+
sage: Dx
|
|
30
|
+
V(x)
|
|
31
|
+
sage: -Dx
|
|
32
|
+
-V(x)
|
|
33
|
+
sage: 2*Dx
|
|
34
|
+
2*V(x)
|
|
35
|
+
sage: Dx*2
|
|
36
|
+
2*V(x)
|
|
37
|
+
sage: (1/2)*Dx + Dy/3 - Dz
|
|
38
|
+
1/2*V(x) + 1/3*V(y) - V(z)
|
|
39
|
+
sage: Dx.parent()
|
|
40
|
+
Group of toric ZZ-Weil divisors
|
|
41
|
+
on 2-d CPR-Fano toric variety covered by 6 affine patches
|
|
42
|
+
sage: (Dx/2).parent()
|
|
43
|
+
Group of toric QQ-Weil divisors
|
|
44
|
+
on 2-d CPR-Fano toric variety covered by 6 affine patches
|
|
45
|
+
|
|
46
|
+
Now we create a more complicated variety to demonstrate divisors of different
|
|
47
|
+
types::
|
|
48
|
+
|
|
49
|
+
sage: F = Fan(cones=[(0,1,2,3), (0,1,4)],
|
|
50
|
+
....: rays=[(1,1,1), (1,-1,1), (1,-1,-1), (1,1,-1), (0,0,1)])
|
|
51
|
+
sage: X = ToricVariety(F)
|
|
52
|
+
sage: QQ_Cartier = X.divisor([2,2,1,1,1])
|
|
53
|
+
sage: Cartier = 2 * QQ_Cartier
|
|
54
|
+
sage: Weil = X.divisor([1,1,1,0,0])
|
|
55
|
+
sage: QQ_Weil = 1/2 * Weil
|
|
56
|
+
sage: [QQ_Weil.is_QQ_Weil(),
|
|
57
|
+
....: QQ_Weil.is_Weil(),
|
|
58
|
+
....: QQ_Weil.is_QQ_Cartier(),
|
|
59
|
+
....: QQ_Weil.is_Cartier()]
|
|
60
|
+
[True, False, False, False]
|
|
61
|
+
sage: [Weil.is_QQ_Weil(),
|
|
62
|
+
....: Weil.is_Weil(),
|
|
63
|
+
....: Weil.is_QQ_Cartier(),
|
|
64
|
+
....: Weil.is_Cartier()]
|
|
65
|
+
[True, True, False, False]
|
|
66
|
+
sage: [QQ_Cartier.is_QQ_Weil(),
|
|
67
|
+
....: QQ_Cartier.is_Weil(),
|
|
68
|
+
....: QQ_Cartier.is_QQ_Cartier(),
|
|
69
|
+
....: QQ_Cartier.is_Cartier()]
|
|
70
|
+
[True, True, True, False]
|
|
71
|
+
sage: [Cartier.is_QQ_Weil(),
|
|
72
|
+
....: Cartier.is_Weil(),
|
|
73
|
+
....: Cartier.is_QQ_Cartier(),
|
|
74
|
+
....: Cartier.is_Cartier()]
|
|
75
|
+
[True, True, True, True]
|
|
76
|
+
|
|
77
|
+
The toric (`\QQ`-Weil) divisors on a toric variety `X` modulo linear
|
|
78
|
+
equivalence generate the divisor **class group** `\mathrm{Cl}(X)`, implemented
|
|
79
|
+
by :class:`ToricRationalDivisorClassGroup`. If `X` is smooth, this equals the
|
|
80
|
+
**Picard group** `\mathop{\mathrm{Pic}}(X)`. We continue using del Pezzo
|
|
81
|
+
surface of degree 6 introduced above::
|
|
82
|
+
|
|
83
|
+
sage: Cl = dP6.rational_class_group(); Cl
|
|
84
|
+
The toric rational divisor class group
|
|
85
|
+
of a 2-d CPR-Fano toric variety covered by 6 affine patches
|
|
86
|
+
sage: Cl.ngens()
|
|
87
|
+
4
|
|
88
|
+
sage: c0,c1,c2,c3 = Cl.gens()
|
|
89
|
+
sage: c = c0 + 2*c1 - c3; c
|
|
90
|
+
Divisor class [1, 2, 0, -1]
|
|
91
|
+
|
|
92
|
+
Divisors are mapped to their classes and lifted via::
|
|
93
|
+
|
|
94
|
+
sage: Dx.divisor_class()
|
|
95
|
+
Divisor class [1, 0, 0, 0]
|
|
96
|
+
sage: Dx.divisor_class() in Cl
|
|
97
|
+
True
|
|
98
|
+
sage: (-Dw + Dv + Dy).divisor_class()
|
|
99
|
+
Divisor class [1, 0, 0, 0]
|
|
100
|
+
sage: c0
|
|
101
|
+
Divisor class [1, 0, 0, 0]
|
|
102
|
+
sage: c0.lift()
|
|
103
|
+
V(x)
|
|
104
|
+
|
|
105
|
+
The (rational) divisor class group is where the Kaehler cone lives::
|
|
106
|
+
|
|
107
|
+
sage: Kc = dP6.Kaehler_cone(); Kc
|
|
108
|
+
4-d cone in 4-d lattice
|
|
109
|
+
sage: Kc.rays()
|
|
110
|
+
Divisor class [0, 1, 1, 0],
|
|
111
|
+
Divisor class [0, 0, 1, 1],
|
|
112
|
+
Divisor class [1, 1, 0, 0],
|
|
113
|
+
Divisor class [1, 1, 1, 0],
|
|
114
|
+
Divisor class [0, 1, 1, 1]
|
|
115
|
+
in Basis lattice of The toric rational divisor class group
|
|
116
|
+
of a 2-d CPR-Fano toric variety covered by 6 affine patches
|
|
117
|
+
sage: Kc.ray(1).lift()
|
|
118
|
+
V(x) + V(w)
|
|
119
|
+
|
|
120
|
+
Given a divisor `D`, we have an associated line bundle (or a reflexive
|
|
121
|
+
sheaf, if `D` is not Cartier) `\mathcal{O}(D)`. Its sections are::
|
|
122
|
+
|
|
123
|
+
sage: P2 = toric_varieties.P2()
|
|
124
|
+
sage: H = P2.divisor(0); H
|
|
125
|
+
V(x)
|
|
126
|
+
sage: H.sections()
|
|
127
|
+
(M(-1, 0), M(-1, 1), M(0, 0))
|
|
128
|
+
sage: H.sections_monomials()
|
|
129
|
+
(z, y, x)
|
|
130
|
+
|
|
131
|
+
Note that the space of sections is always spanned by
|
|
132
|
+
monomials. Therefore, we can grade the sections (as homogeneous
|
|
133
|
+
monomials) by their weight under rescaling individual
|
|
134
|
+
coordinates. This weight data amounts to a point of the dual lattice.
|
|
135
|
+
|
|
136
|
+
In the same way, we can grade cohomology groups by their cohomological
|
|
137
|
+
degree and a weight::
|
|
138
|
+
|
|
139
|
+
sage: M = P2.fan().lattice().dual()
|
|
140
|
+
sage: H.cohomology(deg=0, weight=M(-1,0))
|
|
141
|
+
Vector space of dimension 1 over Rational Field
|
|
142
|
+
sage: _.dimension()
|
|
143
|
+
1
|
|
144
|
+
|
|
145
|
+
Here is a more complicated example with `h^1(dP_6, \mathcal{O}(D))=4` ::
|
|
146
|
+
|
|
147
|
+
sage: D = dP6.divisor([0, 0, -1, 0, 2, -1])
|
|
148
|
+
sage: D.cohomology()
|
|
149
|
+
{0: Vector space of dimension 0 over Rational Field,
|
|
150
|
+
1: Vector space of dimension 4 over Rational Field,
|
|
151
|
+
2: Vector space of dimension 0 over Rational Field}
|
|
152
|
+
sage: D.cohomology(dim=True)
|
|
153
|
+
(0, 4, 0)
|
|
154
|
+
|
|
155
|
+
AUTHORS:
|
|
156
|
+
|
|
157
|
+
- Volker Braun, Andrey Novoseltsev (2010-09-07): initial version.
|
|
158
|
+
"""
|
|
159
|
+
|
|
160
|
+
|
|
161
|
+
# ****************************************************************************
|
|
162
|
+
# Copyright (C) 2012 Volker Braun <vbraun.name@gmail.com>
|
|
163
|
+
# Copyright (C) 2012 Andrey Novoseltsev <novoselt@gmail.com>
|
|
164
|
+
#
|
|
165
|
+
# Distributed under the terms of the GNU General Public License (GPL)
|
|
166
|
+
# as published by the Free Software Foundation; either version 2 of
|
|
167
|
+
# the License, or (at your option) any later version.
|
|
168
|
+
# https://www.gnu.org/licenses/
|
|
169
|
+
# ****************************************************************************
|
|
170
|
+
|
|
171
|
+
from sage.combinat.combination import Combinations
|
|
172
|
+
import sage.geometry.abc
|
|
173
|
+
from sage.geometry.polyhedron.constructor import Polyhedron
|
|
174
|
+
from sage.geometry.toric_lattice_element import ToricLatticeElement
|
|
175
|
+
from sage.matrix.constructor import matrix
|
|
176
|
+
from sage.misc.cachefunc import cached_method
|
|
177
|
+
from sage.misc.flatten import flatten
|
|
178
|
+
from sage.misc.latex import latex
|
|
179
|
+
from sage.misc.lazy_import import lazy_import
|
|
180
|
+
from sage.misc.misc_c import prod
|
|
181
|
+
from sage.modules.free_module_element import vector
|
|
182
|
+
from sage.modules.free_module import (FreeModule_ambient_field,
|
|
183
|
+
FreeModule_ambient_pid)
|
|
184
|
+
from sage.rings.integer_ring import ZZ
|
|
185
|
+
from sage.rings.rational_field import QQ
|
|
186
|
+
from sage.schemes.generic.divisor import Divisor_generic
|
|
187
|
+
from sage.schemes.generic.divisor_group import DivisorGroup_generic
|
|
188
|
+
from sage.schemes.toric.divisor_class import ToricRationalDivisorClass
|
|
189
|
+
from sage.schemes.toric.variety import CohomologyRing, ToricVariety_field
|
|
190
|
+
from sage.structure.unique_representation import UniqueRepresentation
|
|
191
|
+
from sage.structure.element import Vector
|
|
192
|
+
|
|
193
|
+
lazy_import('sage.topology.simplicial_complex', 'SimplicialComplex')
|
|
194
|
+
|
|
195
|
+
|
|
196
|
+
def is_ToricDivisor(x):
|
|
197
|
+
r"""
|
|
198
|
+
Test whether ``x`` is a toric divisor.
|
|
199
|
+
|
|
200
|
+
INPUT:
|
|
201
|
+
|
|
202
|
+
- ``x`` -- anything
|
|
203
|
+
|
|
204
|
+
OUTPUT:
|
|
205
|
+
|
|
206
|
+
- ``True`` if ``x`` is an instance of :class:`ToricDivisor_generic` and
|
|
207
|
+
``False`` otherwise.
|
|
208
|
+
|
|
209
|
+
EXAMPLES::
|
|
210
|
+
|
|
211
|
+
sage: from sage.schemes.toric.divisor import is_ToricDivisor
|
|
212
|
+
sage: is_ToricDivisor(1)
|
|
213
|
+
doctest:warning...
|
|
214
|
+
DeprecationWarning: The function is_ToricDivisor is deprecated;
|
|
215
|
+
use 'isinstance(..., ToricDivisor_generic)' instead.
|
|
216
|
+
See https://github.com/sagemath/sage/issues/38277 for details.
|
|
217
|
+
False
|
|
218
|
+
sage: P2 = toric_varieties.P2()
|
|
219
|
+
sage: D = P2.divisor(0); D
|
|
220
|
+
V(x)
|
|
221
|
+
sage: is_ToricDivisor(D)
|
|
222
|
+
True
|
|
223
|
+
"""
|
|
224
|
+
from sage.misc.superseded import deprecation
|
|
225
|
+
deprecation(38277,
|
|
226
|
+
"The function is_ToricDivisor is deprecated; "
|
|
227
|
+
"use 'isinstance(..., ToricDivisor_generic)' instead.")
|
|
228
|
+
return isinstance(x, ToricDivisor_generic)
|
|
229
|
+
|
|
230
|
+
|
|
231
|
+
# ********************************************************
|
|
232
|
+
def ToricDivisor(toric_variety, arg=None, ring=None, check=True, reduce=True):
|
|
233
|
+
r"""
|
|
234
|
+
Construct a divisor of ``toric_variety``.
|
|
235
|
+
|
|
236
|
+
INPUT:
|
|
237
|
+
|
|
238
|
+
- ``toric_variety`` -- a :class:`toric variety
|
|
239
|
+
<sage.schemes.toric.variety.ToricVariety_field>`
|
|
240
|
+
|
|
241
|
+
- ``arg`` -- one of the following description of the toric divisor to be
|
|
242
|
+
constructed:
|
|
243
|
+
|
|
244
|
+
* ``None`` or 0 (the trivial divisor);
|
|
245
|
+
|
|
246
|
+
* monomial in the homogeneous coordinates;
|
|
247
|
+
|
|
248
|
+
* one-dimensional cone of the fan of ``toric_variety`` or a lattice
|
|
249
|
+
point generating such a cone;
|
|
250
|
+
|
|
251
|
+
* sequence of rational numbers, specifying multiplicities for each of
|
|
252
|
+
the toric divisors.
|
|
253
|
+
|
|
254
|
+
- ``ring`` -- usually either `\ZZ` or `\QQ`. The base ring of the
|
|
255
|
+
divisor group. If ``ring`` is not specified, a coefficient ring
|
|
256
|
+
suitable for ``arg`` is derived.
|
|
257
|
+
|
|
258
|
+
- ``check`` -- boolean (default: ``True``); whether to coerce
|
|
259
|
+
coefficients into base ring. Setting it to ``False`` can speed
|
|
260
|
+
up construction.
|
|
261
|
+
|
|
262
|
+
- ``reduce`` -- reduce (default: ``True``); whether to combine common
|
|
263
|
+
terms. Setting it to ``False`` can speed up construction.
|
|
264
|
+
|
|
265
|
+
.. WARNING::
|
|
266
|
+
|
|
267
|
+
The coefficients of the divisor must be in the base ring and
|
|
268
|
+
the terms must be reduced. If you set ``check=False`` and/or
|
|
269
|
+
``reduce=False`` it is your responsibility to pass valid input
|
|
270
|
+
data ``arg``.
|
|
271
|
+
|
|
272
|
+
OUTPUT: a :class:`sage.schemes.toric.divisor.ToricDivisor_generic`
|
|
273
|
+
|
|
274
|
+
EXAMPLES::
|
|
275
|
+
|
|
276
|
+
sage: from sage.schemes.toric.divisor import ToricDivisor
|
|
277
|
+
sage: dP6 = toric_varieties.dP6()
|
|
278
|
+
sage: ToricDivisor(dP6, [(1,dP6.gen(2)), (1,dP6.gen(1))])
|
|
279
|
+
V(u) + V(y)
|
|
280
|
+
sage: ToricDivisor(dP6, (0,1,1,0,0,0), ring=QQ)
|
|
281
|
+
V(u) + V(y)
|
|
282
|
+
sage: dP6.inject_variables()
|
|
283
|
+
Defining x, u, y, v, z, w
|
|
284
|
+
sage: ToricDivisor(dP6, u + y)
|
|
285
|
+
Traceback (most recent call last):
|
|
286
|
+
...
|
|
287
|
+
ValueError: u + y is not a monomial
|
|
288
|
+
sage: ToricDivisor(dP6, u*y)
|
|
289
|
+
V(u) + V(y)
|
|
290
|
+
sage: ToricDivisor(dP6, dP6.fan(dim=1)[2] )
|
|
291
|
+
V(y)
|
|
292
|
+
sage: cone = Cone(dP6.fan(dim=1)[2])
|
|
293
|
+
sage: ToricDivisor(dP6, cone)
|
|
294
|
+
V(y)
|
|
295
|
+
sage: N = dP6.fan().lattice()
|
|
296
|
+
sage: ToricDivisor(dP6, N(1,1) )
|
|
297
|
+
V(w)
|
|
298
|
+
|
|
299
|
+
We attempt to guess the correct base ring::
|
|
300
|
+
|
|
301
|
+
sage: ToricDivisor(dP6, [(1/2,u)])
|
|
302
|
+
1/2*V(u)
|
|
303
|
+
sage: _.parent()
|
|
304
|
+
Group of toric QQ-Weil divisors on
|
|
305
|
+
2-d CPR-Fano toric variety covered by 6 affine patches
|
|
306
|
+
sage: ToricDivisor(dP6, [(1/2,u), (1/2,u)])
|
|
307
|
+
V(u)
|
|
308
|
+
sage: _.parent()
|
|
309
|
+
Group of toric ZZ-Weil divisors on
|
|
310
|
+
2-d CPR-Fano toric variety covered by 6 affine patches
|
|
311
|
+
sage: ToricDivisor(dP6, [(u,u)])
|
|
312
|
+
Traceback (most recent call last):
|
|
313
|
+
...
|
|
314
|
+
TypeError: cannot deduce coefficient ring for [(u, u)]
|
|
315
|
+
"""
|
|
316
|
+
assert isinstance(toric_variety, ToricVariety_field)
|
|
317
|
+
|
|
318
|
+
# First convert special arguments into lists
|
|
319
|
+
# of multiplicities or (multiplicity,coordinate)
|
|
320
|
+
# Zero divisor
|
|
321
|
+
if arg is None or arg in ZZ and arg == 0:
|
|
322
|
+
arg = []
|
|
323
|
+
check = False
|
|
324
|
+
reduce = False
|
|
325
|
+
# Divisor by lattice point (corresponding to a ray)
|
|
326
|
+
if isinstance(arg, ToricLatticeElement):
|
|
327
|
+
if arg not in toric_variety.fan().lattice():
|
|
328
|
+
raise ValueError("%s is not in the ambient lattice of %s"
|
|
329
|
+
% (arg, toric_variety.fan()))
|
|
330
|
+
arg = toric_variety.fan().cone_containing(arg)
|
|
331
|
+
# Divisor by a one-cone
|
|
332
|
+
if isinstance(arg, sage.geometry.abc.ConvexRationalPolyhedralCone):
|
|
333
|
+
fan = toric_variety.fan()
|
|
334
|
+
cone = fan.embed(arg)
|
|
335
|
+
if cone.dim() != 1:
|
|
336
|
+
raise ValueError("only 1-dimensional cones of the toric variety "
|
|
337
|
+
"define divisors")
|
|
338
|
+
arg = [(1, toric_variety.gen(cone.ambient_ray_indices()[0]))]
|
|
339
|
+
check = True # ensure that the 1 will be coerced into the coefficient ring
|
|
340
|
+
reduce = False
|
|
341
|
+
# Divisor by monomial
|
|
342
|
+
if arg in toric_variety.coordinate_ring():
|
|
343
|
+
if len(list(arg)) != 1:
|
|
344
|
+
raise ValueError(f"{arg} is not a monomial")
|
|
345
|
+
arg = arg.exponents()[0]
|
|
346
|
+
# By now either we have converted arg to a list, or it is something else
|
|
347
|
+
# which should be convertible to a list
|
|
348
|
+
if not isinstance(arg, list):
|
|
349
|
+
try:
|
|
350
|
+
arg = list(arg)
|
|
351
|
+
except TypeError:
|
|
352
|
+
raise TypeError(f"{arg} does not define a divisor")
|
|
353
|
+
|
|
354
|
+
# Now convert a list of multiplicities into pairs multiplicity-coordinate
|
|
355
|
+
try:
|
|
356
|
+
assert all(len(item) == 2 for item in arg)
|
|
357
|
+
except (AssertionError, TypeError):
|
|
358
|
+
n_rays = toric_variety.fan().nrays()
|
|
359
|
+
assert len(arg) == n_rays, \
|
|
360
|
+
'Argument list {} is not of the required length {}!' \
|
|
361
|
+
.format(arg, n_rays)
|
|
362
|
+
arg = list(zip(arg, toric_variety.gens()))
|
|
363
|
+
reduce = False
|
|
364
|
+
|
|
365
|
+
# Now we must have a list of multiplicity-coordinate pairs
|
|
366
|
+
assert all(len(item) == 2 for item in arg)
|
|
367
|
+
if ring is None:
|
|
368
|
+
# if the coefficient ring was not given, try to use the most common ones.
|
|
369
|
+
try:
|
|
370
|
+
TDiv = ToricDivisorGroup(toric_variety, base_ring=ZZ)
|
|
371
|
+
return ToricDivisor_generic(arg, TDiv,
|
|
372
|
+
check=True, reduce=reduce)
|
|
373
|
+
except TypeError:
|
|
374
|
+
pass
|
|
375
|
+
try:
|
|
376
|
+
TDiv = ToricDivisorGroup(toric_variety, base_ring=QQ)
|
|
377
|
+
return ToricDivisor_generic(arg, TDiv,
|
|
378
|
+
check=True, reduce=reduce)
|
|
379
|
+
except TypeError:
|
|
380
|
+
raise TypeError(f"cannot deduce coefficient ring for {arg}")
|
|
381
|
+
TDiv = ToricDivisorGroup(toric_variety, ring)
|
|
382
|
+
return ToricDivisor_generic(arg, TDiv, check, reduce)
|
|
383
|
+
|
|
384
|
+
|
|
385
|
+
class ToricDivisor_generic(Divisor_generic):
|
|
386
|
+
"""
|
|
387
|
+
Construct a :class:`(toric Weil) divisor <ToricDivisor_generic>` on the
|
|
388
|
+
given toric variety.
|
|
389
|
+
|
|
390
|
+
INPUT:
|
|
391
|
+
|
|
392
|
+
- ``v`` -- list of tuples (multiplicity, coordinate)
|
|
393
|
+
|
|
394
|
+
- ``parent`` -- :class:`ToricDivisorGroup`; the parent divisor group
|
|
395
|
+
|
|
396
|
+
- ``check`` -- boolean; type-check the entries of ``v``, see
|
|
397
|
+
:class:`~sage.schemes.generic.divisor_group.DivisorGroup_generic`
|
|
398
|
+
|
|
399
|
+
- ``reduce`` -- boolean; combine coefficients in ``v``, see
|
|
400
|
+
:class:`~sage.schemes.generic.divisor_group.DivisorGroup_generic`
|
|
401
|
+
|
|
402
|
+
.. WARNING::
|
|
403
|
+
|
|
404
|
+
Do not construct :class:`ToricDivisor_generic` objects manually.
|
|
405
|
+
Instead, use either the function :func:`ToricDivisor` or the method
|
|
406
|
+
:meth:`~sage.schemes.toric.variety.ToricVariety_field.divisor`
|
|
407
|
+
of toric varieties.
|
|
408
|
+
|
|
409
|
+
EXAMPLES::
|
|
410
|
+
|
|
411
|
+
sage: dP6 = toric_varieties.dP6()
|
|
412
|
+
sage: ray = dP6.fan().ray(0)
|
|
413
|
+
sage: ray
|
|
414
|
+
N(0, 1)
|
|
415
|
+
sage: D = dP6.divisor(ray); D
|
|
416
|
+
V(x)
|
|
417
|
+
sage: D.parent()
|
|
418
|
+
Group of toric ZZ-Weil divisors
|
|
419
|
+
on 2-d CPR-Fano toric variety covered by 6 affine patches
|
|
420
|
+
"""
|
|
421
|
+
|
|
422
|
+
def __init__(self, v, parent, check=True, reduce=True):
|
|
423
|
+
"""
|
|
424
|
+
See :class:`ToricDivisor_generic` for documentation.
|
|
425
|
+
|
|
426
|
+
EXAMPLES::
|
|
427
|
+
|
|
428
|
+
sage: dP6 = toric_varieties.dP6()
|
|
429
|
+
sage: from sage.schemes.toric.divisor import ToricDivisor_generic
|
|
430
|
+
sage: TDiv = dP6.toric_divisor_group()
|
|
431
|
+
sage: ToricDivisor_generic([], TDiv)
|
|
432
|
+
0
|
|
433
|
+
sage: ToricDivisor_generic([(2,dP6.gen(1))], TDiv)
|
|
434
|
+
2*V(u)
|
|
435
|
+
"""
|
|
436
|
+
super().__init__(v, parent, check, reduce)
|
|
437
|
+
|
|
438
|
+
def _vector_(self, ring=None):
|
|
439
|
+
r"""
|
|
440
|
+
Return a vector representation.
|
|
441
|
+
|
|
442
|
+
INPUT:
|
|
443
|
+
|
|
444
|
+
- ``ring`` -- a ring (usually `\ZZ` or `\QQ`) for the
|
|
445
|
+
coefficients to live in). This is an optional argument, by
|
|
446
|
+
default a suitable ring is chosen automatically.
|
|
447
|
+
|
|
448
|
+
OUTPUT:
|
|
449
|
+
|
|
450
|
+
A vector whose ``self.scheme().fan().nrays()`` components are
|
|
451
|
+
the coefficients of the divisor.
|
|
452
|
+
|
|
453
|
+
EXAMPLES::
|
|
454
|
+
|
|
455
|
+
sage: dP6 = toric_varieties.dP6()
|
|
456
|
+
sage: D = dP6.divisor((0,1,1,0,0,0)); D
|
|
457
|
+
V(u) + V(y)
|
|
458
|
+
sage: D._vector_()
|
|
459
|
+
(0, 1, 1, 0, 0, 0)
|
|
460
|
+
sage: vector(D) # syntactic sugar
|
|
461
|
+
(0, 1, 1, 0, 0, 0)
|
|
462
|
+
sage: type( vector(D) )
|
|
463
|
+
<... 'sage.modules.vector_integer_dense.Vector_integer_dense'>
|
|
464
|
+
sage: D_QQ = dP6.divisor((0,1,1,0,0,0), base_ring=QQ);
|
|
465
|
+
sage: vector(D_QQ)
|
|
466
|
+
(0, 1, 1, 0, 0, 0)
|
|
467
|
+
sage: type( vector(D_QQ) )
|
|
468
|
+
<... 'sage.modules.vector_rational_dense.Vector_rational_dense'>
|
|
469
|
+
|
|
470
|
+
The vector representation is a suitable input for :func:`ToricDivisor` ::
|
|
471
|
+
|
|
472
|
+
sage: dP6.divisor(vector(D)) == D
|
|
473
|
+
True
|
|
474
|
+
"""
|
|
475
|
+
if ring is None:
|
|
476
|
+
ring = self.base_ring()
|
|
477
|
+
X = self.parent().scheme()
|
|
478
|
+
v = vector(ring, [0] * X.ngens())
|
|
479
|
+
for coeff, variable in self:
|
|
480
|
+
v[X.gens().index(variable)] += coeff
|
|
481
|
+
return v
|
|
482
|
+
|
|
483
|
+
def coefficient(self, x):
|
|
484
|
+
r"""
|
|
485
|
+
Return the coefficient of ``x``.
|
|
486
|
+
|
|
487
|
+
INPUT:
|
|
488
|
+
|
|
489
|
+
- ``x`` -- one of the homogeneous coordinates, either given by
|
|
490
|
+
the variable or its index
|
|
491
|
+
|
|
492
|
+
OUTPUT: the coefficient of ``x``
|
|
493
|
+
|
|
494
|
+
EXAMPLES::
|
|
495
|
+
|
|
496
|
+
sage: P2 = toric_varieties.P2()
|
|
497
|
+
sage: D = P2.divisor((11,12,13)); D
|
|
498
|
+
11*V(x) + 12*V(y) + 13*V(z)
|
|
499
|
+
sage: D.coefficient(1)
|
|
500
|
+
12
|
|
501
|
+
sage: P2.inject_variables()
|
|
502
|
+
Defining x, y, z
|
|
503
|
+
sage: D.coefficient(y)
|
|
504
|
+
12
|
|
505
|
+
"""
|
|
506
|
+
try:
|
|
507
|
+
index = ZZ(x)
|
|
508
|
+
variable = self.parent().scheme().gen(index)
|
|
509
|
+
except TypeError:
|
|
510
|
+
variable = x
|
|
511
|
+
|
|
512
|
+
for coeff, var in self:
|
|
513
|
+
if var == variable:
|
|
514
|
+
return coeff
|
|
515
|
+
return self.base_ring().zero()
|
|
516
|
+
|
|
517
|
+
def function_value(self, point):
|
|
518
|
+
r"""
|
|
519
|
+
Return the value of the support function at ``point``.
|
|
520
|
+
|
|
521
|
+
Let `X` be the ambient toric variety of ``self``, `\Sigma` the fan
|
|
522
|
+
associated to `X`, and `N` the ambient lattice of `\Sigma`.
|
|
523
|
+
|
|
524
|
+
INPUT:
|
|
525
|
+
|
|
526
|
+
- ``point`` -- either an integer, interpreted as the index of a ray of
|
|
527
|
+
`\Sigma`, or a point of the lattice `N`
|
|
528
|
+
|
|
529
|
+
OUTPUT: integer or a rational number
|
|
530
|
+
|
|
531
|
+
EXAMPLES::
|
|
532
|
+
|
|
533
|
+
sage: P2 = toric_varieties.P2()
|
|
534
|
+
sage: D = P2.divisor([11,22,44]) # total degree 77
|
|
535
|
+
sage: D.function_value(0)
|
|
536
|
+
11
|
|
537
|
+
sage: N = P2.fan().lattice()
|
|
538
|
+
sage: D.function_value( N(1,1) )
|
|
539
|
+
33
|
|
540
|
+
sage: D.function_value( P2.fan().ray(0) )
|
|
541
|
+
11
|
|
542
|
+
"""
|
|
543
|
+
if not self.is_QQ_Cartier():
|
|
544
|
+
raise ValueError("support functions are associated to QQ-Cartier "
|
|
545
|
+
"divisors only, %s is not QQ-Cartier" % self)
|
|
546
|
+
try:
|
|
547
|
+
index = ZZ(point)
|
|
548
|
+
return self.coefficient(index)
|
|
549
|
+
except TypeError:
|
|
550
|
+
pass
|
|
551
|
+
fan = self.parent().scheme().fan()
|
|
552
|
+
assert point in fan.lattice(), 'The point ' + str(point) + ' is not in the N-lattice.'
|
|
553
|
+
cone = fan.cone_containing(point)
|
|
554
|
+
return point * self.m(cone)
|
|
555
|
+
|
|
556
|
+
def m(self, cone):
|
|
557
|
+
r"""
|
|
558
|
+
Return `m_\sigma` representing `\phi_D` on ``cone``.
|
|
559
|
+
|
|
560
|
+
Let `X` be the ambient toric variety of this divisor `D` associated to
|
|
561
|
+
the fan `\Sigma` in lattice `N`. Let `M` be the lattice dual to `N`.
|
|
562
|
+
Given the cone `\sigma =\langle v_1, \dots, v_k \rangle` in `\Sigma`,
|
|
563
|
+
this method searches for a vector `m_\sigma \in M_\QQ` such that
|
|
564
|
+
`\phi_D(v_i) = \langle m_\sigma, v_i \rangle` for all `i=1, \dots, k`,
|
|
565
|
+
where `\phi_D` is the support function of `D`.
|
|
566
|
+
|
|
567
|
+
INPUT:
|
|
568
|
+
|
|
569
|
+
- ``cone`` -- a cone in the fan of the toric variety
|
|
570
|
+
|
|
571
|
+
OUTPUT: if possible, a point of lattice `M`
|
|
572
|
+
|
|
573
|
+
- If the dual vector cannot be chosen integral, a rational vector is
|
|
574
|
+
returned.
|
|
575
|
+
|
|
576
|
+
- If there is no such vector (i.e. ``self`` is not even a
|
|
577
|
+
`\QQ`-Cartier divisor), a :exc:`ValueError` is raised.
|
|
578
|
+
|
|
579
|
+
EXAMPLES::
|
|
580
|
+
|
|
581
|
+
sage: F = Fan(cones=[(0,1,2,3), (0,1,4)],
|
|
582
|
+
....: rays=[(1,1,1), (1,-1,1), (1,-1,-1), (1,1,-1), (0,0,1)])
|
|
583
|
+
sage: X = ToricVariety(F)
|
|
584
|
+
sage: square_cone = X.fan().cone_containing(0,1,2,3)
|
|
585
|
+
sage: triangle_cone = X.fan().cone_containing(0,1,4)
|
|
586
|
+
sage: ray = X.fan().cone_containing(0)
|
|
587
|
+
sage: QQ_Cartier = X.divisor([2,2,1,1,1])
|
|
588
|
+
sage: QQ_Cartier.m(ray)
|
|
589
|
+
M(0, 2, 0)
|
|
590
|
+
sage: QQ_Cartier.m(square_cone)
|
|
591
|
+
(3/2, 0, 1/2)
|
|
592
|
+
sage: QQ_Cartier.m(triangle_cone)
|
|
593
|
+
M(1, 0, 1)
|
|
594
|
+
sage: QQ_Cartier.m(Cone(triangle_cone))
|
|
595
|
+
M(1, 0, 1)
|
|
596
|
+
sage: Weil = X.divisor([1,1,1,0,0])
|
|
597
|
+
sage: Weil.m(square_cone)
|
|
598
|
+
Traceback (most recent call last):
|
|
599
|
+
...
|
|
600
|
+
ValueError: V(z0) + V(z1) + V(z2) is not QQ-Cartier,
|
|
601
|
+
cannot choose a dual vector on 3-d cone
|
|
602
|
+
of Rational polyhedral fan in 3-d lattice N
|
|
603
|
+
sage: Weil.m(triangle_cone)
|
|
604
|
+
M(1, 0, 0)
|
|
605
|
+
"""
|
|
606
|
+
try:
|
|
607
|
+
return self._m[cone]
|
|
608
|
+
except AttributeError:
|
|
609
|
+
self._m = {}
|
|
610
|
+
except KeyError:
|
|
611
|
+
pass
|
|
612
|
+
|
|
613
|
+
X = self.parent().scheme()
|
|
614
|
+
M = X.fan().dual_lattice()
|
|
615
|
+
fan = X.fan()
|
|
616
|
+
cone = fan.embed(cone)
|
|
617
|
+
if cone.is_trivial():
|
|
618
|
+
m = M(0)
|
|
619
|
+
self._m[cone] = m
|
|
620
|
+
return m
|
|
621
|
+
|
|
622
|
+
assert cone.ambient() is fan
|
|
623
|
+
b = vector(self.coefficient(i) for i in cone.ambient_ray_indices())
|
|
624
|
+
A = cone.rays().column_matrix()
|
|
625
|
+
try:
|
|
626
|
+
if cone.dim() == X.dimension():
|
|
627
|
+
# either unique solution or ValueError (if not QQ-Cartier)
|
|
628
|
+
m = A.solve_left(b) # A m = b
|
|
629
|
+
else:
|
|
630
|
+
# under-determined system; try to find integral solution
|
|
631
|
+
D, U, V = A.smith_form() # D = U*A*V
|
|
632
|
+
bV = b * V
|
|
633
|
+
m = D.solve_left(bV) * U
|
|
634
|
+
except ValueError:
|
|
635
|
+
raise ValueError("%s is not QQ-Cartier, cannot choose a dual "
|
|
636
|
+
"vector on %s" % (self, cone))
|
|
637
|
+
|
|
638
|
+
try:
|
|
639
|
+
m = M(m)
|
|
640
|
+
except TypeError: # not integral
|
|
641
|
+
pass
|
|
642
|
+
self._m[cone] = m
|
|
643
|
+
return m
|
|
644
|
+
|
|
645
|
+
def is_Weil(self):
|
|
646
|
+
"""
|
|
647
|
+
Return whether the divisor is a Weil-divisor.
|
|
648
|
+
|
|
649
|
+
EXAMPLES::
|
|
650
|
+
|
|
651
|
+
sage: P2 = toric_varieties.P2()
|
|
652
|
+
sage: D = P2.divisor([1,2,3])
|
|
653
|
+
sage: D.is_Weil()
|
|
654
|
+
True
|
|
655
|
+
sage: (D/2).is_Weil()
|
|
656
|
+
False
|
|
657
|
+
"""
|
|
658
|
+
if self.base_ring() == ZZ:
|
|
659
|
+
return True
|
|
660
|
+
try:
|
|
661
|
+
vector(ZZ, vector(self))
|
|
662
|
+
return True
|
|
663
|
+
except TypeError:
|
|
664
|
+
return False
|
|
665
|
+
|
|
666
|
+
def is_QQ_Weil(self):
|
|
667
|
+
r"""
|
|
668
|
+
Return whether the divisor is a `\QQ`-Weil-divisor.
|
|
669
|
+
|
|
670
|
+
.. NOTE::
|
|
671
|
+
|
|
672
|
+
This function returns always ``True`` since
|
|
673
|
+
:class:`ToricDivisor <ToricDivisor_generic>` can only
|
|
674
|
+
describe `\QQ`-Weil divisors.
|
|
675
|
+
|
|
676
|
+
EXAMPLES::
|
|
677
|
+
|
|
678
|
+
sage: P2 = toric_varieties.P2()
|
|
679
|
+
sage: D = P2.divisor([1,2,3])
|
|
680
|
+
sage: D.is_QQ_Weil()
|
|
681
|
+
True
|
|
682
|
+
sage: (D/2).is_QQ_Weil()
|
|
683
|
+
True
|
|
684
|
+
"""
|
|
685
|
+
return True
|
|
686
|
+
|
|
687
|
+
def is_Cartier(self):
|
|
688
|
+
r"""
|
|
689
|
+
Return whether the divisor is a Cartier-divisor.
|
|
690
|
+
|
|
691
|
+
.. NOTE::
|
|
692
|
+
|
|
693
|
+
The sheaf `\mathcal{O}(D)` associated to the given divisor
|
|
694
|
+
`D` is a line bundle if and only if the divisor is
|
|
695
|
+
Cartier.
|
|
696
|
+
|
|
697
|
+
EXAMPLES::
|
|
698
|
+
|
|
699
|
+
sage: X = toric_varieties.P4_11169()
|
|
700
|
+
sage: D = X.divisor(3)
|
|
701
|
+
sage: D.is_Cartier()
|
|
702
|
+
False
|
|
703
|
+
sage: D.is_QQ_Cartier()
|
|
704
|
+
True
|
|
705
|
+
"""
|
|
706
|
+
try:
|
|
707
|
+
return self._is_Cartier
|
|
708
|
+
except AttributeError:
|
|
709
|
+
pass
|
|
710
|
+
|
|
711
|
+
self._is_Cartier = self.is_QQ_Cartier()
|
|
712
|
+
if self._is_Cartier:
|
|
713
|
+
fan = self.parent().scheme().fan()
|
|
714
|
+
M = fan.dual_lattice()
|
|
715
|
+
self._is_Cartier = all(self.m(c) in M for c in fan)
|
|
716
|
+
return self._is_Cartier
|
|
717
|
+
|
|
718
|
+
def is_QQ_Cartier(self):
|
|
719
|
+
r"""
|
|
720
|
+
Return whether the divisor is a `\QQ`-Cartier divisor.
|
|
721
|
+
|
|
722
|
+
A `\QQ`-Cartier divisor is a divisor such that some multiple
|
|
723
|
+
of it is Cartier.
|
|
724
|
+
|
|
725
|
+
EXAMPLES::
|
|
726
|
+
|
|
727
|
+
sage: X = toric_varieties.P4_11169()
|
|
728
|
+
sage: D = X.divisor(3)
|
|
729
|
+
sage: D.is_QQ_Cartier()
|
|
730
|
+
True
|
|
731
|
+
|
|
732
|
+
sage: X = toric_varieties.Cube_face_fan()
|
|
733
|
+
sage: D = X.divisor(3)
|
|
734
|
+
sage: D.is_QQ_Cartier()
|
|
735
|
+
False
|
|
736
|
+
"""
|
|
737
|
+
try:
|
|
738
|
+
return self._is_QQ_Cartier
|
|
739
|
+
except AttributeError:
|
|
740
|
+
pass
|
|
741
|
+
|
|
742
|
+
try:
|
|
743
|
+
[self.m(c) for c in self.parent().scheme().fan()]
|
|
744
|
+
self._is_QQ_Cartier = True
|
|
745
|
+
except ValueError:
|
|
746
|
+
self._is_QQ_Cartier = False
|
|
747
|
+
return self._is_QQ_Cartier
|
|
748
|
+
|
|
749
|
+
def is_integral(self):
|
|
750
|
+
r"""
|
|
751
|
+
Return whether the coefficients of the divisor are all integral.
|
|
752
|
+
|
|
753
|
+
EXAMPLES::
|
|
754
|
+
|
|
755
|
+
sage: P2 = toric_varieties.P2()
|
|
756
|
+
sage: DZZ = P2.toric_divisor_group(base_ring=ZZ).gen(0); DZZ
|
|
757
|
+
V(x)
|
|
758
|
+
sage: DQQ = P2.toric_divisor_group(base_ring=QQ).gen(0); DQQ
|
|
759
|
+
V(x)
|
|
760
|
+
sage: DZZ.is_integral()
|
|
761
|
+
True
|
|
762
|
+
sage: DQQ.is_integral()
|
|
763
|
+
True
|
|
764
|
+
"""
|
|
765
|
+
return all(coeff in ZZ for coeff, _ in self)
|
|
766
|
+
|
|
767
|
+
def move_away_from(self, cone):
|
|
768
|
+
"""
|
|
769
|
+
Move the divisor away from the orbit closure of ``cone``.
|
|
770
|
+
|
|
771
|
+
INPUT:
|
|
772
|
+
|
|
773
|
+
- A ``cone`` of the fan of the toric variety.
|
|
774
|
+
|
|
775
|
+
OUTPUT:
|
|
776
|
+
|
|
777
|
+
A (rationally equivalent) divisor that is moved off the
|
|
778
|
+
orbit closure of the given cone.
|
|
779
|
+
|
|
780
|
+
.. NOTE::
|
|
781
|
+
|
|
782
|
+
A divisor that is Weil but not Cartier might be impossible
|
|
783
|
+
to move away. In this case, a :exc:`ValueError` is raised.
|
|
784
|
+
|
|
785
|
+
EXAMPLES::
|
|
786
|
+
|
|
787
|
+
sage: F = Fan(cones=[(0,1,2,3), (0,1,4)],
|
|
788
|
+
....: rays=[(1,1,1), (1,-1,1), (1,-1,-1), (1,1,-1), (0,0,1)])
|
|
789
|
+
sage: X = ToricVariety(F)
|
|
790
|
+
sage: square_cone = X.fan().cone_containing(0,1,2,3)
|
|
791
|
+
sage: triangle_cone = X.fan().cone_containing(0,1,4)
|
|
792
|
+
sage: line_cone = square_cone.intersection(triangle_cone)
|
|
793
|
+
sage: Cartier = X.divisor([2,2,1,1,1])
|
|
794
|
+
sage: Cartier
|
|
795
|
+
2*V(z0) + 2*V(z1) + V(z2) + V(z3) + V(z4)
|
|
796
|
+
sage: Cartier.move_away_from(line_cone)
|
|
797
|
+
3*V(z2) + 3*V(z3) - V(z4)
|
|
798
|
+
sage: QQ_Weil = X.divisor([1,0,1,1,0])
|
|
799
|
+
sage: QQ_Weil.move_away_from(line_cone)
|
|
800
|
+
2*V(z2) + V(z3) - 1/2*V(z4)
|
|
801
|
+
"""
|
|
802
|
+
m = self.m(cone)
|
|
803
|
+
X = self.parent().scheme()
|
|
804
|
+
fan = X.fan()
|
|
805
|
+
if m in fan.lattice():
|
|
806
|
+
ring = self._ring
|
|
807
|
+
else:
|
|
808
|
+
ring = m.base_ring()
|
|
809
|
+
divisor = list(vector(self))
|
|
810
|
+
values = [mult - m * ray for mult, ray in zip(divisor, fan.rays())]
|
|
811
|
+
return ToricDivisor(X, values, ring=ring)
|
|
812
|
+
|
|
813
|
+
def cohomology_class(self):
|
|
814
|
+
r"""
|
|
815
|
+
Return the degree-2 cohomology class associated to the divisor.
|
|
816
|
+
|
|
817
|
+
OUTPUT:
|
|
818
|
+
|
|
819
|
+
The corresponding cohomology class as an instance of
|
|
820
|
+
:class:`~sage.schemes.toric.variety.CohomologyClass`.
|
|
821
|
+
The cohomology class is the first Chern class of the
|
|
822
|
+
associated line bundle `\mathcal{O}(D)`.
|
|
823
|
+
|
|
824
|
+
EXAMPLES::
|
|
825
|
+
|
|
826
|
+
sage: dP6 = toric_varieties.dP6()
|
|
827
|
+
sage: D = dP6.divisor(dP6.fan().ray(0))
|
|
828
|
+
sage: D.cohomology_class() # needs sage.libs.singular
|
|
829
|
+
[y + v - w]
|
|
830
|
+
"""
|
|
831
|
+
divisor = vector(self)
|
|
832
|
+
variety = self.parent().scheme()
|
|
833
|
+
HH = variety.cohomology_ring()
|
|
834
|
+
return sum([divisor[i] * HH.gen(i) for i in range(HH.ngens())])
|
|
835
|
+
|
|
836
|
+
def Chern_character(self):
|
|
837
|
+
r"""
|
|
838
|
+
Return the Chern character of the sheaf `\mathcal{O}(D)`
|
|
839
|
+
defined by the divisor `D`.
|
|
840
|
+
|
|
841
|
+
You can also use a shortcut :meth:`ch`.
|
|
842
|
+
|
|
843
|
+
EXAMPLES::
|
|
844
|
+
|
|
845
|
+
sage: dP6 = toric_varieties.dP6()
|
|
846
|
+
sage: N = dP6.fan().lattice()
|
|
847
|
+
sage: D3 = dP6.divisor(dP6.fan().cone_containing( N(0,1) ))
|
|
848
|
+
sage: D5 = dP6.divisor(dP6.fan().cone_containing( N(-1,-1) ))
|
|
849
|
+
sage: D6 = dP6.divisor(dP6.fan().cone_containing( N(0,-1) ))
|
|
850
|
+
sage: D = -D3 + 2*D5 - D6
|
|
851
|
+
sage: D.Chern_character() # needs sage.libs.singular
|
|
852
|
+
[5*w^2 + y - 2*v + w + 1]
|
|
853
|
+
sage: dP6.integrate(D.ch() * dP6.Td()) # needs sage.libs.singular
|
|
854
|
+
-4
|
|
855
|
+
"""
|
|
856
|
+
return self.cohomology_class().exp()
|
|
857
|
+
|
|
858
|
+
ch = Chern_character
|
|
859
|
+
|
|
860
|
+
def divisor_class(self):
|
|
861
|
+
r"""
|
|
862
|
+
Return the linear equivalence class of the divisor.
|
|
863
|
+
|
|
864
|
+
OUTPUT:
|
|
865
|
+
|
|
866
|
+
The class of the divisor in `\mathop{Cl}(X)
|
|
867
|
+
\otimes_\ZZ \QQ` as an instance of
|
|
868
|
+
:class:`ToricRationalDivisorClassGroup`.
|
|
869
|
+
|
|
870
|
+
EXAMPLES::
|
|
871
|
+
|
|
872
|
+
sage: dP6 = toric_varieties.dP6()
|
|
873
|
+
sage: D = dP6.divisor(0)
|
|
874
|
+
sage: D.divisor_class()
|
|
875
|
+
Divisor class [1, 0, 0, 0]
|
|
876
|
+
"""
|
|
877
|
+
if '_divisor_class' not in self.__dict__:
|
|
878
|
+
self._divisor_class = self.parent().scheme().rational_class_group()(self)
|
|
879
|
+
return self._divisor_class
|
|
880
|
+
|
|
881
|
+
def Chow_cycle(self, ring=ZZ):
|
|
882
|
+
r"""
|
|
883
|
+
Return the Chow homology class of the divisor.
|
|
884
|
+
|
|
885
|
+
INPUT:
|
|
886
|
+
|
|
887
|
+
- ``ring`` -- either ``ZZ`` (default) or ``QQ``; the base ring
|
|
888
|
+
of the Chow group
|
|
889
|
+
|
|
890
|
+
OUTPUT:
|
|
891
|
+
|
|
892
|
+
The :class:`~sage.schemes.toric.chow_group.ChowCycle`
|
|
893
|
+
represented by the divisor.
|
|
894
|
+
|
|
895
|
+
EXAMPLES::
|
|
896
|
+
|
|
897
|
+
sage: dP6 = toric_varieties.dP6()
|
|
898
|
+
sage: cone = dP6.fan(1)[5]
|
|
899
|
+
sage: D = dP6.divisor(cone); D
|
|
900
|
+
V(w)
|
|
901
|
+
sage: D.Chow_cycle()
|
|
902
|
+
( 0 | -1, 0, 1, 1 | 0 )
|
|
903
|
+
sage: dP6.Chow_group()(cone)
|
|
904
|
+
( 0 | -1, 0, 1, 1 | 0 )
|
|
905
|
+
"""
|
|
906
|
+
toric_variety = self.parent().scheme()
|
|
907
|
+
fan = toric_variety.fan()
|
|
908
|
+
A = toric_variety.Chow_group(ring)
|
|
909
|
+
return sum(self.coefficient(i) * A(cone_1d)
|
|
910
|
+
for i, cone_1d in enumerate(fan(dim=1)))
|
|
911
|
+
|
|
912
|
+
def is_ample(self):
|
|
913
|
+
r"""
|
|
914
|
+
Return whether a `\QQ`-Cartier divisor is ample.
|
|
915
|
+
|
|
916
|
+
OUTPUT: ``True`` if the divisor is in the ample cone, ``False`` otherwise
|
|
917
|
+
|
|
918
|
+
.. NOTE::
|
|
919
|
+
|
|
920
|
+
* For a `\QQ`-Cartier divisor, some positive integral
|
|
921
|
+
multiple is Cartier. We return whether this associated
|
|
922
|
+
divisor is ample, i.e. corresponds to an ample line bundle.
|
|
923
|
+
|
|
924
|
+
* In the orbifold case, the ample cone is an open
|
|
925
|
+
and full-dimensional cone in the rational divisor class
|
|
926
|
+
group :class:`ToricRationalDivisorClassGroup`.
|
|
927
|
+
|
|
928
|
+
* If the variety has worse than orbifold singularities,
|
|
929
|
+
the ample cone is a full-dimensional cone within the
|
|
930
|
+
(not full-dimensional) subspace spanned by the Cartier
|
|
931
|
+
divisors inside the rational (Weil) divisor class group,
|
|
932
|
+
that is, :class:`ToricRationalDivisorClassGroup`. The
|
|
933
|
+
ample cone is then relative open (open in this
|
|
934
|
+
subspace).
|
|
935
|
+
|
|
936
|
+
* See also :meth:`is_nef`.
|
|
937
|
+
|
|
938
|
+
* A toric divisor is ample if and only if its support
|
|
939
|
+
function is strictly convex.
|
|
940
|
+
|
|
941
|
+
EXAMPLES::
|
|
942
|
+
|
|
943
|
+
sage: P2 = toric_varieties.P2()
|
|
944
|
+
sage: K = P2.K()
|
|
945
|
+
sage: (+K).is_ample()
|
|
946
|
+
False
|
|
947
|
+
sage: (0*K).is_ample()
|
|
948
|
+
False
|
|
949
|
+
sage: (-K).is_ample()
|
|
950
|
+
True
|
|
951
|
+
|
|
952
|
+
Example 6.1.3, 6.1.11, 6.1.17 of [CLS2011]_::
|
|
953
|
+
|
|
954
|
+
sage: from itertools import product
|
|
955
|
+
sage: fan = Fan(cones=[(0,1), (1,2), (2,3), (3,0)],
|
|
956
|
+
....: rays=[(-1,2), (0,1), (1,0), (0,-1)])
|
|
957
|
+
sage: F2 = ToricVariety(fan,'u1, u2, u3, u4')
|
|
958
|
+
sage: def D(a, b): return a*F2.divisor(2) + b*F2.divisor(3)
|
|
959
|
+
sage: [ (a,b) for a,b in product(range(-3,3), repeat=2)
|
|
960
|
+
....: if D(a,b).is_ample() ]
|
|
961
|
+
[(1, 1), (1, 2), (2, 1), (2, 2)]
|
|
962
|
+
sage: [ (a,b) for a,b in product(range(-3,3), repeat=2)
|
|
963
|
+
....: if D(a,b).is_nef() ]
|
|
964
|
+
[(0, 0), (0, 1), (0, 2), (1, 0), (1, 1), (1, 2), (2, 0), (2, 1), (2, 2)]
|
|
965
|
+
|
|
966
|
+
A (worse than orbifold) singular Fano threefold::
|
|
967
|
+
|
|
968
|
+
sage: points = [(1,0,0),(0,1,0),(0,0,1),(-2,0,-1),(-2,-1,0),(-3,-1,-1),(1,1,1)]
|
|
969
|
+
sage: facets = [[0,1,3],[0,1,6],[0,2,4],[0,2,6],[0,3,5],[0,4,5],[1,2,3,4,5,6]]
|
|
970
|
+
sage: X = ToricVariety(Fan(cones=facets, rays=points))
|
|
971
|
+
sage: X.rational_class_group().dimension()
|
|
972
|
+
4
|
|
973
|
+
sage: X.Kaehler_cone().rays()
|
|
974
|
+
Divisor class [1, 0, 0, 0]
|
|
975
|
+
in Basis lattice of The toric rational divisor class group
|
|
976
|
+
of a 3-d toric variety covered by 7 affine patches
|
|
977
|
+
sage: antiK = -X.K()
|
|
978
|
+
sage: antiK.divisor_class()
|
|
979
|
+
Divisor class [2, 0, 0, 0]
|
|
980
|
+
sage: antiK.is_ample()
|
|
981
|
+
True
|
|
982
|
+
"""
|
|
983
|
+
try:
|
|
984
|
+
return self._is_ample
|
|
985
|
+
except AttributeError:
|
|
986
|
+
pass
|
|
987
|
+
|
|
988
|
+
assert self.is_QQ_Cartier(), 'The divisor must be QQ-Cartier.'
|
|
989
|
+
Kc = self.parent().scheme().Kaehler_cone()
|
|
990
|
+
self._is_ample = Kc.relative_interior_contains(self.divisor_class())
|
|
991
|
+
return self._is_ample
|
|
992
|
+
|
|
993
|
+
def is_nef(self):
|
|
994
|
+
r"""
|
|
995
|
+
Return whether a `\QQ`-Cartier divisor is nef.
|
|
996
|
+
|
|
997
|
+
OUTPUT:
|
|
998
|
+
|
|
999
|
+
- ``True`` if the divisor is in the closure of the ample cone,
|
|
1000
|
+
``False`` otherwise.
|
|
1001
|
+
|
|
1002
|
+
.. NOTE::
|
|
1003
|
+
|
|
1004
|
+
* For a `\QQ`-Cartier divisor, some positive integral multiple is
|
|
1005
|
+
Cartier. We return whether this associated divisor is nef.
|
|
1006
|
+
|
|
1007
|
+
* The nef cone is the closure of the ample cone.
|
|
1008
|
+
|
|
1009
|
+
* See also :meth:`is_ample`.
|
|
1010
|
+
|
|
1011
|
+
* A toric divisor is nef if and only if its support
|
|
1012
|
+
function is convex (but not necessarily strictly
|
|
1013
|
+
convex).
|
|
1014
|
+
|
|
1015
|
+
* A toric Cartier divisor is nef if and only if its linear
|
|
1016
|
+
system is basepoint free.
|
|
1017
|
+
|
|
1018
|
+
EXAMPLES::
|
|
1019
|
+
|
|
1020
|
+
sage: P2 = toric_varieties.P2()
|
|
1021
|
+
sage: K = P2.K()
|
|
1022
|
+
sage: (+K).is_nef()
|
|
1023
|
+
False
|
|
1024
|
+
sage: (0*K).is_nef()
|
|
1025
|
+
True
|
|
1026
|
+
sage: (-K).is_nef()
|
|
1027
|
+
True
|
|
1028
|
+
|
|
1029
|
+
Example 6.1.3, 6.1.11, 6.1.17 of [CLS2011]_::
|
|
1030
|
+
|
|
1031
|
+
sage: from itertools import product
|
|
1032
|
+
sage: fan = Fan(cones=[(0,1), (1,2), (2,3), (3,0)],
|
|
1033
|
+
....: rays=[(-1,2), (0,1), (1,0), (0,-1)])
|
|
1034
|
+
sage: F2 = ToricVariety(fan,'u1, u2, u3, u4')
|
|
1035
|
+
sage: def D(a, b): return a*F2.divisor(2) + b*F2.divisor(3)
|
|
1036
|
+
sage: [ (a,b) for a,b in product(range(-3,3), repeat=2)
|
|
1037
|
+
....: if D(a,b).is_ample() ]
|
|
1038
|
+
[(1, 1), (1, 2), (2, 1), (2, 2)]
|
|
1039
|
+
sage: [ (a,b) for a,b in product(range(-3,3), repeat=2)
|
|
1040
|
+
....: if D(a,b).is_nef() ]
|
|
1041
|
+
[(0, 0), (0, 1), (0, 2), (1, 0), (1, 1), (1, 2), (2, 0), (2, 1), (2, 2)]
|
|
1042
|
+
"""
|
|
1043
|
+
try:
|
|
1044
|
+
return self._is_nef
|
|
1045
|
+
except AttributeError:
|
|
1046
|
+
pass
|
|
1047
|
+
|
|
1048
|
+
assert self.is_QQ_Cartier(), 'The divisor must be QQ-Cartier.'
|
|
1049
|
+
self._is_nef = self.divisor_class() in self.parent().scheme().Kaehler_cone()
|
|
1050
|
+
return self._is_nef
|
|
1051
|
+
|
|
1052
|
+
def polyhedron(self):
|
|
1053
|
+
r"""
|
|
1054
|
+
Return the polyhedron `P_D\subset M` associated to a toric
|
|
1055
|
+
divisor `D`.
|
|
1056
|
+
|
|
1057
|
+
OUTPUT: `P_D` as an instance of :class:`~sage.geometry.polyhedron.base.Polyhedron_base`
|
|
1058
|
+
|
|
1059
|
+
EXAMPLES::
|
|
1060
|
+
|
|
1061
|
+
sage: dP7 = toric_varieties.dP7()
|
|
1062
|
+
sage: D = dP7.divisor(2)
|
|
1063
|
+
sage: P_D = D.polyhedron(); P_D
|
|
1064
|
+
A 0-dimensional polyhedron in QQ^2 defined as the convex hull of 1 vertex
|
|
1065
|
+
sage: P_D.Vrepresentation()
|
|
1066
|
+
(A vertex at (0, 0),)
|
|
1067
|
+
sage: D.is_nef()
|
|
1068
|
+
False
|
|
1069
|
+
sage: dP7.integrate(D.ch() * dP7.Td()) # needs sage.libs.singular
|
|
1070
|
+
1
|
|
1071
|
+
sage: P_antiK = (-dP7.K()).polyhedron(); P_antiK
|
|
1072
|
+
A 2-dimensional polyhedron in QQ^2 defined as the convex hull of 5 vertices
|
|
1073
|
+
sage: P_antiK.Vrepresentation()
|
|
1074
|
+
(A vertex at (1, -1), A vertex at (0, 1), A vertex at (1, 0),
|
|
1075
|
+
A vertex at (-1, 1), A vertex at (-1, -1))
|
|
1076
|
+
sage: P_antiK.integral_points()
|
|
1077
|
+
((-1, -1), (-1, 0), (-1, 1), (0, -1), (0, 0), (0, 1), (1, -1), (1, 0))
|
|
1078
|
+
|
|
1079
|
+
Example 6.1.3, 6.1.11, 6.1.17 of [CLS2011]_::
|
|
1080
|
+
|
|
1081
|
+
sage: fan = Fan(cones=[(0,1), (1,2), (2,3), (3,0)],
|
|
1082
|
+
....: rays=[(-1,2), (0,1), (1,0), (0,-1)])
|
|
1083
|
+
sage: F2 = ToricVariety(fan,'u1, u2, u3, u4')
|
|
1084
|
+
sage: D = F2.divisor(3)
|
|
1085
|
+
sage: D.polyhedron().Vrepresentation()
|
|
1086
|
+
(A vertex at (0, 0), A vertex at (2, 1), A vertex at (0, 1))
|
|
1087
|
+
sage: Dprime = F2.divisor(1) + D
|
|
1088
|
+
sage: Dprime.polyhedron().Vrepresentation()
|
|
1089
|
+
(A vertex at (2, 1), A vertex at (0, 1), A vertex at (0, 0))
|
|
1090
|
+
sage: D.is_ample()
|
|
1091
|
+
False
|
|
1092
|
+
sage: D.is_nef()
|
|
1093
|
+
True
|
|
1094
|
+
sage: Dprime.is_nef()
|
|
1095
|
+
False
|
|
1096
|
+
|
|
1097
|
+
A more complicated example where `P_D` is not a lattice polytope::
|
|
1098
|
+
|
|
1099
|
+
sage: X = toric_varieties.BCdlOG_base()
|
|
1100
|
+
sage: antiK = -X.K()
|
|
1101
|
+
sage: P_D = antiK.polyhedron()
|
|
1102
|
+
sage: P_D
|
|
1103
|
+
A 3-dimensional polyhedron in QQ^3 defined as the convex hull of 8 vertices
|
|
1104
|
+
sage: P_D.Vrepresentation()
|
|
1105
|
+
(A vertex at (1, -1, 0), A vertex at (1, -3, 1),
|
|
1106
|
+
A vertex at (1, 1, 1), A vertex at (-5, 1, 1),
|
|
1107
|
+
A vertex at (1, 1, -1/2), A vertex at (1, 1/2, -1/2),
|
|
1108
|
+
A vertex at (-1, -1, 0), A vertex at (-5, -3, 1))
|
|
1109
|
+
sage: P_D.Hrepresentation()
|
|
1110
|
+
(An inequality (-1, 0, 0) x + 1 >= 0, An inequality (0, -1, 0) x + 1 >= 0,
|
|
1111
|
+
An inequality (0, 0, -1) x + 1 >= 0, An inequality (1, 0, 4) x + 1 >= 0,
|
|
1112
|
+
An inequality (0, 1, 3) x + 1 >= 0, An inequality (0, 1, 2) x + 1 >= 0)
|
|
1113
|
+
sage: P_D.integral_points()
|
|
1114
|
+
((-1, -1, 0), (0, -1, 0), (1, -1, 0), (-1, 0, 0), (0, 0, 0),
|
|
1115
|
+
(1, 0, 0), (-1, 1, 0), (0, 1, 0), (1, 1, 0), (-5, -3, 1),
|
|
1116
|
+
(-4, -3, 1), (-3, -3, 1), (-2, -3, 1), (-1, -3, 1), (0, -3, 1),
|
|
1117
|
+
(1, -3, 1), (-5, -2, 1), (-4, -2, 1), (-3, -2, 1), (-2, -2, 1),
|
|
1118
|
+
(-1, -2, 1), (0, -2, 1), (1, -2, 1), (-5, -1, 1), (-4, -1, 1),
|
|
1119
|
+
(-3, -1, 1), (-2, -1, 1), (-1, -1, 1), (0, -1, 1), (1, -1, 1),
|
|
1120
|
+
(-5, 0, 1), (-4, 0, 1), (-3, 0, 1), (-2, 0, 1), (-1, 0, 1),
|
|
1121
|
+
(0, 0, 1), (1, 0, 1), (-5, 1, 1), (-4, 1, 1), (-3, 1, 1),
|
|
1122
|
+
(-2, 1, 1), (-1, 1, 1), (0, 1, 1), (1, 1, 1))
|
|
1123
|
+
"""
|
|
1124
|
+
try:
|
|
1125
|
+
return self._polyhedron
|
|
1126
|
+
except AttributeError:
|
|
1127
|
+
pass
|
|
1128
|
+
|
|
1129
|
+
fan = self.parent().scheme().fan()
|
|
1130
|
+
divisor = vector(self)
|
|
1131
|
+
ieqs = [[divisor[i]] + list(fan.ray(i)) for i in range(fan.nrays())]
|
|
1132
|
+
self._polyhedron = Polyhedron(ieqs=ieqs)
|
|
1133
|
+
return self._polyhedron
|
|
1134
|
+
|
|
1135
|
+
def sections(self):
|
|
1136
|
+
"""
|
|
1137
|
+
Return the global sections (as points of the `M`-lattice) of
|
|
1138
|
+
the line bundle (or reflexive sheaf) associated to the
|
|
1139
|
+
divisor.
|
|
1140
|
+
|
|
1141
|
+
OUTPUT: a :class:`tuple` of points of lattice `M`
|
|
1142
|
+
|
|
1143
|
+
EXAMPLES::
|
|
1144
|
+
|
|
1145
|
+
sage: P2 = toric_varieties.P2()
|
|
1146
|
+
sage: P2.fan().nrays()
|
|
1147
|
+
3
|
|
1148
|
+
sage: P2.divisor(0).sections()
|
|
1149
|
+
(M(-1, 0), M(-1, 1), M(0, 0))
|
|
1150
|
+
sage: P2.divisor(1).sections()
|
|
1151
|
+
(M(0, -1), M(0, 0), M(1, -1))
|
|
1152
|
+
sage: P2.divisor(2).sections()
|
|
1153
|
+
(M(0, 0), M(0, 1), M(1, 0))
|
|
1154
|
+
|
|
1155
|
+
The divisor can be non-nef yet still have sections::
|
|
1156
|
+
|
|
1157
|
+
sage: rays = [(1,0,0),(0,1,0),(0,0,1),(-2,0,-1),(-2,-1,0),(-3,-1,-1),(1,1,1),(-1,0,0)]
|
|
1158
|
+
sage: cones = [[0,1,3],[0,1,6],[0,2,4],[0,2,6],[0,3,5],[0,4,5],[1,3,7],[1,6,7],[2,4,7],[2,6,7],[3,5,7],[4,5,7]]
|
|
1159
|
+
sage: X = ToricVariety(Fan(rays=rays, cones=cones))
|
|
1160
|
+
sage: D = X.divisor(2); D
|
|
1161
|
+
V(z2)
|
|
1162
|
+
sage: D.is_nef()
|
|
1163
|
+
False
|
|
1164
|
+
sage: D.sections()
|
|
1165
|
+
(M(0, 0, 0),)
|
|
1166
|
+
sage: D.cohomology(dim=True)
|
|
1167
|
+
(1, 0, 0, 0)
|
|
1168
|
+
"""
|
|
1169
|
+
try:
|
|
1170
|
+
return self._sections
|
|
1171
|
+
except AttributeError:
|
|
1172
|
+
pass
|
|
1173
|
+
|
|
1174
|
+
M = self.parent().scheme().fan().dual_lattice()
|
|
1175
|
+
self._sections = tuple(M(m)
|
|
1176
|
+
for m in self.polyhedron().integral_points())
|
|
1177
|
+
return self._sections
|
|
1178
|
+
|
|
1179
|
+
def sections_monomials(self):
|
|
1180
|
+
"""
|
|
1181
|
+
Return the global sections of the line bundle associated to the
|
|
1182
|
+
Cartier divisor.
|
|
1183
|
+
|
|
1184
|
+
The sections are described as monomials in the generalized homogeneous
|
|
1185
|
+
coordinates.
|
|
1186
|
+
|
|
1187
|
+
OUTPUT: tuple of monomials in the coordinate ring of ``self``
|
|
1188
|
+
|
|
1189
|
+
EXAMPLES::
|
|
1190
|
+
|
|
1191
|
+
sage: P2 = toric_varieties.P2()
|
|
1192
|
+
sage: P2.fan().nrays()
|
|
1193
|
+
3
|
|
1194
|
+
sage: P2.divisor(0).sections_monomials()
|
|
1195
|
+
(z, y, x)
|
|
1196
|
+
sage: P2.divisor(1).sections_monomials()
|
|
1197
|
+
(z, y, x)
|
|
1198
|
+
sage: P2.divisor(2).sections_monomials()
|
|
1199
|
+
(z, y, x)
|
|
1200
|
+
|
|
1201
|
+
From [Cox]_ page 38::
|
|
1202
|
+
|
|
1203
|
+
sage: lp = LatticePolytope([(1,0), (1,1), (0,1), (-1,0), (0,-1)])
|
|
1204
|
+
sage: lp # needs polytopes_db
|
|
1205
|
+
2-d reflexive polytope #5 in 2-d lattice M
|
|
1206
|
+
sage: dP7 = ToricVariety(FaceFan(lp), 'x1, x2, x3, x4, x5')
|
|
1207
|
+
sage: AK = -dP7.K()
|
|
1208
|
+
sage: AK.sections()
|
|
1209
|
+
(N(-1, 0), N(-1, 1), N(0, -1), N(0, 0),
|
|
1210
|
+
N(0, 1), N(1, -1), N(1, 0), N(1, 1))
|
|
1211
|
+
sage: AK.sections_monomials()
|
|
1212
|
+
(x3*x4^2*x5, x2*x3^2*x4^2, x1*x4*x5^2, x1*x2*x3*x4*x5,
|
|
1213
|
+
x1*x2^2*x3^2*x4, x1^2*x2*x5^2, x1^2*x2^2*x3*x5, x1^2*x2^3*x3^2)
|
|
1214
|
+
"""
|
|
1215
|
+
return tuple(self.monomial(m) for m in self.sections())
|
|
1216
|
+
|
|
1217
|
+
def monomial(self, point):
|
|
1218
|
+
r"""
|
|
1219
|
+
Return the monomial in the homogeneous coordinate ring
|
|
1220
|
+
associated to the ``point`` in the dual lattice.
|
|
1221
|
+
|
|
1222
|
+
INPUT:
|
|
1223
|
+
|
|
1224
|
+
- ``point`` -- a point in ``self.variety().fan().dual_lattice()``
|
|
1225
|
+
|
|
1226
|
+
OUTPUT:
|
|
1227
|
+
|
|
1228
|
+
For a fixed divisor ``D``, the sections are generated by
|
|
1229
|
+
monomials in :meth:`ToricVariety.coordinate_ring
|
|
1230
|
+
<sage.schemes.toric.variety.ToricVariety_field.coordinate_ring>`.
|
|
1231
|
+
Alternatively, the monomials can be described as `M`-lattice
|
|
1232
|
+
points in the polyhedron ``D.polyhedron()``. This method
|
|
1233
|
+
converts the points `m\in M` into homogeneous polynomials.
|
|
1234
|
+
|
|
1235
|
+
EXAMPLES::
|
|
1236
|
+
|
|
1237
|
+
sage: P2 = toric_varieties.P2()
|
|
1238
|
+
sage: O3_P2 = -P2.K()
|
|
1239
|
+
sage: M = P2.fan().dual_lattice()
|
|
1240
|
+
sage: O3_P2.monomial( M(0,0) )
|
|
1241
|
+
x*y*z
|
|
1242
|
+
"""
|
|
1243
|
+
X = self.parent().scheme()
|
|
1244
|
+
fan = X.fan()
|
|
1245
|
+
assert point in fan.dual_lattice(), \
|
|
1246
|
+
f'{point} must be a point in the M-lattice'
|
|
1247
|
+
R = X.coordinate_ring()
|
|
1248
|
+
return prod([R.gen(i) ** (point * fan.ray(i) + self.coefficient(i))
|
|
1249
|
+
for i in range(fan.nrays())])
|
|
1250
|
+
|
|
1251
|
+
def Kodaira_map(self, names='z'):
|
|
1252
|
+
r"""
|
|
1253
|
+
Return the Kodaira map.
|
|
1254
|
+
|
|
1255
|
+
The Kodaira map is the rational map `X_\Sigma \to
|
|
1256
|
+
\mathbb{P}^{n-1}`, where `n` equals the number of sections. It
|
|
1257
|
+
is defined by the monomial sections of the line bundle.
|
|
1258
|
+
|
|
1259
|
+
If the divisor is ample and the toric variety smooth or of
|
|
1260
|
+
dimension 2, then this is an embedding.
|
|
1261
|
+
|
|
1262
|
+
INPUT:
|
|
1263
|
+
|
|
1264
|
+
- ``names`` -- string (default: ``'z'``); the
|
|
1265
|
+
variable names for the destination projective space
|
|
1266
|
+
|
|
1267
|
+
EXAMPLES::
|
|
1268
|
+
|
|
1269
|
+
sage: P1.<u,v> = toric_varieties.P1()
|
|
1270
|
+
sage: D = -P1.K()
|
|
1271
|
+
sage: D.Kodaira_map() # needs fpylll sage.libs.singular
|
|
1272
|
+
Scheme morphism:
|
|
1273
|
+
From: 1-d CPR-Fano toric variety covered by 2 affine patches
|
|
1274
|
+
To: Closed subscheme of Projective Space of dimension 2
|
|
1275
|
+
over Rational Field defined by: -z1^2 + z0*z2
|
|
1276
|
+
Defn: Defined on coordinates by sending [u : v] to (v^2 : u*v : u^2)
|
|
1277
|
+
|
|
1278
|
+
sage: dP6 = toric_varieties.dP6()
|
|
1279
|
+
sage: D = -dP6.K()
|
|
1280
|
+
sage: D.Kodaira_map(names='x') # needs fpylll sage.libs.singular
|
|
1281
|
+
Scheme morphism:
|
|
1282
|
+
From: 2-d CPR-Fano toric variety covered by 6 affine patches
|
|
1283
|
+
To: Closed subscheme of Projective Space of dimension 6
|
|
1284
|
+
over Rational Field defined by:
|
|
1285
|
+
-x1*x5 + x0*x6, -x2*x3 + x0*x5, -x1*x3 + x0*x4,
|
|
1286
|
+
x4*x5 - x3*x6, -x1*x2 + x0*x3, x3*x5 - x2*x6,
|
|
1287
|
+
x3*x4 - x1*x6, x3^2 - x1*x5, x2*x4 - x1*x5,
|
|
1288
|
+
-x1*x5^2 + x2*x3*x6, -x1*x5^3 + x2^2*x6^2
|
|
1289
|
+
Defn: Defined on coordinates by sending [x : u : y : v : z : w] to
|
|
1290
|
+
(x*u^2*y^2*v : x^2*u^2*y*w : u*y^2*v^2*z : x*u*y*v*z*w :
|
|
1291
|
+
x^2*u*z*w^2 : y*v^2*z^2*w : x*v*z^2*w^2)
|
|
1292
|
+
"""
|
|
1293
|
+
sections = self.sections_monomials()
|
|
1294
|
+
if not sections:
|
|
1295
|
+
raise ValueError('the Kodaira map is not defined for divisors without sections')
|
|
1296
|
+
src = self.parent().scheme()
|
|
1297
|
+
from sage.schemes.projective.projective_space import ProjectiveSpace
|
|
1298
|
+
ambient = ProjectiveSpace(src.base_ring(), len(sections) - 1, names=names)
|
|
1299
|
+
A = matrix(ZZ, [list(s.exponents()[0]) for s in sections]).transpose()
|
|
1300
|
+
from sage.schemes.toric.ideal import ToricIdeal
|
|
1301
|
+
IA = ToricIdeal(A, names=names)
|
|
1302
|
+
dst = ambient.subscheme(IA)
|
|
1303
|
+
homset = src.Hom(dst)
|
|
1304
|
+
return homset(sections)
|
|
1305
|
+
|
|
1306
|
+
def _sheaf_complex(self, m):
|
|
1307
|
+
r"""
|
|
1308
|
+
Return a simplicial complex whose cohomology is isomorphic to the
|
|
1309
|
+
`m\in M`-graded piece of the sheaf cohomology.
|
|
1310
|
+
|
|
1311
|
+
Helper for :meth:`cohomology`.
|
|
1312
|
+
|
|
1313
|
+
INPUT:
|
|
1314
|
+
|
|
1315
|
+
- ``m`` -- a point in ``self.scheme().fan().dual_lattice()``
|
|
1316
|
+
|
|
1317
|
+
OUTPUT: a :class:`simplicial complex <sage.topology.simplicial_complex.SimplicialComplex>`
|
|
1318
|
+
|
|
1319
|
+
EXAMPLES::
|
|
1320
|
+
|
|
1321
|
+
sage: dP6 = toric_varieties.dP6()
|
|
1322
|
+
sage: D0 = dP6.divisor(0)
|
|
1323
|
+
sage: D2 = dP6.divisor(2)
|
|
1324
|
+
sage: D3 = dP6.divisor(3)
|
|
1325
|
+
sage: D = -D0 + 2*D2 - D3
|
|
1326
|
+
sage: M = dP6.fan().dual_lattice()
|
|
1327
|
+
sage: D._sheaf_complex( M(1,0) )
|
|
1328
|
+
Simplicial complex with vertex set (0, 1, 3) and facets {(3,), (0, 1)}
|
|
1329
|
+
"""
|
|
1330
|
+
fan = self.parent().scheme().fan()
|
|
1331
|
+
ray_is_negative = [m * ray + self.coefficient(i) < 0
|
|
1332
|
+
for i, ray in enumerate(fan.rays())]
|
|
1333
|
+
|
|
1334
|
+
def cone_is_negative(cone): # and non-trivial
|
|
1335
|
+
if cone.is_trivial():
|
|
1336
|
+
return False
|
|
1337
|
+
return all(ray_is_negative[i] for i in cone.ambient_ray_indices())
|
|
1338
|
+
|
|
1339
|
+
negative_cones = [cone for cone in flatten(fan.cones()) if cone_is_negative(cone)]
|
|
1340
|
+
return SimplicialComplex([c.ambient_ray_indices() for c in negative_cones])
|
|
1341
|
+
|
|
1342
|
+
def _sheaf_cohomology(self, cplx):
|
|
1343
|
+
"""
|
|
1344
|
+
Return the sheaf cohomology as the shifted, reduced cohomology
|
|
1345
|
+
of the complex.
|
|
1346
|
+
|
|
1347
|
+
Helper for :meth:`cohomology`.
|
|
1348
|
+
|
|
1349
|
+
INPUT:
|
|
1350
|
+
|
|
1351
|
+
- ``cplx`` -- simplicial complex
|
|
1352
|
+
|
|
1353
|
+
OUTPUT: integer vector
|
|
1354
|
+
|
|
1355
|
+
EXAMPLES::
|
|
1356
|
+
|
|
1357
|
+
sage: dP6 = toric_varieties.dP6()
|
|
1358
|
+
sage: D = dP6.divisor(1)
|
|
1359
|
+
sage: D._sheaf_cohomology( SimplicialComplex() )
|
|
1360
|
+
(1, 0, 0)
|
|
1361
|
+
sage: D._sheaf_cohomology( SimplicialComplex([[1,2],[2,3],[3,1]]) )
|
|
1362
|
+
(0, 0, 1)
|
|
1363
|
+
|
|
1364
|
+
A more complicated example to test that :issue:`10731` is fixed::
|
|
1365
|
+
|
|
1366
|
+
sage: cell24 = Polyhedron(vertices=[
|
|
1367
|
+
....: (1,0,0,0),(0,1,0,0),(0,0,1,0),(0,0,0,1),(1,-1,-1,1),(0,0,-1,1),
|
|
1368
|
+
....: (0,-1,0,1),(-1,0,0,1),(1,0,0,-1),(0,1,0,-1),(0,0,1,-1),(-1,1,1,-1),
|
|
1369
|
+
....: (1,-1,-1,0),(0,0,-1,0),(0,-1,0,0),(-1,0,0,0),(1,-1,0,0),(1,0,-1,0),
|
|
1370
|
+
....: (0,1,1,-1),(-1,1,1,0),(-1,1,0,0),(-1,0,1,0),(0,-1,-1,1),(0,0,0,-1)])
|
|
1371
|
+
sage: X = ToricVariety(FaceFan(cell24.lattice_polytope())) # long time
|
|
1372
|
+
sage: D = -X.divisor(0) # long time
|
|
1373
|
+
sage: D.cohomology(dim=True) # long time
|
|
1374
|
+
(0, 0, 0, 0, 0)
|
|
1375
|
+
"""
|
|
1376
|
+
d = self.parent().scheme().dimension()
|
|
1377
|
+
if cplx.dimension() == -1:
|
|
1378
|
+
return vector(ZZ, [1] + [0] * d)
|
|
1379
|
+
|
|
1380
|
+
HH = cplx.homology(base_ring=QQ, cohomology=True)
|
|
1381
|
+
HH_list = [0] * (d + 1)
|
|
1382
|
+
for h in HH.items():
|
|
1383
|
+
degree = h[0] + 1
|
|
1384
|
+
cohomology_dim = h[1].dimension()
|
|
1385
|
+
if degree > d or degree < 0:
|
|
1386
|
+
assert cohomology_dim == 0
|
|
1387
|
+
continue
|
|
1388
|
+
HH_list[degree] = cohomology_dim
|
|
1389
|
+
|
|
1390
|
+
return vector(ZZ, HH_list)
|
|
1391
|
+
|
|
1392
|
+
def _sheaf_cohomology_support(self):
|
|
1393
|
+
r"""
|
|
1394
|
+
Return the weights for which the cohomology groups can be non-vanishing.
|
|
1395
|
+
|
|
1396
|
+
OUTPUT:
|
|
1397
|
+
|
|
1398
|
+
A :class:`~sage.geometry.polyhedron.base.Polyhedron_base`
|
|
1399
|
+
object that contains all weights `m` for which the sheaf
|
|
1400
|
+
cohomology is *potentially* non-vanishing.
|
|
1401
|
+
|
|
1402
|
+
ALGORITHM:
|
|
1403
|
+
|
|
1404
|
+
See :meth:`cohomology` and note that every `d`-tuple (where
|
|
1405
|
+
`d` is the dimension of the variety) of rays determines one
|
|
1406
|
+
vertex in the chamber decomposition if none of the hyperplanes
|
|
1407
|
+
are parallel.
|
|
1408
|
+
|
|
1409
|
+
EXAMPLES::
|
|
1410
|
+
|
|
1411
|
+
sage: dP6 = toric_varieties.dP6()
|
|
1412
|
+
sage: D0 = dP6.divisor(0)
|
|
1413
|
+
sage: D2 = dP6.divisor(2)
|
|
1414
|
+
sage: D3 = dP6.divisor(3)
|
|
1415
|
+
sage: D = -D0 + 2*D2 - D3
|
|
1416
|
+
sage: supp = D._sheaf_cohomology_support()
|
|
1417
|
+
sage: supp
|
|
1418
|
+
A 2-dimensional polyhedron in QQ^2 defined as the convex hull of 4 vertices
|
|
1419
|
+
sage: supp.Vrepresentation()
|
|
1420
|
+
(A vertex at (-1, 1), A vertex at (0, -1), A vertex at (3, -1), A vertex at (0, 2))
|
|
1421
|
+
"""
|
|
1422
|
+
X = self.parent().scheme()
|
|
1423
|
+
fan = X.fan()
|
|
1424
|
+
if not X.is_complete():
|
|
1425
|
+
raise ValueError("%s is not complete, its cohomology is not "
|
|
1426
|
+
"finite-dimensional" % X)
|
|
1427
|
+
d = X.dimension()
|
|
1428
|
+
chamber_vertices = []
|
|
1429
|
+
for pindexlist in Combinations(range(fan.nrays()), d):
|
|
1430
|
+
A = matrix(ZZ, [fan.ray(p) for p in pindexlist])
|
|
1431
|
+
b = vector([self.coefficient(p) for p in pindexlist])
|
|
1432
|
+
try:
|
|
1433
|
+
chamber_vertices.append(A.solve_right(-b))
|
|
1434
|
+
except ValueError:
|
|
1435
|
+
pass
|
|
1436
|
+
return Polyhedron(vertices=chamber_vertices)
|
|
1437
|
+
|
|
1438
|
+
def cohomology(self, weight=None, deg=None, dim=False):
|
|
1439
|
+
r"""
|
|
1440
|
+
Return the cohomology of the line bundle associated to the
|
|
1441
|
+
Cartier divisor or reflexive sheaf associated to the Weil
|
|
1442
|
+
divisor.
|
|
1443
|
+
|
|
1444
|
+
.. NOTE::
|
|
1445
|
+
|
|
1446
|
+
The cohomology of a toric line bundle/reflexive sheaf is
|
|
1447
|
+
graded by the usual degree as well as by the `M`-lattice.
|
|
1448
|
+
|
|
1449
|
+
INPUT:
|
|
1450
|
+
|
|
1451
|
+
- ``weight`` -- (optional) a point of the `M`-lattice
|
|
1452
|
+
|
|
1453
|
+
- ``deg`` -- (optional) the degree of the cohomology group
|
|
1454
|
+
|
|
1455
|
+
- ``dim`` -- boolean; if ``False`` (default), the cohomology
|
|
1456
|
+
groups are returned as vector spaces. If ``True``, only the
|
|
1457
|
+
dimension of the vector space(s) is returned.
|
|
1458
|
+
|
|
1459
|
+
OUTPUT:
|
|
1460
|
+
|
|
1461
|
+
The vector space `H^\text{deg}(X,\mathcal{O}(D))` (if ``deg``
|
|
1462
|
+
is specified) or a dictionary ``{degree:cohomology(degree)}``
|
|
1463
|
+
of all degrees between 0 and the dimension of the variety.
|
|
1464
|
+
|
|
1465
|
+
If ``weight`` is specified, return only the subspace
|
|
1466
|
+
`H^\text{deg}(X,\mathcal{O}(D))_\text{weight}` of the
|
|
1467
|
+
cohomology of the given weight.
|
|
1468
|
+
|
|
1469
|
+
If ``dim==True``, the dimension of the cohomology vector space
|
|
1470
|
+
is returned instead of actual vector space. Moreover, if
|
|
1471
|
+
``deg`` was not specified, a vector whose entries are the
|
|
1472
|
+
dimensions is returned instead of a dictionary.
|
|
1473
|
+
|
|
1474
|
+
ALGORITHM:
|
|
1475
|
+
|
|
1476
|
+
Roughly, Chech cohomology is used to compute the
|
|
1477
|
+
cohomology. For toric divisors, the local sections can be
|
|
1478
|
+
chosen to be monomials (instead of general homogeneous
|
|
1479
|
+
polynomials), this is the reason for the extra grading by
|
|
1480
|
+
`m\in M`. General references would be [Ful1993]_, [CLS2011]_. Here
|
|
1481
|
+
are some salient features of our implementation:
|
|
1482
|
+
|
|
1483
|
+
* First, a finite set of `M`-lattice points is identified that
|
|
1484
|
+
supports the cohomology. The toric divisor determines a
|
|
1485
|
+
(polyhedral) chamber decomposition of `M_\RR`, see Section
|
|
1486
|
+
9.1 and Figure 4 of [CLS2011]_. The cohomology vanishes on the
|
|
1487
|
+
non-compact chambers. Hence, the convex hull of the vertices
|
|
1488
|
+
of the chamber decomposition contains all non-vanishing
|
|
1489
|
+
cohomology groups. This is returned by the private method
|
|
1490
|
+
:meth:`_sheaf_cohomology_support`.
|
|
1491
|
+
|
|
1492
|
+
It would be more efficient, but more difficult to implement,
|
|
1493
|
+
to keep track of all of the individual chambers. We leave
|
|
1494
|
+
this for future work.
|
|
1495
|
+
|
|
1496
|
+
* For each point `m\in M`, the weight-`m` part of the
|
|
1497
|
+
cohomology can be rewritten as the cohomology of a
|
|
1498
|
+
simplicial complex, see Exercise 9.1.10 of [CLS2011]_,
|
|
1499
|
+
[Per2007]_. This is returned by the private method
|
|
1500
|
+
:meth:`_sheaf_complex`.
|
|
1501
|
+
|
|
1502
|
+
The simplicial complex is the same for all points in a
|
|
1503
|
+
chamber, but we currently do not make use of this and
|
|
1504
|
+
compute each point `m\in M` separately.
|
|
1505
|
+
|
|
1506
|
+
* Finally, the cohomology (over `\QQ`) of this simplicial
|
|
1507
|
+
complex is computed in the private method
|
|
1508
|
+
:meth:`_sheaf_cohomology`. Summing over the supporting
|
|
1509
|
+
points `m\in M` yields the cohomology of the sheaf`.
|
|
1510
|
+
|
|
1511
|
+
EXAMPLES:
|
|
1512
|
+
|
|
1513
|
+
Example 9.1.7 of Cox, Little, Schenck: "Toric Varieties" [CLS2011]_::
|
|
1514
|
+
|
|
1515
|
+
sage: F = Fan(cones=[(0,1), (1,2), (2,3), (3,4), (4,5), (5,0)],
|
|
1516
|
+
....: rays=[(1,0), (1,1), (0,1), (-1,0), (-1,-1), (0,-1)])
|
|
1517
|
+
sage: dP6 = ToricVariety(F)
|
|
1518
|
+
sage: D3 = dP6.divisor(2)
|
|
1519
|
+
sage: D5 = dP6.divisor(4)
|
|
1520
|
+
sage: D6 = dP6.divisor(5)
|
|
1521
|
+
sage: D = -D3 + 2*D5 - D6
|
|
1522
|
+
sage: D.cohomology()
|
|
1523
|
+
{0: Vector space of dimension 0 over Rational Field,
|
|
1524
|
+
1: Vector space of dimension 4 over Rational Field,
|
|
1525
|
+
2: Vector space of dimension 0 over Rational Field}
|
|
1526
|
+
sage: D.cohomology(deg=1)
|
|
1527
|
+
Vector space of dimension 4 over Rational Field
|
|
1528
|
+
sage: M = F.dual_lattice()
|
|
1529
|
+
sage: D.cohomology( M(0,0) )
|
|
1530
|
+
{0: Vector space of dimension 0 over Rational Field,
|
|
1531
|
+
1: Vector space of dimension 1 over Rational Field,
|
|
1532
|
+
2: Vector space of dimension 0 over Rational Field}
|
|
1533
|
+
sage: D.cohomology( weight=M(0,0), deg=1 )
|
|
1534
|
+
Vector space of dimension 1 over Rational Field
|
|
1535
|
+
sage: dP6.integrate(D.ch() * dP6.Td()) # needs sage.libs.singular
|
|
1536
|
+
-4
|
|
1537
|
+
|
|
1538
|
+
Note the different output options::
|
|
1539
|
+
|
|
1540
|
+
sage: D.cohomology()
|
|
1541
|
+
{0: Vector space of dimension 0 over Rational Field,
|
|
1542
|
+
1: Vector space of dimension 4 over Rational Field,
|
|
1543
|
+
2: Vector space of dimension 0 over Rational Field}
|
|
1544
|
+
sage: D.cohomology(dim=True)
|
|
1545
|
+
(0, 4, 0)
|
|
1546
|
+
sage: D.cohomology(weight=M(0,0))
|
|
1547
|
+
{0: Vector space of dimension 0 over Rational Field,
|
|
1548
|
+
1: Vector space of dimension 1 over Rational Field,
|
|
1549
|
+
2: Vector space of dimension 0 over Rational Field}
|
|
1550
|
+
sage: D.cohomology(weight=M(0,0), dim=True)
|
|
1551
|
+
(0, 1, 0)
|
|
1552
|
+
sage: D.cohomology(deg=1)
|
|
1553
|
+
Vector space of dimension 4 over Rational Field
|
|
1554
|
+
sage: D.cohomology(deg=1, dim=True)
|
|
1555
|
+
4
|
|
1556
|
+
sage: D.cohomology(weight=M(0,0), deg=1)
|
|
1557
|
+
Vector space of dimension 1 over Rational Field
|
|
1558
|
+
sage: D.cohomology(weight=M(0,0), deg=1, dim=True)
|
|
1559
|
+
1
|
|
1560
|
+
|
|
1561
|
+
Here is a Weil (non-Cartier) divisor example::
|
|
1562
|
+
|
|
1563
|
+
sage: K = toric_varieties.Cube_nonpolyhedral().K()
|
|
1564
|
+
sage: K.is_Weil()
|
|
1565
|
+
True
|
|
1566
|
+
sage: K.is_QQ_Cartier()
|
|
1567
|
+
False
|
|
1568
|
+
sage: K.cohomology(dim=True)
|
|
1569
|
+
(0, 0, 0, 1)
|
|
1570
|
+
"""
|
|
1571
|
+
if '_cohomology_vector' in self.__dict__ and weight is None:
|
|
1572
|
+
# cache the cohomology but not the individual weight pieces
|
|
1573
|
+
HH = self._cohomology_vector
|
|
1574
|
+
else:
|
|
1575
|
+
X = self.parent().scheme()
|
|
1576
|
+
M = X.fan().dual_lattice()
|
|
1577
|
+
support = self._sheaf_cohomology_support()
|
|
1578
|
+
if weight is None:
|
|
1579
|
+
m_list = [M(p) for p in support.integral_points()]
|
|
1580
|
+
else:
|
|
1581
|
+
m_list = [M(weight)]
|
|
1582
|
+
|
|
1583
|
+
HH = vector(ZZ, [0] * (X.dimension() + 1))
|
|
1584
|
+
for m_point in m_list:
|
|
1585
|
+
cplx = self._sheaf_complex(m_point)
|
|
1586
|
+
HH += self._sheaf_cohomology(cplx)
|
|
1587
|
+
|
|
1588
|
+
if weight is None:
|
|
1589
|
+
self._cohomology_vector = HH
|
|
1590
|
+
|
|
1591
|
+
if dim:
|
|
1592
|
+
if deg is None:
|
|
1593
|
+
return HH
|
|
1594
|
+
else:
|
|
1595
|
+
return HH[deg]
|
|
1596
|
+
else:
|
|
1597
|
+
from sage.modules.free_module import VectorSpace
|
|
1598
|
+
vectorspaces = {k: VectorSpace(self.scheme().base_ring(), HH[k])
|
|
1599
|
+
for k in range(len(HH))}
|
|
1600
|
+
if deg is None:
|
|
1601
|
+
return vectorspaces
|
|
1602
|
+
else:
|
|
1603
|
+
return vectorspaces[deg]
|
|
1604
|
+
|
|
1605
|
+
def cohomology_support(self):
|
|
1606
|
+
r"""
|
|
1607
|
+
Return the weights for which the cohomology groups do not vanish.
|
|
1608
|
+
|
|
1609
|
+
OUTPUT:
|
|
1610
|
+
|
|
1611
|
+
A tuple of dual lattice points. ``self.cohomology(weight=m)``
|
|
1612
|
+
does not vanish if and only if ``m`` is in the output.
|
|
1613
|
+
|
|
1614
|
+
.. NOTE::
|
|
1615
|
+
|
|
1616
|
+
This method is provided for educational purposes and it is
|
|
1617
|
+
not an efficient way of computing the cohomology groups.
|
|
1618
|
+
|
|
1619
|
+
EXAMPLES::
|
|
1620
|
+
|
|
1621
|
+
sage: F = Fan(cones=[(0,1), (1,2), (2,3), (3,4), (4,5), (5,0)],
|
|
1622
|
+
....: rays=[(1,0), (1,1), (0,1), (-1,0), (-1,-1), (0,-1)])
|
|
1623
|
+
sage: dP6 = ToricVariety(F)
|
|
1624
|
+
sage: D3 = dP6.divisor(2)
|
|
1625
|
+
sage: D5 = dP6.divisor(4)
|
|
1626
|
+
sage: D6 = dP6.divisor(5)
|
|
1627
|
+
sage: D = -D3 + 2*D5 - D6
|
|
1628
|
+
sage: D.cohomology_support()
|
|
1629
|
+
(M(0, 0), M(1, 0), M(2, 0), M(1, 1))
|
|
1630
|
+
"""
|
|
1631
|
+
X = self.parent().scheme()
|
|
1632
|
+
M = X.fan().dual_lattice()
|
|
1633
|
+
support_hull = self._sheaf_cohomology_support()
|
|
1634
|
+
support_hull = [M(p) for p in support_hull.integral_points()]
|
|
1635
|
+
support = []
|
|
1636
|
+
for m in support_hull:
|
|
1637
|
+
cplx = self._sheaf_complex(m)
|
|
1638
|
+
HH = self._sheaf_cohomology(cplx)
|
|
1639
|
+
if sum(HH) > 0:
|
|
1640
|
+
support.append(m)
|
|
1641
|
+
return tuple(support)
|
|
1642
|
+
|
|
1643
|
+
|
|
1644
|
+
class ToricDivisorGroup(DivisorGroup_generic):
|
|
1645
|
+
r"""
|
|
1646
|
+
The group of (`\QQ`-T-Weil) divisors on a toric variety.
|
|
1647
|
+
|
|
1648
|
+
EXAMPLES::
|
|
1649
|
+
|
|
1650
|
+
sage: P2 = toric_varieties.P2()
|
|
1651
|
+
sage: P2.toric_divisor_group()
|
|
1652
|
+
Group of toric ZZ-Weil divisors
|
|
1653
|
+
on 2-d CPR-Fano toric variety covered by 3 affine patches
|
|
1654
|
+
"""
|
|
1655
|
+
|
|
1656
|
+
def __init__(self, toric_variety, base_ring):
|
|
1657
|
+
r"""
|
|
1658
|
+
Construct an instance of :class:`ToricDivisorGroup`.
|
|
1659
|
+
|
|
1660
|
+
INPUT:
|
|
1661
|
+
|
|
1662
|
+
- ``toric_variety`` -- a
|
|
1663
|
+
:class:`toric variety
|
|
1664
|
+
<sage.schemes.toric.variety.ToricVariety_field>``
|
|
1665
|
+
|
|
1666
|
+
- ``base_ring`` -- the coefficient ring of this divisor group,
|
|
1667
|
+
usually `\ZZ` (default) or `\QQ`
|
|
1668
|
+
|
|
1669
|
+
Implementation note: :meth:`__classcall__` sets the default
|
|
1670
|
+
value for ``base_ring``.
|
|
1671
|
+
|
|
1672
|
+
OUTPUT: divisor group of the toric variety
|
|
1673
|
+
|
|
1674
|
+
EXAMPLES::
|
|
1675
|
+
|
|
1676
|
+
sage: P2 = toric_varieties.P2()
|
|
1677
|
+
sage: from sage.schemes.toric.divisor import ToricDivisorGroup
|
|
1678
|
+
sage: ToricDivisorGroup(P2, base_ring=ZZ)
|
|
1679
|
+
Group of toric ZZ-Weil divisors
|
|
1680
|
+
on 2-d CPR-Fano toric variety covered by 3 affine patches
|
|
1681
|
+
|
|
1682
|
+
Note that :class:`UniqueRepresentation` correctly distinguishes the
|
|
1683
|
+
parent classes even if the schemes are the same::
|
|
1684
|
+
|
|
1685
|
+
sage: from sage.schemes.generic.divisor_group import DivisorGroup
|
|
1686
|
+
sage: DivisorGroup(P2, ZZ) is ToricDivisorGroup(P2, ZZ)
|
|
1687
|
+
False
|
|
1688
|
+
"""
|
|
1689
|
+
assert isinstance(toric_variety, ToricVariety_field), str(toric_variety) + ' is not a toric variety!'
|
|
1690
|
+
super().__init__(toric_variety, base_ring)
|
|
1691
|
+
|
|
1692
|
+
def _latex_(self):
|
|
1693
|
+
r"""
|
|
1694
|
+
Return a LaTeX representation of ``self``.
|
|
1695
|
+
|
|
1696
|
+
OUTPUT: string
|
|
1697
|
+
|
|
1698
|
+
TESTS::
|
|
1699
|
+
|
|
1700
|
+
sage: print(toric_varieties.P2().toric_divisor_group()._latex_()) # needs polytopes_db
|
|
1701
|
+
\mathrm{Div_T}\left(\mathbb{P}_{\Delta^{2}_{15}}, \Bold{Z}\right)
|
|
1702
|
+
"""
|
|
1703
|
+
return (r"\mathrm{Div_T}\left(%s, %s\right)"
|
|
1704
|
+
% (latex(self.scheme()), latex(self.base_ring())))
|
|
1705
|
+
|
|
1706
|
+
def _repr_(self):
|
|
1707
|
+
"""
|
|
1708
|
+
Return a string representation of the toric divisor group.
|
|
1709
|
+
|
|
1710
|
+
OUTPUT: string
|
|
1711
|
+
|
|
1712
|
+
EXAMPLES::
|
|
1713
|
+
|
|
1714
|
+
sage: toric_varieties.P2().toric_divisor_group()._repr_()
|
|
1715
|
+
'Group of toric ZZ-Weil divisors
|
|
1716
|
+
on 2-d CPR-Fano toric variety covered by 3 affine patches'
|
|
1717
|
+
"""
|
|
1718
|
+
ring = self.base_ring()
|
|
1719
|
+
if ring == ZZ:
|
|
1720
|
+
base_ring_str = 'ZZ'
|
|
1721
|
+
elif ring == QQ:
|
|
1722
|
+
base_ring_str = 'QQ'
|
|
1723
|
+
else:
|
|
1724
|
+
base_ring_str = '(' + str(ring) + ')'
|
|
1725
|
+
return 'Group of toric ' + base_ring_str + '-Weil divisors on ' + str(self.scheme())
|
|
1726
|
+
|
|
1727
|
+
def ngens(self):
|
|
1728
|
+
r"""
|
|
1729
|
+
Return the number of generators.
|
|
1730
|
+
|
|
1731
|
+
OUTPUT:
|
|
1732
|
+
|
|
1733
|
+
The number of generators of ``self``, which equals the number of
|
|
1734
|
+
rays in the fan of the toric variety.
|
|
1735
|
+
|
|
1736
|
+
EXAMPLES::
|
|
1737
|
+
|
|
1738
|
+
sage: P2 = toric_varieties.P2()
|
|
1739
|
+
sage: TDiv = P2.toric_divisor_group()
|
|
1740
|
+
sage: TDiv.ngens()
|
|
1741
|
+
3
|
|
1742
|
+
"""
|
|
1743
|
+
return self.scheme().fan().nrays()
|
|
1744
|
+
|
|
1745
|
+
@cached_method
|
|
1746
|
+
def gens(self) -> tuple:
|
|
1747
|
+
r"""
|
|
1748
|
+
Return the generators of the divisor group.
|
|
1749
|
+
|
|
1750
|
+
EXAMPLES::
|
|
1751
|
+
|
|
1752
|
+
sage: P2 = toric_varieties.P2()
|
|
1753
|
+
sage: TDiv = P2.toric_divisor_group()
|
|
1754
|
+
sage: TDiv.gens()
|
|
1755
|
+
(V(x), V(y), V(z))
|
|
1756
|
+
"""
|
|
1757
|
+
one = self.base_ring().one()
|
|
1758
|
+
return tuple(ToricDivisor_generic([(one, c)], self)
|
|
1759
|
+
for c in self.scheme().gens())
|
|
1760
|
+
|
|
1761
|
+
def gen(self, i):
|
|
1762
|
+
r"""
|
|
1763
|
+
Return the ``i``-th generator of the divisor group.
|
|
1764
|
+
|
|
1765
|
+
INPUT:
|
|
1766
|
+
|
|
1767
|
+
- ``i`` -- integer
|
|
1768
|
+
|
|
1769
|
+
OUTPUT:
|
|
1770
|
+
|
|
1771
|
+
The divisor `z_i=0`, where `z_i` is the `i`-th homogeneous
|
|
1772
|
+
coordinate.
|
|
1773
|
+
|
|
1774
|
+
EXAMPLES::
|
|
1775
|
+
|
|
1776
|
+
sage: P2 = toric_varieties.P2()
|
|
1777
|
+
sage: TDiv = P2.toric_divisor_group()
|
|
1778
|
+
sage: TDiv.gen(2)
|
|
1779
|
+
V(z)
|
|
1780
|
+
"""
|
|
1781
|
+
return self.gens()[i]
|
|
1782
|
+
|
|
1783
|
+
def _element_constructor_(self, x, check=True, reduce=True):
|
|
1784
|
+
r"""
|
|
1785
|
+
Construct a :class:`ToricDivisor_generic`.
|
|
1786
|
+
|
|
1787
|
+
INPUT:
|
|
1788
|
+
|
|
1789
|
+
- ``x`` -- something defining a toric divisor, see
|
|
1790
|
+
:func:`ToricDivisor`
|
|
1791
|
+
|
|
1792
|
+
- ``check``, ``reduce`` -- boolean; See
|
|
1793
|
+
:meth:`ToricDivisor_generic.__init__`
|
|
1794
|
+
|
|
1795
|
+
EXAMPLES::
|
|
1796
|
+
|
|
1797
|
+
sage: P2 = toric_varieties.P2()
|
|
1798
|
+
sage: TDiv = P2.toric_divisor_group()
|
|
1799
|
+
sage: TDiv._element_constructor_([ (1,P2.gen(2)) ])
|
|
1800
|
+
V(z)
|
|
1801
|
+
sage: TDiv( P2.fan(1)[0] )
|
|
1802
|
+
V(x)
|
|
1803
|
+
|
|
1804
|
+
TESTS:
|
|
1805
|
+
|
|
1806
|
+
Check for :issue:`12812`::
|
|
1807
|
+
|
|
1808
|
+
sage: TDiv(0)
|
|
1809
|
+
0
|
|
1810
|
+
sage: TDiv(1)
|
|
1811
|
+
Traceback (most recent call last):
|
|
1812
|
+
...
|
|
1813
|
+
TypeError: 'sage.rings.integer.Integer' object is not iterable
|
|
1814
|
+
sage: TDiv(TDiv.gen(0), check=True)
|
|
1815
|
+
V(x)
|
|
1816
|
+
"""
|
|
1817
|
+
if isinstance(x, ToricDivisor_generic):
|
|
1818
|
+
if x.parent() is self:
|
|
1819
|
+
return x
|
|
1820
|
+
else:
|
|
1821
|
+
x = x._data
|
|
1822
|
+
return ToricDivisor(self.scheme(), x, self.base_ring(), check, reduce)
|
|
1823
|
+
|
|
1824
|
+
def base_extend(self, R):
|
|
1825
|
+
"""
|
|
1826
|
+
Extend the scalars of ``self`` to ``R``.
|
|
1827
|
+
|
|
1828
|
+
INPUT:
|
|
1829
|
+
|
|
1830
|
+
- ``R`` -- ring
|
|
1831
|
+
|
|
1832
|
+
OUTPUT: toric divisor group
|
|
1833
|
+
|
|
1834
|
+
EXAMPLES::
|
|
1835
|
+
|
|
1836
|
+
sage: P2 = toric_varieties.P2()
|
|
1837
|
+
sage: DivZZ = P2.toric_divisor_group()
|
|
1838
|
+
sage: DivQQ = P2.toric_divisor_group(base_ring=QQ)
|
|
1839
|
+
sage: DivZZ.base_extend(QQ) is DivQQ
|
|
1840
|
+
True
|
|
1841
|
+
"""
|
|
1842
|
+
# This check prevents extension to cohomology rings via coercion
|
|
1843
|
+
if isinstance(R, CohomologyRing):
|
|
1844
|
+
raise TypeError('coefficient ring cannot be a cohomology ring')
|
|
1845
|
+
if self.base_ring().has_coerce_map_from(R):
|
|
1846
|
+
return self
|
|
1847
|
+
if R.has_coerce_map_from(self.base_ring()):
|
|
1848
|
+
return ToricDivisorGroup(self.scheme(), base_ring=R)
|
|
1849
|
+
raise ValueError(f"the base of {self} cannot be extended to {R}")
|
|
1850
|
+
|
|
1851
|
+
Element = ToricDivisor_generic
|
|
1852
|
+
|
|
1853
|
+
|
|
1854
|
+
class ToricRationalDivisorClassGroup(FreeModule_ambient_field, UniqueRepresentation):
|
|
1855
|
+
r"""
|
|
1856
|
+
The rational divisor class group of a toric variety.
|
|
1857
|
+
|
|
1858
|
+
The **T-Weil divisor class group** `\mathop{Cl}(X)` of a toric
|
|
1859
|
+
variety `X` is a finitely generated abelian group and can contain
|
|
1860
|
+
torsion. Its rank equals the number of rays in the fan of `X`
|
|
1861
|
+
minus the dimension of `X`.
|
|
1862
|
+
|
|
1863
|
+
The **rational divisor class group** is `\mathop{Cl}(X)
|
|
1864
|
+
\otimes_\ZZ \QQ` and never includes torsion. If `X` is *smooth*,
|
|
1865
|
+
this equals the **Picard group** `\mathop{\mathrm{Pic}}(X)`, whose
|
|
1866
|
+
elements are the isomorphism classes of line bundles on `X`. The
|
|
1867
|
+
group law (which we write as addition) is the tensor product of
|
|
1868
|
+
the line bundles. The Picard group of a toric variety is always
|
|
1869
|
+
torsion-free.
|
|
1870
|
+
|
|
1871
|
+
.. WARNING::
|
|
1872
|
+
|
|
1873
|
+
Do not instantiate this class yourself. Use
|
|
1874
|
+
:meth:`~sage.schemes.toric.variety.ToricVariety_field.rational_class_group`
|
|
1875
|
+
method of :class:`toric varieties
|
|
1876
|
+
<sage.schemes.toric.variety.ToricVariety_field>` if you need
|
|
1877
|
+
the divisor class group. Or you can obtain it as the parent of any
|
|
1878
|
+
divisor class constructed, for example, via
|
|
1879
|
+
:meth:`ToricDivisor_generic.divisor_class`.
|
|
1880
|
+
|
|
1881
|
+
INPUT:
|
|
1882
|
+
|
|
1883
|
+
- ``toric_variety`` -- :class:`toric variety
|
|
1884
|
+
<sage.schemes.toric.variety.ToricVariety_field`
|
|
1885
|
+
|
|
1886
|
+
OUTPUT: rational divisor class group of a toric variety
|
|
1887
|
+
|
|
1888
|
+
EXAMPLES::
|
|
1889
|
+
|
|
1890
|
+
sage: P2 = toric_varieties.P2()
|
|
1891
|
+
sage: P2.rational_class_group()
|
|
1892
|
+
The toric rational divisor class group of a 2-d CPR-Fano
|
|
1893
|
+
toric variety covered by 3 affine patches
|
|
1894
|
+
sage: D = P2.divisor(0); D
|
|
1895
|
+
V(x)
|
|
1896
|
+
sage: Dclass = D.divisor_class(); Dclass
|
|
1897
|
+
Divisor class [1]
|
|
1898
|
+
sage: Dclass.lift()
|
|
1899
|
+
V(y)
|
|
1900
|
+
sage: Dclass.parent()
|
|
1901
|
+
The toric rational divisor class group of a 2-d CPR-Fano
|
|
1902
|
+
toric variety covered by 3 affine patches
|
|
1903
|
+
"""
|
|
1904
|
+
|
|
1905
|
+
def __init__(self, toric_variety):
|
|
1906
|
+
r"""
|
|
1907
|
+
Construct the toric rational divisor class group.
|
|
1908
|
+
|
|
1909
|
+
EXAMPLES::
|
|
1910
|
+
|
|
1911
|
+
sage: P2 = toric_varieties.P2()
|
|
1912
|
+
sage: from sage.schemes.toric.divisor import ToricRationalDivisorClassGroup
|
|
1913
|
+
sage: ToricRationalDivisorClassGroup(P2)
|
|
1914
|
+
The toric rational divisor class group of a 2-d CPR-Fano
|
|
1915
|
+
toric variety covered by 3 affine patches
|
|
1916
|
+
|
|
1917
|
+
TESTS:
|
|
1918
|
+
|
|
1919
|
+
Make sure we lift integral classes to integral divisors::
|
|
1920
|
+
|
|
1921
|
+
sage: rays = [(1, 0, 0), (-1, 0, 0), (0, 1, 0), (0, 0, 1), (2, -1, -1)]
|
|
1922
|
+
sage: cones = [(0, 2, 3), (0, 2, 4), (0, 3, 4), (1, 2, 3), (1, 2, 4), (1, 3, 4)]
|
|
1923
|
+
sage: X = ToricVariety(Fan(cones=cones, rays=rays))
|
|
1924
|
+
sage: Cl = X.rational_class_group()
|
|
1925
|
+
sage: Cl._projection_matrix
|
|
1926
|
+
[1 1 0 0 0]
|
|
1927
|
+
[0 2 1 1 1]
|
|
1928
|
+
sage: Cl._lift_matrix
|
|
1929
|
+
[ 0 0]
|
|
1930
|
+
[ 1 0]
|
|
1931
|
+
[ 0 0]
|
|
1932
|
+
[-2 1]
|
|
1933
|
+
[ 0 0]
|
|
1934
|
+
sage: Cl._lift_matrix.base_ring()
|
|
1935
|
+
Integer Ring
|
|
1936
|
+
"""
|
|
1937
|
+
self._variety = toric_variety
|
|
1938
|
+
fan = toric_variety.fan()
|
|
1939
|
+
nrays = fan.nrays()
|
|
1940
|
+
rk = nrays - fan.lattice_dim()
|
|
1941
|
+
super().__init__(base_field=QQ, dimension=rk, sparse=False)
|
|
1942
|
+
gale = fan.Gale_transform()
|
|
1943
|
+
self._projection_matrix = gale.matrix_from_columns(range(nrays))
|
|
1944
|
+
D, U, V = self._projection_matrix.transpose().smith_form()
|
|
1945
|
+
assert all(D[i, i] == 1 for i in range(D.ncols())), \
|
|
1946
|
+
'This is a property of the Gale transform.'
|
|
1947
|
+
self._lift_matrix = (V * D.transpose() * U).transpose()
|
|
1948
|
+
|
|
1949
|
+
def _repr_(self):
|
|
1950
|
+
r"""
|
|
1951
|
+
Return a string representation of ``self``.
|
|
1952
|
+
|
|
1953
|
+
OUTPUT: string
|
|
1954
|
+
|
|
1955
|
+
EXAMPLES::
|
|
1956
|
+
|
|
1957
|
+
sage: P2 = toric_varieties.P2()
|
|
1958
|
+
sage: from sage.schemes.toric.divisor import ToricRationalDivisorClassGroup
|
|
1959
|
+
sage: ToricRationalDivisorClassGroup(P2)._repr_()
|
|
1960
|
+
'The toric rational divisor class group of a 2-d CPR-Fano toric variety covered by 3 affine patches'
|
|
1961
|
+
"""
|
|
1962
|
+
return 'The toric rational divisor class group of a %s' % self._variety
|
|
1963
|
+
|
|
1964
|
+
def _latex_(self):
|
|
1965
|
+
r"""
|
|
1966
|
+
Return a LaTeX representation of ``self``.
|
|
1967
|
+
|
|
1968
|
+
OUTPUT: string
|
|
1969
|
+
|
|
1970
|
+
EXAMPLES::
|
|
1971
|
+
|
|
1972
|
+
sage: P2 = toric_varieties.P2()
|
|
1973
|
+
sage: from sage.schemes.toric.divisor import ToricRationalDivisorClassGroup
|
|
1974
|
+
sage: print(ToricRationalDivisorClassGroup(P2)._latex_()) # needs polytopes_db
|
|
1975
|
+
\mathop{Cl}_{\QQ}\left(\mathbb{P}_{\Delta^{2}_{15}}\right)
|
|
1976
|
+
"""
|
|
1977
|
+
return '\\mathop{Cl}_{\\QQ}\\left(' + self._variety._latex_() + '\\right)'
|
|
1978
|
+
|
|
1979
|
+
def _element_constructor_(self, x):
|
|
1980
|
+
r"""
|
|
1981
|
+
Construct a :class:`ToricRationalDivisorClass`.
|
|
1982
|
+
|
|
1983
|
+
INPUT:
|
|
1984
|
+
|
|
1985
|
+
- ``x`` -- one of the following:
|
|
1986
|
+
* toric divisor;
|
|
1987
|
+
* vector;
|
|
1988
|
+
* list.
|
|
1989
|
+
|
|
1990
|
+
OUTPUT: :class:`ToricRationalDivisorClass`
|
|
1991
|
+
|
|
1992
|
+
EXAMPLES::
|
|
1993
|
+
|
|
1994
|
+
sage: dP6 = toric_varieties.dP6()
|
|
1995
|
+
sage: Cl = dP6.rational_class_group()
|
|
1996
|
+
sage: D = dP6.divisor(2)
|
|
1997
|
+
sage: Cl._element_constructor_(D)
|
|
1998
|
+
Divisor class [0, 0, 1, 0]
|
|
1999
|
+
sage: Cl(D)
|
|
2000
|
+
Divisor class [0, 0, 1, 0]
|
|
2001
|
+
"""
|
|
2002
|
+
if isinstance(x, ToricDivisor_generic):
|
|
2003
|
+
x = self._projection_matrix * vector(x)
|
|
2004
|
+
if isinstance(x, Vector):
|
|
2005
|
+
x = list(x)
|
|
2006
|
+
return self.element_class(self, x)
|
|
2007
|
+
|
|
2008
|
+
Element = ToricRationalDivisorClass
|
|
2009
|
+
|
|
2010
|
+
|
|
2011
|
+
class ToricRationalDivisorClassGroup_basis_lattice(FreeModule_ambient_pid):
|
|
2012
|
+
r"""
|
|
2013
|
+
Construct the basis lattice of the ``group``.
|
|
2014
|
+
|
|
2015
|
+
INPUT:
|
|
2016
|
+
|
|
2017
|
+
- ``group`` -- :class:`toric rational divisor class group
|
|
2018
|
+
<ToricRationalDivisorClassGroup>`
|
|
2019
|
+
|
|
2020
|
+
OUTPUT: the basis lattice of ``group``
|
|
2021
|
+
|
|
2022
|
+
EXAMPLES::
|
|
2023
|
+
|
|
2024
|
+
sage: P1xP1 = toric_varieties.P1xP1()
|
|
2025
|
+
sage: L = P1xP1.Kaehler_cone().lattice()
|
|
2026
|
+
sage: L
|
|
2027
|
+
Basis lattice of The toric rational divisor class group of a
|
|
2028
|
+
2-d CPR-Fano toric variety covered by 4 affine patches
|
|
2029
|
+
sage: L.basis()
|
|
2030
|
+
[Divisor class [1, 0], Divisor class [0, 1]]
|
|
2031
|
+
"""
|
|
2032
|
+
|
|
2033
|
+
def __init__(self, group):
|
|
2034
|
+
r"""
|
|
2035
|
+
See :class:`ToricRationalDivisorClassGroup_basis_lattice` for
|
|
2036
|
+
documentation.
|
|
2037
|
+
|
|
2038
|
+
TESTS::
|
|
2039
|
+
|
|
2040
|
+
sage: P1xP1 = toric_varieties.P1xP1()
|
|
2041
|
+
sage: L = P1xP1.Kaehler_cone().lattice()
|
|
2042
|
+
sage: TestSuite(L).run()
|
|
2043
|
+
"""
|
|
2044
|
+
assert isinstance(group, ToricRationalDivisorClassGroup)
|
|
2045
|
+
self._group = group
|
|
2046
|
+
self._variety = group._variety
|
|
2047
|
+
self._lift_matrix = group._lift_matrix
|
|
2048
|
+
super().__init__(ZZ, group.dimension(), coordinate_ring=QQ)
|
|
2049
|
+
|
|
2050
|
+
def _repr_(self):
|
|
2051
|
+
r"""
|
|
2052
|
+
Return a string representation of ``self``.
|
|
2053
|
+
|
|
2054
|
+
OUTPUT: string
|
|
2055
|
+
|
|
2056
|
+
TESTS::
|
|
2057
|
+
|
|
2058
|
+
sage: P1xP1 = toric_varieties.P1xP1()
|
|
2059
|
+
sage: L = P1xP1.Kaehler_cone().lattice()
|
|
2060
|
+
sage: print(L._repr_())
|
|
2061
|
+
Basis lattice of The toric rational divisor class group of a
|
|
2062
|
+
2-d CPR-Fano toric variety covered by 4 affine patches
|
|
2063
|
+
"""
|
|
2064
|
+
return "Basis lattice of {}".format(self._group)
|
|
2065
|
+
|
|
2066
|
+
def _latex_(self):
|
|
2067
|
+
r"""
|
|
2068
|
+
Return a LaTeX representation of ``self``.
|
|
2069
|
+
|
|
2070
|
+
OUTPUT: string
|
|
2071
|
+
|
|
2072
|
+
TESTS::
|
|
2073
|
+
|
|
2074
|
+
sage: P1xP1 = toric_varieties.P1xP1()
|
|
2075
|
+
sage: L = P1xP1.Kaehler_cone().lattice()
|
|
2076
|
+
sage: print(L._latex_()) # needs polytopes_db
|
|
2077
|
+
\text{Basis lattice of }
|
|
2078
|
+
\mathop{Cl}_{\QQ}\left(\mathbb{P}_{\Delta^{2}_{14}}\right)
|
|
2079
|
+
"""
|
|
2080
|
+
return r"\text{{Basis lattice of }} {}".format(latex(self._group))
|
|
2081
|
+
|
|
2082
|
+
Element = ToricRationalDivisorClass
|