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