Chow rings
QuiverTools implements Chow rings computations for quivers and their representations. There also is an implementation of Bundle
objects in the Chow ring, which enable tensor calculus in the Chow ring.
Bundle
objects can also carry Teleman weights, and these behave well with respect to tensor calculus.
A QuiverModuliSpace
comes with an intermediary structure, ChowRing
, which is functionally just a container for various Chow ring data.
QuiverTools.ChowRing
— TypeSummary
struct ChowRing
A Type used to encode various Chow ring data.
Fields
parent :: Any
ring :: Singular.PolyRing{Singular.n_Q}
chi :: AbstractVector{Int}
point :: Union{Singular.spoly{Singular.n_Q},UndefInitializer}
todd :: Union{Singular.spoly{Singular.n_Q},UndefInitializer}
_R :: Singular.PolyRing{Singular.n_Q}
_inclusion :: Singular.SAlgHom{Singular.Rationals}
Presentation of Chow rings
Chow rings must be initialized manually, passing a choice of linearization to the constructor. If no linearization is passed, the default one is used.
QuiverTools.chow_ring
— Functionchow_ring(Q::Quiver, d::AbstractVector{Int}, theta::AbstractVector{Int}=canonical_stability(Q, d); chi::AbstractVector{Int}=extended_gcd(d)[2])
Compute the Chow ring of the moduli space of theta
-semistable representations of Q
with dimension vector d
, for a choice of linearization a
.
This method of the function chow_ring
also returns the ambient ring $R$ and the inclusion morphism.
Input
Q::Quiver
: a quiver.d::AbstractVector{Int}
: a dimension vector.theta::AbstractVector{Int}
: a stability parameter. Default iscanonical_stability(Q, d)
.chi
: a linearization. Default is the extended gcd ofextended_gcd(d)[2]
.
Output
A tuple containing:
- the Chow ring of the moduli space,
- the polynomial ring above it,
- the inclusion map $\iota : A \to R$.
Examples
The Chow ring for the projective line has two generators:
julia> Q = kronecker_quiver(2); M = QuiverModuliSpace(Q, [1, 1]);
julia> CH = chow_ring(M);
julia> QuiverTools.gens(QuiverTools.quotient_ideal(CH))
2-element Vector{Singular.spoly{Singular.n_Q}}:
x21
x11^2
The Chow ring for our favourite 6-fold has, in this implementation, 16 generators:
julia> Q = kronecker_quiver(3); M = QuiverModuliSpace(Q, [2, 3]);
julia> CH = chow_ring(M); I = QuiverTools.quotient_ideal(CH);
julia> length(QuiverTools.gens(I))
16
chow_ring(M::QuiverModuliSpace; chi::Union{AbstractVector{Int},UndefInitializer}=undef)
Compute the Chow ring of the moduli space M
for the given linearization chi
.
Input
M::QuiverModuliSpace
: a moduli space of representations of a quiver.chi::AbstractVector{Int}
: a choice of linearization for the trivial line bundle. Default isextended_gcd(M.d)[2]
.
Output
- the Chow ring of the moduli space.
chow_ring(F::Bundle)
QuiverTools.point_class
— Functionpoint_class(M::QuiverModuliSpace)
Compute the point class of the moduli space M
.
Input
M::QuiverModuliSpace
: a moduli space of representations of a quiver.
Output
- the point class of the moduli space, as a polynomial in its Chow ring.
Examples
A projective 7-fold:
julia> Q = kronecker_quiver(8);
julia> M = QuiverModuliSpace(Q, [1, 1]);
julia> chow_ring(M; chi=[1, 0]); point_class(M)
x21^7
Our favourite 6-fold:
julia> Q = kronecker_quiver(3);
julia> M = QuiverModuliSpace(Q, [2, 3]);
julia> point_class(M)
x23^2
QuiverTools.todd_class
— Functiontodd_class(M::QuiverModuliSpace)
Compute the Todd class of the moduli space M
.
Input
M::QuiverModuliSpace
: a moduli space of representations of a quiver.
Output
- the Todd class of the moduli space, as a polynomial in its Chow ring.
Examples
The Todd class of our favourite 3-Kronecker quiver moduli:
julia> Q = kronecker_quiver(3); M = QuiverModuliSpace(Q, [2, 3]);
julia> todd_class(M)
-17//8*x12*x21 + x21^2 + 823//360*x12*x22 - 823//1080*x22^2 + 553//1080*x21*x23 - 77//60*x22*x23 + x23^2 + 5//12*x12 - 3//2*x21 + 9//8*x23 + 1
QuiverTools.chern_class_line_bundle
— Functionchern_class_line_bundle(M::QuiverModuliSpace, eta::AbstractVector{Int})
Compute the first Chern class of the line bundle L(eta)
.
This is given by $L(eta) = \bigoplus_{i \in Q_0} \det(U_i)^{-eta_i}$.
Input
M::QuiverModuliSpace
: a moduli space of representations of a quiver.eta::AbstractVector{Int]
: a choice of linearization for the trivial line bundle.
Output
- the first Chern class of the line bundle L(eta) as a polynomial.
Examples
The line bundles $\mathcal{O}(i)$ on the projective line:
julia> Q = kronecker_quiver(2); M = QuiverModuliSpace(Q, [1, 1]);
julia> l = chern_class_line_bundle(M, [1, -1])
-x11
The line bundle corresponding to the canonical stability condition on our favourite 6-fold:
julia> Q = kronecker_quiver(3); M = QuiverModuliSpace(Q, [2, 3]);
julia> chern_class_line_bundle(M, [9, -6])
-3*x21
QuiverTools.chern_character_line_bundle
— Functionchern_character_line_bundle(M::QuiverModuliSpace, eta::AbstractVector{Int})
Compute the Chern character of the line bundle L(eta)
.
Input
M::QuiverModuliSpace
: a moduli space of representations of a quiver.eta::AbstractVector{Int}
: a choice of linearization for the trivial line bundle.
Output
- the Chern character of the line bundle
L(eta)
.
Examples
Some line bundles on the projective line:
julia> Q = kronecker_quiver(2); M = QuiverModuliSpace(Q, [1, 1]);
julia> chern_character_line_bundle(M, [1, -1])
-x11 + 1
Some Chern characters for our favourite 6-fold:
julia> Q = kronecker_quiver(3); M = QuiverModuliSpace(Q, [2, 3]);
julia> chern_character_line_bundle(M, [3, -2])
1//720*x21^6 - 1//120*x21^5 + 1//24*x21^4 - 1//6*x21^3 + 1//2*x21^2 - x21 + 1
QuiverTools.integral
— Functionintegral(M::QuiverModuliSpace, f)
Computes the integral of f
according to the Hirzebruch-Riemann-Roch theorem.
In other words, it computes the Euler characteristic of the vector bundle whose Chern character is f
.
Input
M::QuiverModuliSpace
: a moduli space of representations of a quiver.f
: the Chern character in to integrate.
Output
- the integral of
f
.
Examples
The integral of $\mathcal{O}(i)$ on the projective line for some i
s.
julia> Q = kronecker_quiver(2); M = QuiverModuliSpace(Q, [1, 1]);
julia> L = chern_character_line_bundle(M, [1, -1]);
julia> [integral(M, L^i) for i in 0:5]
6-element Vector{Singular.n_Q}:
1
2
3
4
5
6
Hilbert series for the 3-Kronecker quiver as in our favourite 6-fold:
julia> Q = kronecker_quiver(3); M = QuiverModuliSpace(Q, [2, 3]);
julia> L = chern_character_line_bundle(M, [3, -2]);
julia> [integral(M, L^i) for i in 0:5]
6-element Vector{Singular.n_Q}:
1
20
148
664
2206
5999
Bundle objects
QuiverTools.Bundle
— TypeSummary
mutable struct Bundle
An abstract bundle on a quiver moduli. It is represented in practice by its Chern character.
Fields
parent :: ChowRing
rank :: Int
chern_character :: Singular.spoly{Singular.n_Q}
chern_class :: Dict{Int,Singular.spoly{Singular.n_Q}}
teleman_weights :: Dict{<:HNTypes,Vector{Int}}
QuiverTools.chern_character
— Functionchern_character(F::Bundle)
QuiverTools.chern_class
— Functionchern_class(F::Bundle)
chern_class(F::Bundle, k)
QuiverTools.chern_classes
— Functionchern_classes(F::Bundle)
AbstractAlgebra.degree
— Functiondegree(F::Bundle)
Compute the degree of the bundle F
. If rank(F)
is larger than $1$, returns the degree of the determinant of F
.
Input
F::Bundle
: a bundle.
Output
- the degree of
F
.
Example
The degrees of canonical bundles on the first projective spaces:
julia> d = [1, 1]; Pn = map(i -> QuiverModuliSpace(kronecker_quiver(i + 1), d), 1:5);
julia> omega = map(canonical_bundle, Pn);
julia> omega = map(dual, omega);
julia> map(degree, omega)
5-element Vector{Singular.spoly{Singular.n_Q}}:
2
9
64
625
7776
An example from [arXiv:2411.15125]:
julia> Q = Quiver("1-2,1-3,2---3"); d = [1, 1, 1]; a = [1, 1, -1];
julia> M = QuiverModuliSpace(Q, d); chow_ring(M; chi=a);
julia> F = dual(canonical_bundle(M))
Bundle of rank 1
julia> chern_class(F)
2*x31 + 1
julia> degree(F)
56
QuiverTools.rank
— Functionrank(F::Bundle)
QuiverTools.teleman_weights
— Functionteleman_weights(F::Bundle)
A line bundle descending from a linearization above can be computed.
QuiverTools.line_bundle
— Functionline_bundle(M::QuiverModuliSpace, eta::AbstractVector{Int})
Construct the descent of L(eta)
on the quiver moduli space M
.
Input
M::QuiverModuliSpace
: a quiver moduli space.eta::AbstractVector{Int}
: a dimension vector.
Output
- the line bundle on
M
with Chern classchern_class_line_bundle(M, eta)
.
Examples
The ample generator of the Picard group of our favourite 6-fold:
julia> Q = kronecker_quiver(3); M = QuiverModuliSpace(Q, [2, 3]);
julia> chow_ring(M; chi=[-1, 1]);
julia> H = line_bundle(M, [3, -2]);
julia> chern_class(H)
-x21
julia> teleman_weights(H)
Dict{HNType{2}, Vector{Int64}} with 7 entries:
[[2, 2], [0, 1]] => [-30]
[[2, 1], [0, 2]] => [-40]
[[1, 0], [1, 2], [0, 1]] => [-40]
[[1, 0], [1, 3]] => [-135]
[[1, 0], [1, 1], [0, 2]] => [-105]
[[1, 1], [1, 2]] => [-5]
[[2, 0], [0, 3]] => [-90]
Some special bundles can be computed out of the box.
QuiverTools.zero_sheaf
— Functionzero_sheaf(M::QuiverModuliSpace)
QuiverTools.structure_sheaf
— Functionstructure_sheaf(M::QuiverModuliSpace)
QuiverTools.canonical_bundle
— Functioncanonical_bundle(M::QuiverModuliSpace)
Compute the canonical bundle on the quiver moduli space M
.
If $d$ is $theta$-coprime and amply stable, the canonical bundle is described in [Proposition 4.2, MR4352662].
This function computes both the Chern character and the Teleman weights of the canonical bundle.
Input
M::QuiverModuliSpace
: a quiver moduli space.
Output
- the canonical bundle on
M
.
Example
On various projective spaces:
julia> d = [1, 1]; Pn = map(i -> QuiverModuliSpace(kronecker_quiver(i + 1), d), 1:5);
julia> omega = map(canonical_bundle, Pn);
julia> map(chern_class, omega)
5-element Vector{Singular.spoly{Singular.n_Q}}:
2*x11
3*x11
4*x11
5*x11
6*x11
julia> map(teleman_weights, omega)
5-element Vector{Dict{HNType{2}, Vector{Int64}}}:
Dict([[1, 0], [0, 1]] => [8])
Dict([[1, 0], [0, 1]] => [18])
Dict([[1, 0], [0, 1]] => [32])
Dict([[1, 0], [0, 1]] => [50])
Dict([[1, 0], [0, 1]] => [72])
On our favourite 6-fold:
julia> Q = kronecker_quiver(3); M = QuiverModuliSpace(Q, [2, 3]);
julia> omega = canonical_bundle(M);
julia> chern_class(omega)
3*x21
julia> QuiverTools.teleman_weights(omega)
Dict{HNType{2}, Vector{Int64}} with 7 entries:
[[2, 2], [0, 1]] => [90]
[[2, 1], [0, 2]] => [120]
[[1, 0], [1, 2], [0, 1]] => [120]
[[1, 0], [1, 3]] => [405]
[[1, 0], [1, 1], [0, 2]] => [315]
[[1, 1], [1, 2]] => [15]
[[2, 0], [0, 3]] => [270]
QuiverTools.universal_bundle
— Functionuniversal_bundle(M:::QuiverModuliSpace, i::Int)
Compute the i
-th universal bundle of M
.
This function computes both the Chern classes and the Teleman weights of the universal bundle.
To use this method, the moduli space M
must have a linearization. If not, this method will initialize the Chow ring of M
by calling chow_ring(M)
and it will use the default linearization.
Input
M::QuiverModuliSpace
: a quiver moduli space.i::Int
: the universal bundle on thei
-th vertex of the quiver.
Output
- the
i
-th universal bundle onM
.
Example
On the projective line:
julia> Q = kronecker_quiver(2); d = [1, 1];
julia> M = QuiverModuliSpace(Q, d); chow_ring(M; chi=[1, 0]);
julia> u1, u2 = universal_bundle(M, 1), universal_bundle(M, 2);
julia> map(chern_class, [u1, u2])
2-element Vector{Singular.spoly{Singular.n_Q}}:
x11 + 1
x21 + 1
julia> map(teleman_weights, [u1, u2])
2-element Vector{Dict{HNType{2}, Vector{Int64}}}:
Dict([[1, 0], [0, 1]] => [0])
Dict([[1, 0], [0, 1]] => [-4])
On our favourite 6-fold:
julia> Q = kronecker_quiver(3); M = QuiverModuliSpace(Q, [2, 3]);
julia> chow_ring(M; chi=[-1, 1]);
julia> u1, u2 = universal_bundle(M, 1), universal_bundle(M, 2);
julia> map(chern_character, [u1, u2])
2-element Vector{Singular.spoly{Singular.n_Q}}:
1//6*x12*x21 + 1//2*x21^2 + 1//12*x12*x22 - 1//36*x22^2 - 7//72*x21*x23 - 1//120*x22*x23 - 1//720*x23^2 - x12 + x21 - 1//2*x23 + 2
2//3*x12*x21 + 1//2*x21^2 - 1//6*x12*x22 - 1//2*x21*x22 + 1//12*x22^2 + 1//24*x21*x23 + 1//180*x22*x23 + x21 - x22 + 3
julia> w = map(teleman_weights, [u1, u2]);
julia> w[1]
Dict{HNType{2}, Vector{Int64}} with 7 entries:
[[2, 2], [0, 1]] => [15, 15]
[[2, 1], [0, 2]] => [20, 20]
[[1, 0], [1, 2], [0, 1]] => [25, 15]
[[1, 0], [1, 3]] => [90, 45]
[[1, 0], [1, 1], [0, 2]] => [60, 45]
[[1, 1], [1, 2]] => [5, 0]
[[2, 0], [0, 3]] => [45, 45]
julia> w[2]
Dict{HNType{2}, Vector{Int64}} with 7 entries:
[[2, 2], [0, 1]] => [15, 15, 0]
[[2, 1], [0, 2]] => [20, 10, 10]
[[1, 0], [1, 2], [0, 1]] => [15, 15, 10]
[[1, 0], [1, 3]] => [45, 45, 45]
[[1, 0], [1, 1], [0, 2]] => [45, 30, 30]
[[1, 1], [1, 2]] => [5, 0, 0]
[[2, 0], [0, 3]] => [30, 30, 30]
Tensor calculus
QuiverTools.dual
— Functiondual(F::Bundle)
Compute the dual bundle of F
.
Input
F::Bundle
: a bundle.
Output
- the dual bundle of
F
.
Example
On the projective line:
julia> Q = kronecker_quiver(2); d = [1, 1]; a = [1, 0];
julia> M = QuiverModuliSpace(Q, d); chow_ring(M; chi=a);
julia> td = Bundle(M, todd_class(M))
Bundle of rank 1
julia> chern_character(dual(td))
-x21 + 1
On our favourite 6-fold:
julia> Q, d = kronecker_quiver(3), [2, 3];
julia> M = QuiverModuliSpace(Q, d); chow_ring(M; chi=[-1, 1]);
julia> td = Bundle(M, todd_class(M));
julia> chern_character(td)
-17//8*x12*x21 + x21^2 + 823//360*x12*x22 - 823//1080*x22^2 + 553//1080*x21*x23 - 77//60*x22*x23 + x23^2 + 5//12*x12 - 3//2*x21 + 9//8*x23 + 1
julia> tdd = dual(td)
Bundle of rank 1
julia> chern_character(tdd)
17//8*x12*x21 + x21^2 + 823//360*x12*x22 - 823//1080*x22^2 + 553//1080*x21*x23 + 77//60*x22*x23 + x23^2 + 5//12*x12 + 3//2*x21 - 9//8*x23 + 1
QuiverTools.exterior_power
— Functionexterior_power(F::Bundle, k::Int)
Compute the k
-th exterior power of F
.
Input
F::Bundle
: a bundle.k::Int
: the degree of the exterior power.
Output
- the
k
-th exterior power ofF
.
Example
On the projective line:
julia> Q = kronecker_quiver(2); d = [1, 1]; a = [1, 0];
julia> M = QuiverModuliSpace(Q, d); chow_ring(M; chi=a);
julia> td = Bundle(M, todd_class(M))
Bundle of rank 1
julia> F = 3*td
Bundle of rank 3
julia> chern_character(F)
3*x21 + 3
julia> W = map(i -> exterior_power(F, i), 0:4);
julia> map(w -> (rank(w), chern_character(w)), W)
5-element Vector{Tuple{Int64, Singular.spoly{Singular.n_Q}}}:
(1, 1)
(3, 3*x21 + 3)
(3, 6*x21 + 3)
(1, 3*x21 + 1)
(0, 0)
QuiverTools.symmetric_power
— Functionsymmetric_power(F::Bundle, k::Int)
Compute the k
-th symmetric power of F
.
Input
F::Bundle
: a bundle.k::Int
: the degree of the symmetric power.
Output
- the
k
-th symmetric power ofF
.
Example
On the projective line:
julia> Q = kronecker_quiver(2); d = [1, 1]; a = [1, 0];
julia> M = QuiverModuliSpace(Q, d); chow_ring(M; chi=a);
julia> td = Bundle(M, todd_class(M));
julia> F = 3*td
Bundle of rank 3
julia> chern_character(F)
3*x21 + 3
julia> W = map(i -> symmetric_power(F, i), 0:4);
julia> map(w -> (rank(w), chern_character(w)), W)
5-element Vector{Tuple{Int64, Singular.spoly{Singular.n_Q}}}:
(1, 1)
(3, 3*x21 + 3)
(6, 12*x21 + 6)
(10, 30*x21 + 10)
(15, 60*x21 + 15)
QuiverTools.det
— Functiondet(F::Bundle)
Compute the determinant of F
. This is the top exterior power of F
.