/
methods.jl
177 lines (142 loc) · 7.7 KB
/
methods.jl
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
#####################################################
# 1: Fiber analysis
#####################################################
@doc raw"""
analyze_fibers(model::GlobalTateModel, centers::Vector{<:Vector{<:Integer}})
Determine the fiber of a (singular) global Tate model over a particular base locus.
```
"""
function analyze_fibers(model::GlobalTateModel, centers::Vector{<:Vector{<:Integer}})
# This method only works if the model is defined over a toric variety over toric scheme
@req base_space(model) isa NormalToricVariety "Analysis of fibers currently only supported for toric variety as base space"
# Ideal of the defining polynomial
hypersurface_ideal = ideal([tate_polynomial(model)])
# Toric ambient space
tas = ambient_space(model)
# Various important ideals
irr = irrelevant_ideal(tas);
sri = stanley_reisner_ideal(tas);
lin = ideal_of_linear_relations(tas);
# Singular loci
sing_loc = singular_loci(model)
# Pick out the singular loci that are more singular than an I_1
# Then keep only the locus and not the extra info about it
interesting_singular_loci = map(tup -> tup[1], filter(locus -> locus[2][3] > 1, sing_loc))
# This is a kludge to map polynomials on the base into the ambient space, and should be fixed once the ambient space constructors supply such a map
base_coords = parent(gens(interesting_singular_loci[1])[1])
ambient_coords = parent(tate_polynomial(model))
base_to_ambient_ring_map = hom(base_coords, ambient_coords, gens(ambient_coords)[1:end-3])
# Resolved model
strict_transform, exceptionals, crepant, res_irr, res_sri, res_lin, res_S, res_S_gens, res_ring_map = _blowup_global_sequence(hypersurface_ideal, centers, irr, sri, lin)
if !crepant
@warn "The given sequence of blowups is not crepant"
end
loci_fiber_intersections = Tuple{MPolyIdeal{QQMPolyRingElem}, Vector{Tuple{Tuple{Int64, Int64}, Vector{MPolyIdeal{QQMPolyRingElem}}}}}[]
for locus in interesting_singular_loci
# Currently have to get the ungraded ideal generators by hand using .f
ungraded_locus = ideal(map(gen -> base_to_ambient_ring_map(gen).f, gens(locus)))
# Potential components of the fiber over this locus
# For now, we only consider the associated prime ideal,
# but we may later want to actually consider the primary ideals
potential_components = map(pair -> pair[2], primary_decomposition(strict_transform + res_ring_map(ungraded_locus)))
# Filter out the trivial loci among the potential components
components = filter(component -> _is_nontrivial(component, res_irr), potential_components)
# Check the pairwise intersections of the components
intersections = Tuple{Tuple{Int64, Int64}, Vector{MPolyIdeal{QQMPolyRingElem}}}[]
for i in 1:length(components) - 1
for j in i + 1:length(components)
intersection = filter(candidate_locus -> _is_nontrivial(candidate_locus, res_irr), map(pair -> pair[2], primary_decomposition(components[i] + components[j])))
push!(intersections, ((i, j), intersection))
end
end
push!(loci_fiber_intersections, (ungraded_locus, intersections))
end
return loci_fiber_intersections
end
#####################################################
# 2: Tune a Tate model
#####################################################
@doc raw"""
tune(t::GlobalTateModel, input_sections::Dict{String, <:Any}; completeness_check::Bool = true)
Tune a Tate model by fixing a special choice for the model sections.
# Examples
```jldoctest
julia> B3 = projective_space(NormalToricVariety, 3)
Normal toric variety
julia> w = torusinvariant_prime_divisors(B3)[1]
Torus-invariant, prime divisor on a normal toric variety
julia> t = literature_model(arxiv_id = "1109.3454", equation = "3.1", base_space = B3, model_sections = Dict("w" => w), completeness_check = false)
Construction over concrete base may lead to singularity enhancement. Consider computing singular_loci. However, this may take time!
Global Tate model over a concrete base -- SU(5)xU(1) restricted Tate model based on arXiv paper 1109.3454 Eq. (3.1)
julia> x1, x2, x3, x4 = gens(cox_ring(base_space(t)))
4-element Vector{MPolyDecRingElem{QQFieldElem, QQMPolyRingElem}}:
x1
x2
x3
x4
julia> my_choice = Dict("a1" => x1^4, "a2" => x1^8, "w" => x2 - x3)
Dict{String, MPolyDecRingElem{QQFieldElem, QQMPolyRingElem}} with 3 entries:
"w" => x2 - x3
"a2" => x1^8
"a1" => x1^4
julia> tuned_t = tune(t, my_choice)
Global Tate model over a concrete base
julia> tate_section_a1(tuned_t) == x1^4
true
```
"""
function tune(t::GlobalTateModel, input_sections::Dict{String, <:Any}; completeness_check::Bool = true)
# Consistency checks
@req base_space(t) isa NormalToricVariety "Currently, tuning is only supported for models over concrete toric bases"
isempty(input_sections) && return t
secs_names = collect(keys(explicit_model_sections(t)))
tuned_secs_names = collect(keys(input_sections))
@req all(x -> x in secs_names, tuned_secs_names) "Provided section name not recognized"
# 0. Prepare for computation by setting up some information
explicit_secs = deepcopy(explicit_model_sections(t))
def_secs_param = deepcopy(defining_section_parametrization(t))
tate_sections = ["a1", "a2", "a3", "a4", "a6"]
# 1. Tune model sections different from Tate sections
for x in setdiff(tuned_secs_names, tate_sections)
section_parent = parent(input_sections[x])
section_degree = degree(input_sections[x])
@req section_parent == parent(explicit_model_sections(t)[x]) "Parent mismatch between given and existing model section"
@req section_degree == degree(explicit_model_sections(t)[x]) "Degree mismatch between given and existing model section"
explicit_secs[x] = input_sections[x]
end
# 2. Use model sections to reevaluate the Tate sections via their known parametrization
parametrization_keys = collect(keys(def_secs_param))
if !isempty(parametrization_keys) && !isempty(secs_names)
R = parent(def_secs_param[parametrization_keys[1]])
S = parent(explicit_secs[secs_names[1]])
vars = [string(k) for k in gens(R)]
images = [k in secs_names ? explicit_secs[k] : k == "Kbar" ? eval_poly("0", S) : eval_poly(k, S) for k in vars]
map = hom(R, S, images)
for section in tate_sections
haskey(def_secs_param, section) && (explicit_secs[section] = map(eval_poly(string(def_secs_param[section]), R)))
end
end
# 3. Does the user want to set some Tate sections? If so, overwrite existing choice with desired value.
for sec in tate_sections
if haskey(input_sections, sec)
@req parent(input_sections[sec]) == parent(explicit_model_sections(t)[sec]) "Parent mismatch between given and existing Tate section"
@req degree(input_sections[sec]) == degree(explicit_model_sections(t)[sec]) "Degree mismatch between given and existing Tate section"
explicit_secs[sec] = input_sections[sec]
delete!(def_secs_param, sec)
end
end
# 4. There could be unused model sections...
if !isempty(parametrization_keys)
polys = [eval_poly(string(def_secs_param[section]), R) for section in tate_sections if haskey(def_secs_param, section)]
all_appearing_monomials = vcat([collect(monomials(p)) for p in polys]...)
all_appearing_exponents = [collect(exponents(m))[1] for m in all_appearing_monomials]
potentially_redundant_sections = gens(R)
for k in 1:length(potentially_redundant_sections)
string(potentially_redundant_sections[k]) in tate_sections && continue
is_used = any(all_appearing_exponents[l][k] != 0 for l in 1:length(all_appearing_exponents))
is_used || delete!(explicit_secs, string(potentially_redundant_sections[k]))
end
end
# 5. Build the new model
return global_tate_model(base_space(t), explicit_secs, def_secs_param; completeness_check)
end