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