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

Pullback of rational functions along strict transforms #2681

Merged
Show file tree
Hide file tree
Changes from 12 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
3 changes: 3 additions & 0 deletions experimental/Schemes/Auxiliary.jl
Original file line number Diff line number Diff line change
Expand Up @@ -372,3 +372,6 @@ function inherit_glueings!(ref::Covering, orig::Covering)
return ref
end

### Generic pullback and pushforward for composite maps
pushforward(f::Generic.CompositeMap, a::Any) = pushforward(map2(f), pushforward(map1(f), a))
pullback(f::Generic.CompositeMap, a::Any) = pullback(map1(f), pullback(map2(f), a))
101 changes: 91 additions & 10 deletions experimental/Schemes/BlowupMorphism.jl
Original file line number Diff line number Diff line change
Expand Up @@ -73,8 +73,15 @@ with restriction
```
"""
@attributes mutable struct BlowupMorphism{
CodomainType<:AbsCoveredScheme
} # TODO: Derive this from AbsCoveredSchemeMorphism ?
DomainType<:AbsCoveredScheme, # Not a concrete type in general because this is lazy
CodomainType<:AbsCoveredScheme,
BaseMorphismType # Nothing in case of no base change
} <: AbsCoveredSchemeMorphism{
DomainType,
CodomainType,
BaseMorphismType,
BlowupMorphism
}
projective_bundle::CoveredProjectiveScheme
codomain::CodomainType # in general a CoveredScheme
center::IdealSheaf # on codomain
Expand All @@ -88,10 +95,13 @@ with restriction
)
X = base_scheme(IP)
X === scheme(I) || error("ideal sheaf not compatible with blown up variety")
return new{typeof(X)}(IP, X, I)
return new{AbsCoveredScheme, typeof(X), Nothing}(IP, X, I)
end
end

### Forward the essential functionality
underlying_morphism(phi::BlowupMorphism) = projection(phi)

function domain(p::BlowupMorphism)
if !isdefined(p, :domain)
p.domain = covered_scheme(p.projective_bundle)
Expand Down Expand Up @@ -151,10 +161,60 @@ function strict_transform(p::BlowupMorphism, inc::CoveredClosedEmbedding)
inc_Z_trans = CoveredClosedEmbedding(Y, I_trans,
covering=simplified_covering(Y), # Has been set by the previous call
check=false)
inc_cov = covering_morphism(inc_Z_trans)
inc_dom_cov = covering_morphism(inc_Z_trans)
inc_cod_cov = covering_morphism(inc)

Z_trans = domain(inc_Z_trans)
pr_res = restrict(projection(p), inc_Z_trans, inc)

if has_attribute(p, :isomorphism_on_open_subset)
OOX = OO(X)
OOY = OO(Y)
p_iso = isomorphism_on_open_subset(p)
U = domain(p_iso)::PrincipalOpenSubset
V = codomain(p_iso)::PrincipalOpenSubset
V_amb = ambient_scheme(V)
U_amb = ambient_scheme(U)

# Given all the refinements that potentially had to be done, we have
# to do the following.
# - Find a `patch` `U_sub` of the `domain` of `inc_dom_cov` for which
# inc_cod : U_sub -> W has a codomain `W` which has `U_amb` as an
# ancestor. Since `U_amb` is one of the `affine_charts` of `X`, this will work.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is U_amb a chart of X? It seems to me that it is a chart of Y?
What is the domain and codomain of p_iso? (i.e. does it point in the same direction as p? or the opposite one?)

simonbrandhorst marked this conversation as resolved.
Show resolved Hide resolved
# - pr_res : U_amb -> V_amb has some codomain such that there exists
# an ancestor `VV` in the `domain` of `inc_dom_cov` such that
# inc_dom : VV -> W' has a codomain with `V_amb` as an ancestor.
# - outside the `complement_equation`s of `U` and `V` the projection
# was an isomorphism. Then the restriction of `pr_res` to those
# complements in `U_sub` and `V_sub` also is.
k = findfirst(x->has_ancestor(y->y===U_amb, codomain(inc_dom_cov[x])), patches(domain(inc_dom_cov)))
U_sub = patches(domain(inc_dom_cov))[k]
iso_U_sub = _flatten_open_subscheme(U_sub, domain(inc_dom_cov[U_sub]))
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what does this do and why do you do it?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

line 192 is deprecated and superfluous. Did you mean that? In that case: Thanks for catching!

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yep

U_sub_res = PrincipalOpenSubset(U_sub,
pullback(inc_dom_cov[U_sub])(
OOX(U_amb, codomain(inc_dom_cov[U_sub]))(
complement_equation(U)
)
)
)

pr_res_cov = covering_morphism(pr_res)
pr_sub = pr_res_cov[U_sub]

V_sub = codomain(pr_sub)
@assert has_ancestor(x->any(y->y===x, patches(domain(inc_cod_cov))), V_sub)
V_sub_inc, comp_eqns = _find_chart(V_sub, domain(inc_cod_cov))
OOZ = OO(Z)
dummy_dom = codomain(V_sub_inc)
dummy_map = inc_cod_cov[dummy_dom]
dummy_cod = codomain(dummy_map)
V_sub_res = PrincipalOpenSubset(V_sub,
OOZ(dummy_dom, V_sub)(pullback(dummy_map)(OOY(V_amb, dummy_cod)(complement_equation(V)))))
result = restrict(pr_sub, U_sub_res, V_sub_res)
# TODO: Obtain the inverse another way?
@assert is_isomorphism(result)
set_attribute!(pr_res, :isomorphism_on_open_subset, result)
end
return Z_trans, inc_Z_trans, pr_res
end

Expand Down Expand Up @@ -498,13 +558,17 @@ end
return p_res
end

### Some functionality used by function fields

# If set this attribute shall return some isomorphism on some open subsets of the domain
# and codomain of phi. If both are irreducible, this automatically implies that both are
# dense, but we do not check for this.
@attr AbsSpecMor function isomorphism_on_open_subset(f::BlowupMorphism)
pr = isomorphism_on_complement_of_center(f)
X = domain(pr)
Y = codomain(pr)
pr_cov = covering_morphism(pr)
U = first(patches(domain(pr_cov)))
pr_res = pr_cov[U]
X = domain(f)
Y = codomain(f)
iso_dict = get_attribute(f, :isos_on_complement_of_center)
pr_res = first(values(iso_dict))
U = domain(pr_res)
V = codomain(pr_res)
iso_U = _flatten_open_subscheme(U, default_covering(X))
U_flat = codomain(iso_U)
Expand Down Expand Up @@ -544,3 +608,20 @@ function pushforward(f::BlowupMorphism, g::VarietyFunctionFieldElem)
pfg = fraction(pullback(phi)(OO(V)(numerator(h))))//fraction(pullback(phi)(OO(V)(denominator(h))))
return FY.(pfg)
end

@attr AbsSpecMor function isomorphism_on_open_subset(phi::AbsCoveredSchemeMorphism)
error("attribute not found; this needs to be set manually in general")
end

function compose(f::BlowupMorphism, g::BlowupMorphism)
return composite_map(f, g)
end

function compose(f::BlowupMorphism, g::AbsCoveredSchemeMorphism)
return composite_map(f, g)
end

function compose(f::AbsCoveredSchemeMorphism, g::BlowupMorphism)
return composite_map(f, g)
end

159 changes: 159 additions & 0 deletions experimental/Schemes/CoveredScheme.jl
Original file line number Diff line number Diff line change
Expand Up @@ -568,3 +568,162 @@ function CoveredClosedEmbedding(X::AbsCoveredScheme, I::IdealSheaf;
return CoveredClosedEmbedding(Z, X, cov_inc, ideal_sheaf=I, check=false)
end

########################################################################
# Composite morphism of covered schemes
########################################################################

@attributes mutable struct CompositeCoveredSchemeMorphism{
simonbrandhorst marked this conversation as resolved.
Show resolved Hide resolved
DomainType<:AbsCoveredScheme,
CodomainType<:AbsCoveredScheme,
BaseMorphismType
} <: AbsCoveredSchemeMorphism{
DomainType,
CodomainType,
BaseMorphismType,
CoveredSchemeMorphism
}
maps::Vector{<:AbsCoveredSchemeMorphism}

# fields for caching
composed_map::AbsCoveredSchemeMorphism

function CompositeCoveredSchemeMorphism(maps::Vector{<:AbsCoveredSchemeMorphism})
n = length(maps)
for i in 1:n-1
@assert codomain(maps[i]) === domain(maps[i+1]) "maps are not compatible"
end
# TODO: Take care of non-trivial base changes!
return new{typeof(domain(first(maps))), typeof(codomain(maps[end])), Nothing}(maps)
end
end

### Essential getters
maps(f::CompositeCoveredSchemeMorphism) = f.maps
domain(f::CompositeCoveredSchemeMorphism) = domain(first(f.maps))
codomain(f::CompositeCoveredSchemeMorphism) = codomain(f.maps[end])

### Forwarding essential functionality (to be avoided!)
function underlying_morphism(f::CompositeCoveredSchemeMorphism)
if !isdefined(f, :composed_map)
result = underlying_morphism(first(maps(f)))::CoveredSchemeMorphism
for i in 2:length(maps(f))
result = compose(result, underlying_morphism(maps(f)[i]))::CoveredSchemeMorphism
end
f.composed_map = result
end
return f.composed_map::CoveredSchemeMorphism
end

### Specialized functionality

# Casting into the minimal concrete type for AbsCoveredSchemeMorphism
function CoveredSchemeMorphism(f::CompositeCoveredSchemeMorphism)
return underlying_morphism(f)
end

function CoveredSchemeMorphism(f::CoveredSchemeMorphism)
return f
end

########################################################################
# The standard constructors
########################################################################
@doc raw"""
composite_map(f::AbsCoveredSchemeMorphism, g::AbsCoveredSchemeMorphism)

Realize the composition ``x → g(f(x))`` as a composite map, i.e. an
instance of `CompositeCoveredSchemeMorphism`.

# Examples
```jldoctest
julia> IA2 = affine_space(QQ, [:x, :y])
Affine space of dimension 2
over rational field
with coordinates [x, y]

julia> (x, y) = gens(OO(IA2));

julia> I = ideal(OO(IA2), [x, y]);

julia> pr = blow_up(IA2, I);

julia> JJ = ideal_sheaf(exceptional_divisor(pr));

julia> inc_E = oscar.CoveredClosedEmbedding(domain(pr), JJ);

julia> comp = oscar.composite_map(inc_E, pr)
Composite morphism of
Morphism: scheme over QQ covered with 2 patches -> scheme over QQ covered with 2 patches
Blow-up: scheme over QQ covered with 2 patches -> scheme over QQ covered with 1 patch

julia> oscar.maps(comp)[1] === inc_E
true

julia> oscar.maps(comp)[2] === pr
true

```
"""
function composite_map(f::AbsCoveredSchemeMorphism, g::AbsCoveredSchemeMorphism)
return CompositeCoveredSchemeMorphism([f, g])
end

function composite_map(f::AbsCoveredSchemeMorphism, g::CompositeCoveredSchemeMorphism)
return CompositeCoveredSchemeMorphism(pushfirst!(Vector{AbsCoveredSchemeMorphism}(copy(maps(g))), f))
end

function composite_map(f::CompositeCoveredSchemeMorphism, g::CompositeCoveredSchemeMorphism)
return CompositeCoveredSchemeMorphism(vcat(maps(f), maps(g)))
end

function composite_map(f::CompositeCoveredSchemeMorphism, g::AbsCoveredSchemeMorphism)
return CompositeCoveredSchemeMorphism(push!(Vector{AbsCoveredSchemeMorphism}(copy(maps(f))), g))
end

########################################################################
# Printing
########################################################################
function Base.show(io::IO, f::CompositeCoveredSchemeMorphism)
io = pretty(io)
if get(io, :supercompact, false)
print(io, "Composite morphism")
else
map_string = "$(domain(f)) -> "
for i in 2:length(maps(f))
map_string = map_string * "$(domain(map(f)[i])) -> "
end
map_string = map_string * "$(codomain(map(f)[end]))"

print(io, "Composition of ", map_string)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No need to print to an intermediate string

Suggested change
map_string = "$(domain(f)) -> "
for i in 2:length(maps(f))
map_string = map_string * "$(domain(map(f)[i])) -> "
end
map_string = map_string * "$(codomain(map(f)[end]))"
print(io, "Composition of ", map_string)
print(io, "Composition of ", map_string)
print(io, domain(f), " -> ")
for i in 2:length(maps(f))
print(io, domain(map(f)[i]), " -> ")
end
print(io, codomain(map(f)[end]))

end
end

function Base.show(io::IO, ::MIME"text/plain", f::CompositeCoveredSchemeMorphism)
io = pretty(io)
println(io, "Composite morphism of", Indent())
for g in maps(f)
println(io, g)
end
end
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
end
end
end
print(io, Dedent())
end


########################################################################
# Bound functionality
########################################################################
function pushforward(f::CompositeCoveredSchemeMorphism, a::VarietyFunctionFieldElem)
result = a
for g in maps(f)
result = pushforward(g, result)
end
return result
end

function pullback(f::CompositeCoveredSchemeMorphism, a::VarietyFunctionFieldElem)
result = a
for g in reverse(maps(f))
result = pullback(g, result)
end
return result
end

### Missing compatibility
underlying_morphism(f::CoveredSchemeMorphism) = f
13 changes: 13 additions & 0 deletions experimental/Schemes/FunctionFields.jl
Original file line number Diff line number Diff line change
Expand Up @@ -502,6 +502,19 @@ function is_regular(f::VarietyFunctionFieldElem, W::SpecOpen)
end

function pushforward(f::AbsCoveredSchemeMorphism, a::VarietyFunctionFieldElem)
X = domain(f)
Y = codomain(f)
parent(a) === function_field(X) || error("element does not belong to the correct ring")
has_attribute(f, :isomorphism_on_open_subset) || error("need an isomorphism on some open subset")
f_res = isomorphism_on_open_subset(f)
U = domain(f_res)
V = codomain(f_res)
aa = a[ambient_scheme(U)]
f_res_inv = inverse(f_res)
num = pullback(f_res_inv)(numerator(aa))
den = pullback(f_res_inv)(denominator(aa))
bb = fraction(num)//fraction(den)
simonbrandhorst marked this conversation as resolved.
Show resolved Hide resolved
return function_field(Y)(bb)
end

function pullback(f::AbsCoveredSchemeMorphism, a::VarietyFunctionFieldElem)
Expand Down
2 changes: 1 addition & 1 deletion experimental/Schemes/elliptic_surface.jl
Original file line number Diff line number Diff line change
Expand Up @@ -452,7 +452,7 @@ function relatively_minimal_model(E::EllipticSurface)

ambient_exceptionals = EffectiveCartierDivisor{typeof(X0)}[]
varnames = [:a,:b,:c,:d,:e,:f,:g,:h,:i,:j,:k,:l,:m,:n,:o,:p,:q,:r,:u,:v,:w]
projectionsX = BlowupMorphism{typeof(X0)}[]
projectionsX = BlowupMorphism[]
projectionsY = AbsCoveredSchemeMorphism[]
count = 0

Expand Down
Loading
Loading