Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Intersection theory: Schubert calculus #3959

Merged
merged 2 commits into from
Jul 22, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions experimental/IntersectionTheory/docs/doc.main
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
"AbstractBundles.md",
"AbstractVarietyMaps.md",
"BlowUps.md",
"schubert.md",
"BottFormulas.md",
"examples.md"
],
Expand Down
16 changes: 14 additions & 2 deletions experimental/IntersectionTheory/docs/src/examples.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,20 @@ DocTestSetup = Oscar.doctestsetup()

# Illustrating Examples From Enumerative Geometry

#### How Many Lines in $\mathbb P^3$ Meet Four General Lines in $\mathbb P^3$?

#### How Many Conics in $\mathbb P^3$ Meet Eight General Lines
```jldoctest
julia> G = abstract_grassmannian(2,4)
AbstractVariety of dim 4

julia> s1 = schubert_class(G, 1)
-c[1]

julia> integral(s1^4)
2

```
#### How Many Conics in $\mathbb P^3$ Meet Eight General Lines in $\mathbb P^3$?

```jldoctest
julia> G = abstract_grassmannian(3, 4)
Expand Down Expand Up @@ -69,7 +81,7 @@ julia> integral((6*HBl-2*e)^5)

```

#### Number of Twisted Cubics on the General Quintic Hypersurface
#### How Many Twisted Cubics lie on the General Quintic Hypersurface

```jldoctest
julia> G = abstract_grassmannian(3, 5)
Expand Down
72 changes: 72 additions & 0 deletions experimental/IntersectionTheory/docs/src/schubert.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
```@meta
CurrentModule = Oscar
```

# Schubert Calculus

To recall the definition of Schubert cycles on a Grassmannian $\mathrm{G}(k,n)$, we think of $\mathrm{G}(k, n)$ as the
Grassmannian $\mathrm{G}(k, W)$ of $k$-dimensional subspaces of an $n$-dimensional $K$-vector space $W$.

A *flag* in $W$ is a strictly increasing sequence of linear subspaces

$\{0\} \subset W_1 \subset \dots \subset W_{n-1} \subset W_n = W, \; \text{ with }\; \dim(W_i) = i.$

Let such a flag $\mathcal{W}$ be given. For any sequence $a = (a_1, \ldots, a_k)$
of integers with $n-k \geq a_1 \geq \ldots \geq a_k \geq 0$, we define
the *Schubert cycle* $\Sigma_a(\mathcal{W})$ by setting

$\Sigma_a(\mathcal{W}):= \{ V \in \mathrm{G}(k, W)\mid \dim(W_{n-k+i-a_i} \cap V) \geq i, i = 1, \ldots, k \} \,.$

Then we have:
- The Schubert cycle $\Sigma_a(\mathcal{W})$ is an irreducible subvariety of $\mathrm{G}(k, W)$ of codimension $|a| = \sum a_i$.
- Its cycle class $[\Sigma_a(\mathcal{W})]$ does not depend on the choice of the flag.

We define the *Schubert class* of $a = (a_1, \ldots, a_k)$ to be the cycle class

$\sigma_a := [\Sigma_a(\mathcal{W})] \,.$

The number of Schubert classes on the Grassmannian $\mathrm{G}(k, n)$ is equal to $\binom{n}{k}$.

Instead of $\sigma_a$, we write $\sigma_{a_1,\ldots,a_s}$ whenever
$a = (a_1, \ldots, a_s, 0, \ldots, 0)$, and $\sigma_{p^i}$ whenever
$a = (p, \ldots, p, 0, \ldots, 0) \in \mathbb Z^i \times \{0\}^{k-i}$.

The classes $\sigma_{1^i}$, $i = 1, \ldots, k$, and $\sigma_i$, $i = 1, \ldots, n-k$, are
called *special Schubert classes*. They are closely related to the Chern classes of the tautological
vector bundles on $\mathrm{G}(k, W)$. Recall:

- The *tautological subbundle* on $\mathrm{G}(k, W)$ is the vector bundle of rank $k$ whose fiber at $V \in \mathrm{G}(k, W)$ is the subspace $V \subset W$.
- The *tautological quotient bundle* on $\mathrm{G}(k, W)$ is the vector bundle of rank $(n-k)$ whose fiber at $V \in \mathrm{G}(k, W)$ is the quotient vector space $W/V$.

We denote these vector bundles by $S$ and $Q$, respectively.

The Chern classes of $S$ and $Q$ are

$c_i(S) = (-1)^i \sigma_{1^i} \; \text{ for } \; i = 1, \ldots, k$

and

$c_i(Q) = \sigma_i \; \text{ for }\; i = 1, \ldots, n-k,$

respectively.

All Schubert classes form a $K$-vector space basis of the Chow ring of $\mathrm{G}(k,n)$.
The Chern classes of $S$ (the special Schubert classes $\sigma_{1^i}$, $i=1, \ldots, k$)
form a minimal set of generators for the Chow ring of $\mathrm{G}(k,n)$ as a $K$-algebra.
See [EH16](@cite) for the relations on these generators.

```@docs
schubert_class(G::AbstractVariety, λ::Int...)
```

```@docs
schubert_classes(G::AbstractVariety, m::Int)
```

```@docs
schubert_classes(G::AbstractVariety)
```




3 changes: 2 additions & 1 deletion experimental/IntersectionTheory/src/IntersectionTheory.jl
Original file line number Diff line number Diff line change
Expand Up @@ -75,8 +75,9 @@ include("Types.jl")
include("Misc.jl")

include("Bott.jl") # integration using Bott's formula
include("Main.jl") # basic constructions for Schubert calculus
include("Main.jl") # basic constructors and functionality
include("blowup.jl") # blowup
include("schubert.jl") # Schubert calculus
# include("Moduli.jl") # moduli of matrices, twisted cubics
# include("Weyl.jl") # weyl groups

Expand Down
54 changes: 18 additions & 36 deletions experimental/IntersectionTheory/src/Main.jl
Original file line number Diff line number Diff line change
Expand Up @@ -408,7 +408,7 @@ end
#
# generic abstract_variety with some classes in given degrees
@doc raw"""
abstract_variety(n::Int, symbols::Vector{String}, degs::Vector{Int})
abstract_variety(n::Int, symbols::Vector{String}, degs::Vector{Int}; base::Ring=QQ)

Construct a generic abstract variety of dimension $n$ with some classes in given degrees.

Expand Down Expand Up @@ -499,7 +499,7 @@ end
@doc raw"""
chow_ring(X::AbstractVariety)

Return the Chow ring of `X`.
Return the Chow ring of the abstract variety `X`.

# Examples
```jldoctest
Expand Down Expand Up @@ -1971,7 +1971,7 @@ end
@doc raw"""
abstract_grassmannian(k::Int, n::Int; base::Ring = QQ, symbol::String = "c")

Return the abstract Grassmannian $\mathrm{Gr}(k, n)$ of `k`-dimensional subspaces of an
Return the abstract Grassmannian $\mathrm{G}(k, n)$ of `k`-dimensional subspaces of an
`n`-dimensional vector space.

# Examples
Expand All @@ -1986,14 +1986,27 @@ Quotient
c[2] -> [2]
by ideal (-c[1]^3 + 2*c[1]*c[2], c[1]^4 - 3*c[1]^2*c[2] + c[2]^2)

julia> S = tautological_bundles(G)[1]
AbstractBundle of rank 2 on AbstractVariety of dim 4

julia> V = [chern_class(S, i) for i = 1:2]
2-element Vector{MPolyQuoRingElem{MPolyDecRingElem{QQFieldElem, QQMPolyRingElem}}}:
c[1]
c[2]

julia> is_regular_sequence(gens(modulus(CR)))
true

julia> Q = tautological_bundles(G)[2]
AbstractBundle of rank 2 on AbstractVariety of dim 4

julia> tangent_bundle(G) == dual(S)*Q
true

```
"""
function abstract_grassmannian(k::Int, n::Int; base::Ring = QQ, symbol::String = "c")
@assert k < n

@assert k < n
d = k*(n-k)
R, c = graded_polynomial_ring(base, _parse_symbol(symbol, 1:k), collect(1:k))
inv_c = sum((-sum(c))^i for i in 1:n) # this is c(Q) since c(S)⋅c(Q) = 1
Expand Down Expand Up @@ -2164,34 +2177,3 @@ function abstract_flag_variety(F::AbstractBundle, dims::Vector{Int}; symbol::Str
if l == 2 set_attribute!(Fl, :grassmannian => :relative) end
return Fl
end

@doc raw"""
schubert_class(G::AbstractVariety, λ::Int...)
schubert_class(G::AbstractVariety, λ::Vector{Int})
schubert_class(G::AbstractVariety, λ::Partition)

Return the Schubert class $\sigma_\lambda$ on a (relative) Grassmannian $G$.
"""
function schubert_class(G::AbstractVariety, λ::Int...) schubert_class(G, collect(λ)) end
function schubert_class(G::AbstractVariety, λ::Partition) schubert_class(G, Vector(λ)) end
function schubert_class(G::AbstractVariety, λ::Vector{Int})
get_attribute(G, :grassmannian) === nothing && error("the abstract_variety is not a Grassmannian")
(length(λ) > rank(G.bundles[1]) || sort(λ, rev=true) != λ) && error("the Schubert input is not well-formed")
giambelli(G.bundles[2], λ)
end

@doc raw"""
schubert_classes(m::Int, G::AbstractVariety)

Return all the Schubert classes in codimension $m$ on a (relative) Grassmannian $G$.
"""
function schubert_classes(G::AbstractVariety, m::Int)
get_attribute(G, :grassmannian) === nothing && error("the abstract_variety is not a Grassmannian")
S, Q = G.bundles
res = elem_type(G.ring)[]
for i in 0:rank(S)
append!(res, [schubert_class(G, l) for l in partitions(m, i, 1, rank(Q))])
end
return res
end

132 changes: 132 additions & 0 deletions experimental/IntersectionTheory/src/schubert.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
@doc raw"""
schubert_class(G::AbstractVariety, λ::Int...)
schubert_class(G::AbstractVariety, λ::Vector{Int})
schubert_class(G::AbstractVariety, λ::Partition)

Return the Schubert class $\sigma_\lambda$ on a (relative) Grassmannian `G`.

# Examples

```jldoctest
julia> G = abstract_grassmannian(2,4)
AbstractVariety of dim 4

julia> s0 = schubert_class(G, 0)
1

julia> s1 = schubert_class(G, 1)
-c[1]

julia> s2 = schubert_class(G, 2)
c[1]^2 - c[2]

julia> s11 = schubert_class(G, [1, 1])
c[2]

julia> s21 = schubert_class(G, [2, 1])
-c[1]*c[2]

julia> s22 = schubert_class(G, [2, 2])
c[2]^2

julia> s1*s1 == s2+s11
true

julia> s1*s2 == s1*s11 == s21
true

julia> s1*s21 == s2*s2 == s22
true

```

```jldoctest
julia> G = abstract_grassmannian(2,5)
AbstractVariety of dim 6

julia> s3 = schubert_class(G, 5-2)
-c[1]^3 + 2*c[1]*c[2]

julia> s3^2 == point_class(G)
true

julia> Q = tautological_bundles(G)[2]
AbstractBundle of rank 3 on AbstractVariety of dim 6

julia> chern_class(Q, 3)
-c[1]^3 + 2*c[1]*c[2]

```

```jldoctest
julia> G = abstract_grassmannian(2,4)
AbstractVariety of dim 4

julia> s1 = schubert_class(G, 1)
-c[1]

julia> s1 == schubert_class(G, [1, 0])
true

julia> integral(s1^4)
2

```
"""
function schubert_class(G::AbstractVariety, λ::Int...) schubert_class(G, collect(λ)) end
function schubert_class(G::AbstractVariety, λ::Partition) schubert_class(G, Vector(λ)) end
function schubert_class(G::AbstractVariety, λ::Vector{Int})
get_attribute(G, :grassmannian) === nothing && error("the abstract_variety is not a Grassmannian")
(length(λ) > rank(G.bundles[1]) || sort(λ, rev=true) != λ) && error("the Schubert input is not well-formed")
giambelli(G.bundles[2], λ)
end

@doc raw"""
schubert_classes(G::AbstractVariety, m::Int)

Return all Schubert classes in codimension `m` on a (relative) Grassmannian `G`.
"""
function schubert_classes(G::AbstractVariety, m::Int)
get_attribute(G, :grassmannian) === nothing && error("the abstract_variety is not a Grassmannian")
S, Q = G.bundles
res = elem_type(G.ring)[]
for i in 0:rank(S)
append!(res, [schubert_class(G, l) for l in partitions(m, i, 1, rank(Q))])
end
return res
end

@doc raw"""
schubert_classes(G::AbstractVariety)

Return all Schubert classes on a (relative) Grassmannian `G`.

# Examples

```jldoctest
julia> G = abstract_grassmannian(2,4)
AbstractVariety of dim 4

julia> schubert_classes(G)
5-element Vector{Vector{MPolyQuoRingElem{MPolyDecRingElem{QQFieldElem, QQMPolyRingElem}}}}:
[1]
[-c[1]]
[c[1]^2 - c[2], c[2]]
[-c[1]*c[2]]
[c[2]^2]

julia> basis(G)
5-element Vector{Vector{MPolyQuoRingElem}}:
[1]
[c[1]]
[c[2], c[1]^2]
[c[1]*c[2]]
[c[2]^2]

```
"""
function schubert_classes(G::AbstractVariety)
get_attribute(G, :grassmannian) === nothing && error("the abstract_variety is not a Grassmannian")
S, Q = G.bundles
return [schubert_classes(G, i) for i = 0:rank(S)*rank(Q)]
end
Loading