Introduction to Toric Geometry
Chiara Meroni ~ March 4, 2022
This notebook provides auxiliary code to the text “Introduction to Toric Geometry” by Simon Telen http://arxiv.org/abs/2203.01690.
For installation instructions and documentation see https://oscar.computeralgebra.de.
The examples are numbered as in the text.
[1]:
using Pkg
Pkg.add("Oscar")
using Oscar
----- ----- ----- - -----
| | | | | | | | | |
| | | | | | | |
| | ----- | | | |-----
| | | | |-----| | |
| | | | | | | | | |
----- ----- ----- - - - -
...combining (and extending) ANTIC, GAP, Polymake and Singular
Version 0.8.1 ...
... which comes with absolutely no warranty whatsoever
Type: '?Oscar' for more information
(c) 2019-2022 by The Oscar Development Team
Updating registry at `~/.julia/registries/General.toml`
Resolving package versions...
No Changes to `~/Documents/git/mathrepo_website/mathrepo/source/ToricGeometry/Project.toml`
No Changes to `~/Documents/git/mathrepo_website/mathrepo/source/ToricGeometry/Manifest.toml`
Section 2
Example* 2.24
We have the following matrix
[2]:
A = [2 2 1 0 0 1 1; 1 0 0 1 2 2 1; 0 1 2 2 1 0 1]
[2]:
3×7 Matrix{Int64}:
2 2 1 0 0 1 1
1 0 0 1 2 2 1
0 1 2 2 1 0 1
To compute the binomial ideal of the associated toric variety we do the following:
[3]:
I = toric_ideal(transpose(A))
[3]:
Example* 2.40
We show here how to work with cones. We first define a cone \(\sigma\).
[4]:
σ = positive_hull([0 1;1 2;2 1])
[4]:
A polyhedral cone in ambient dimension 2
We can then compute its dual cone, its facets, its rays, its dimension.
[5]:
σ_dual = polarize(σ)
facets_σ = facets(σ)
rays_σ = rays(σ)
dimσ = dim(σ)
[5]:
2
Example* 2.47
We consider the cone \(\sigma\) from Example* 2.40 and compute the embedding of the associated normal affine toric variety \(U_\sigma\). We do it by computing the Hilbert basis of the dual cone σ_dual
.
[6]:
H = hilbert_basis(σ_dual)
[6]:
3-element SubObjectIterator{PointVector{Polymake.Integer}}:
[1, 0]
[-1, 2]
[0, 1]
From the Hilbert basis we can then compute for instance the toric ideal of \(U_\sigma\).
[7]:
I = toric_ideal(H)
[7]:
Otherwise, to get the toric variety \(U_\sigma\) as an abstract variety, for then studying its dimension or smoothness, we can use the following command.
[8]:
U_σ = AffineNormalToricVariety(σ)
[8]:
A normal, affine toric variety
And we can then check some properties.
[9]:
dim(U_σ)
issmooth(U_σ)
[9]:
false
Example* 2.58
We now consider a different cone \(\sigma\subset\mathbb{R}^3\).
[10]:
σ = positive_hull([1 2 3; 2 1 3; 3 2 1; 2 3 1; 1 3 2; 3 1 2])
σ_dual = polarize(σ)
[10]:
A polyhedral cone in ambient dimension 3
What is the smallest integer \(p\) such that the toric variety \(U_\sigma\) can be embedded in \(\mathbb{C}^p\)? Such number can be characterized as the number of generators of a Hilbert basis associated to \(\sigma^\vee\).
[11]:
σ_hilbert = hilbert_basis(σ_dual)
[11]:
15-element SubObjectIterator{PointVector{Polymake.Integer}}:
[1, 0, 0]
[-1, 5, -1]
[-1, 3, 0]
[5, -1, -1]
[0, 1, 0]
[1, 1, -1]
[0, 3, -1]
[-1, 1, 1]
[0, 0, 1]
[-1, -1, 5]
[1, -1, 1]
[3, -1, 0]
[3, 0, -1]
[0, -1, 3]
[-1, 0, 3]
The answer is therefore \(p=15\). We obtain the associated toric ideal in @time toric_ideal(Y)
seconds:
[12]:
U_σ = AffineNormalToricVariety(σ)
[12]:
A normal, affine toric variety
[13]:
dim(U_σ)
[13]:
3
[15]:
@time I = toric_ideal(U_σ)
0.002283 seconds (15.01 k allocations: 404.906 KiB)
[15]:
[16]:
gens(I)
[16]:
77-element Vector{fmpq_mpoly}:
-x1^4 + x4*x8
-x1^3 + x9*x13
-x1^3 + x5*x12
-x1^3*x6^2 + x4*x7
-x1^3*x9*x11 + x4*x15
-x1^3*x11^2 + x4*x14
-x1^3*x11*x14 + x4*x10
-x1^3*x5*x6 + x3*x4
-x1^3*x6*x7 + x2*x4
-x1^2*x5*x6 + x7*x12
-x1^2*x5 + x8*x13
-x1^2*x8*x11 + x13*x15
-x1^2*x9*x11 + x13*x14
⋮
-x3*x9 + x5^2*x8
-x4*x6 + x13^2
-x4*x11 + x12^2
-x5^2 + x6*x8
-x5*x10 + x8*x9*x14
-x5*x15 + x8^2*x11
-x8*x10 + x15^2
-x8*x14 + x9*x15
-x8*x11 + x9^2
-x9*x10 + x14*x15
-x9*x14 + x11*x15
-x10*x11 + x14^2
Section 3
Example* 3.25
Consider a polytope \(P\).
[17]:
P = convex_hull([0 0; 1 0; 0 1; 2 1; 1 2])
[17]:
A polyhedron in ambient dimension 2
[18]:
dim(P), length(vertices(P)), length(facets(P))
[18]:
(2, 5, 5)
We want to compute its Ehrhart polynomial.
[19]:
E_P = ehrhart_polynomial(P)
[19]:
Example* 3.29
This example regards Kushnirenko’s Theorem (Theorem 3.1 in the notes). We consider the polytope \(P\subset \mathbb{R}^2\) from the previous example and check that
Here \(X_{\mathscr{A}}\) denotes the toric surface associated to the set \(\mathscr{A}\) whose convex hull is \(P\).
[20]:
A = [0 0; 1 0; 0 1; 2 1; 1 2]
P = convex_hull(A)
[20]:
A polyhedron in ambient dimension 2
[21]:
V = 2*volume(P)
[21]:
5
We use Corollary 3.2 in the notes to verify the statement. The second line in the code below is to avoid ambiguities with the command solve
in Oscar.jl
.
[23]:
using HomotopyContinuation
solve = HomotopyContinuation.solve
[23]:
solve (generic function with 9 methods)
[24]:
@var t[1:2]
monomials = [prod(t.^transpose(A)[:,i]) for i = 1:5]
coeffs = [randn(5) for i = 1:2]
f = [dot(coeffs[i],monomials) for i = 1:2]
[24]:
2-element Vector{Expression}:
0.670834357300711 - 1.84995014545632*t₁ - 0.970451966318485*t₂ + 2.53906268972251*t₂*t₁^2 + 0.24712986535149*t₂^2*t₁
1.33971230052044 - 1.45714877010853*t₁ + 2.76166434414561*t₂ + 0.220622723359913*t₂*t₁^2 - 0.786317734708661*t₂^2*t₁
[25]:
sols = solve(f)
Tracking 5 paths... 100%|███████████████████████████████| Time: 0:00:10
# paths tracked: 5
# non-singular solutions (real): 5 (5)
# singular endpoints (real): 0 (0)
# total solutions (real): 5 (5)
[25]:
Result with 5 solutions
=======================
• 5 paths tracked
• 5 non-singular solutions (5 real)
• random_seed: 0x4a45e277
• start_system: :polyhedral
[26]:
V == nnonsingular(sols)
[26]:
true
Alternatively, we can construct \(X_{\mathscr{A}}\) and compute its toric ideal. This is a projective surface in \(\mathbb{P}^4\).
[27]:
 = hcat(A,ones(5))
I = toric_ideal(Â)
[27]:
In order to compute its degree we intersect it with two random linear spaces and use HomotopyContinuation.jl
to compute the points of intersection.
[28]:
@var x[1:5]
systemA = System([x[3]*x[4]-x[2]*x[5];
x[2]*x[3]^2-x[1]^2*x[5];
x[2]^2*x[3]-x[1]^2*x[4];
x[1]^2*x[4]^2-x[2]^3*x[5];
dot(coeffs[1],x); dot(coeffs[2],x)])
[28]:
System of length 6
5 variables: x₁, x₂, x₃, x₄, x₅
x₄*x₃ - x₅*x₂
x₂*x₃^2 - x₅*x₁^2
x₂^2*x₃ - x₄*x₁^2
x₄^2*x₁^2 - x₅*x₂^3
0.670834357300711*x₁ - 1.84995014545632*x₂ - 0.970451966318485*x₃ + 2.53906268972251*x₄ + 0.24712986535149*x₅
1.33971230052044*x₁ - 1.45714877010853*x₂ + 2.76166434414561*x₃ + 0.220622723359913*x₄ - 0.786317734708661*x₅
[29]:
intersection_pointsA = HomotopyContinuation.solve(systemA)
Tracking 38 paths... 100%|██████████████████████████████| Time: 0:00:03
# paths tracked: 38
# non-singular solutions (real): 5 (0)
# singular endpoints (real): 0 (0)
# total solutions (real): 5 (0)
[29]:
Result with 5 solutions
=======================
• 38 paths tracked
• 5 non-singular solutions (0 real)
• 21 excess solutions
• random_seed: 0x22368dc7
• start_system: :polyhedral
We can see that the number of intersection points coincides with the lattice volume of the polytope.
[30]:
V == nnonsingular(intersection_pointsA)
[30]:
true
What happens if we remove the origin?
Our new polytope \(Q\) does not satisfy the hypotheses of Kushnirenko’s Theorem; indeed, we can check that the statement is not true in this setting.
[31]:
B = [1 0; 0 1; 2 1; 1 2]
Q = convex_hull(B)
[31]:
A polyhedron in ambient dimension 2
[32]:
VV = 2*volume(Q)
[32]:
4
We construct now the projective toric variety associated to \(Q\).
[33]:
B̂ = hcat(B,ones(4))
J = toric_ideal(B̂)
[33]:
[34]:
@var x[1:4]
systemB = System([x[1]*x[4]-x[2]*x[3];
dot(randn(4),x); dot(randn(4),x)])
[34]:
System of length 3
4 variables: x₁, x₂, x₃, x₄
-x₂*x₃ + x₄*x₁
-1.79653649460657*x₁ + 2.66499103944441*x₂ + 0.941303310780985*x₃ + 0.345953420794041*x₄
-1.07124612109659*x₁ - 0.82694720327857*x₂ - 0.0361493797245357*x₃ - 1.1030689331341*x₄
[35]:
intersection_pointsB = HomotopyContinuation.solve(systemB)
[35]:
Result with 2 solutions
=======================
• 2 paths tracked
• 2 non-singular solutions (0 real)
• random_seed: 0x04d14d25
• start_system: :polyhedral
With the following command we check that the volume of \(Q\) does not coincide with the degree of the associated projective toric variety.
[36]:
VV == nnonsingular(intersection_pointsB)
[36]:
false
Example* 3.46
Consider the polytope \(P\) from Example* 3.25. We can compute its normal fan as follows.
[37]:
P = convex_hull([0 0; 1 0; 0 1; 2 1; 1 2])
Σ = normal_fan(P)
[37]:
A polyhedral fan in ambient dimension 2
[38]:
rays(Σ)
[38]:
5-element SubObjectIterator{RayVector{Polymake.Rational}}:
[1, 0]
[0, 1]
[1, -1]
[-1, -1]
[-1, 1]
We can ask whether the normal fan of \(P\) is smooth.
[39]:
issmooth(Σ)
[39]:
false
Example* 3.50
Consider the following polytope \(P\) and compute the associated projective toric variety.
[40]:
P = convex_hull([0 0; 3 -1; 2 2; 1 2])
[40]:
A polyhedron in ambient dimension 2
[41]:
X = NormalToricVariety(P)
[41]:
A normal toric variety
[42]:
A = hcat([vcat(p,1) for p ∈ lattice_points(P)]...)
[42]:
3×8 Matrix{Polymake.Integer}:
0 1 1 1 2 2 2 3
0 0 1 2 0 1 2 -1
1 1 1 1 1 1 1 1
As we saw in previous examples, the Hilbert basis gives an embedding of the toric variety \(X\) in \(\mathbb{C}^8\). Since polygons are normal, \(X\) is projectively normal, and we can actually embed it in \(\mathbb{P}^7\).
[43]:
I = toric_ideal(transpose(A))
[43]:
We can compute the affine open covering of \(X\) associated to the vertices of \(P\).
[44]:
cover = affine_open_covering(X)
[44]:
4-element Vector{AffineNormalToricVariety}:
A normal, affine toric variety
A normal, affine toric variety
A normal, affine toric variety
A normal, affine toric variety
In particular \(U_i\) is the affine chart coming from the vertex \((0,0)\) and \(U_j\) is the one coming from the vertex \((3,-1)\).
[45]:
U_i = cover[1]
U_j = cover[2]
[45]:
A normal, affine toric variety
Example* 3.53
We study in this example permutohedra and the associated toric varieties. In order to define a permutohedron, we need to use Polymake.jl
. We start by analyzing the permutohedron \(P \subset \mathbb{R}^4\) which is three-dimensional. Hence, we project it onto an appropriate hyperplane.
[46]:
using Polymake
[47]:
PP = Polyhedron(polytope.permutahedron(3))
P = project_full(PP)
[47]:
A polyhedron in ambient dimension 3
The associated toric variety is smooth and projectively normal, since the polytope \(P\) is smooth and normal, as we can see using the following commands.
[48]:
X = NormalToricVariety(P)
[issmooth(P), isnormal(P), issmooth(X), isnormal(X)]
[48]:
4-element Vector{Bool}:
1
1
1
1
We compute the Hilbert function of \(X\). Because the variety is projectively normal, the Hilbert polynomial coincides with the Ehrhart polynomial of \(P\).
[49]:
E_P = ehrhart_polynomial(P)
[49]:
Section 4
Example* 4.18
Consider the complete fan \(\Sigma\) in \(\mathbb{R}^2\) whose rays have generators \(\rho_1 = (1,2), \rho_2 = (1,0), \rho_3 = (-3,-2), \rho_4 = (0,1)\). This is the normal fan of a polytope \(P\).
[50]:
P = convex_hull([0 15; 0 1; 2 0; 10 0])
Σ = normal_fan(P)
[50]:
A polyhedral fan in ambient dimension 2
[51]:
isnormal(P)
[51]:
true
Because the polytope \(P\) is normal, the affine cone over the projective variety \(X_\Sigma\) associated to \(\Sigma\) coincides with the affine variety associated to the cone \(\text{cone}(PP)\subset \mathbb{R}^3\), where \(PP\) is \(P\) placed at height \(1\) in \(\mathbb{R}^3\).
[52]:
lattice_points(P)
[52]:
89-element SubObjectIterator{PointVector{Polymake.Integer}}:
[2, 0]
[0, 15]
[0, 1]
[0, 14]
[1, 1]
[1, 13]
[0, 2]
[3, 0]
[2, 1]
[1, 2]
[4, 0]
[3, 1]
[0, 3]
⋮
[2, 9]
[4, 8]
[1, 10]
[3, 9]
[0, 11]
[1, 12]
[2, 10]
[4, 9]
[1, 11]
[3, 10]
[0, 12]
[2, 11]
Since \(P\) has \(89\) lattice points, we can embedd \(\text{cone}(X_\Sigma)\) in \(\mathbb{C}^{89}\) and therefore \(X_\Sigma \subset \mathbb{P}^{88}\).
[53]:
X_Σ = NormalToricVariety(Σ)
[53]:
A normal toric variety
This variety can be covered by \(4\) affine pieces, only one of which is smooth.
[54]:
cover = affine_open_covering(X_Σ)
[issmooth(U) for U in cover]
[54]:
4-element Vector{Bool}:
0
0
1
0
[55]:
rays(cover[3])
[55]:
2-element SubObjectIterator{RayVector{Polymake.Rational}}:
[1, 2]
[0, 1]
To compute for instance the change of coordinates between \(U_{12}\) and \(U_{23}\) we need to compute the Hilbert bases of the associated cones.
[56]:
U12 = cover[2]
U23 = cover[1]
[56]:
A normal, affine, non-smooth toric variety
[57]:
H12 = hilbert_basis(polarize(cone(U12)))
H23 = hilbert_basis(polarize(cone(U23)))
println(H12)
println(H23)
PointVector{Polymake.Integer}[[1, 0], [0, 1], [2, -1]]
PointVector{Polymake.Integer}[[2, -3], [1, -2], [0, -1]]
They provide the embeddings \(U_{ij}\subset \mathbb{C}^3\) and the change of coordinates
Section 5
Example* 5.20
We can compute in Oscar.jl
the class group of a toric variety as follows.
[58]:
P = convex_hull([0 15; 0 1; 2 0; 10 0])
Σ = normal_fan(P)
X_Σ = NormalToricVariety(Σ)
[58]:
A normal toric variety
[59]:
Cl = class_group(X_Σ)
[59]:
Example* 5.23
We want to consider two distinct cones and compare the class group and the Picard group of the associated toric varieties.
[60]:
Σ = positive_hull([-1 -2; 1 0])
[60]:
A polyhedral cone in ambient dimension 2
[61]:
ΣΣ = PolyhedralFan([-1 -2; 1 0],IncidenceMatrix([[1],[2]]))
[61]:
A polyhedral fan in ambient dimension 2
[62]:
X_Σ = NormalToricVariety(Σ)
X_ΣΣ = NormalToricVariety(ΣΣ)
[62]:
A normal toric variety
[63]:
[issmooth(X_Σ), issmooth(X_ΣΣ)]
[63]:
2-element Vector{Bool}:
0
1
Since \(X_{\hat{\Sigma}}\) is smooth, we deduce that its class group coincides with its Picard group. On the other hand, they are different for \(X_\Sigma\): because \(\Sigma\) has a full dimensional cone, the Picard group is trivial. Moreover \(\Sigma\) and \(\hat{\Sigma}\) have the same set of rays, therefore their class groups coincide.
We can verify all these statements by computing the groups as follows.
[64]:
Pic1 = picard_group(X_Σ)
Pic2 = picard_group(X_ΣΣ)
Cl1 = class_group(X_Σ)
Cl2 = class_group(X_ΣΣ)
Pic1, Cl1, Pic2, Cl2
[64]:
(GrpAb: Z/1, GrpAb: Z/2, GrpAb: Z/2, GrpAb: Z/2)
Example* 5.27
We consider again the fan from Example* 4.18.
[65]:
ρ1 = [1 2]
ρ2 = [1 0]
ρ3 = [-3 -2]
ρ4 = [0 1]
Rays = [ρ1; ρ2; ρ3; ρ4]
IM = IncidenceMatrix([[1,2],[2,3],[3,4],[1,4]])
Σ = PolyhedralFan(Rays,IM)
X_Σ = NormalToricVariety(Σ)
[65]:
A normal toric variety
We construct the divisor \(D_3\) associated to the ray \(\rho_3\).
[66]:
D3 = ToricDivisor(X_Σ, [0,0,1,0])
[66]:
A torus-invariant, prime divisor on a normal toric variety
[67]:
iscartier(D3)
[67]:
false
This is not a Cartier divisor, but since \(\Sigma\) is simplicial, there exists an integer \(\ell > 0\) such that \(\ell \cdot D_3\) is simplicial. We can compute it as follows.
[68]:
i = 0
ℓ = 1
while i < 1
DD = iscartier(ToricDivisor(X_Σ, [0,0,ℓ,0]))
if DD == false
global ℓ += 1
else
print("ℓ = ", ℓ)
i = 1
end
end
ℓ = 6