Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit be82871

Browse files
committedMar 10, 2025·
[FTheoryTools] Include -1/2 c2 in computation of G4-flux families
1 parent 2597903 commit be82871

File tree

6 files changed

+330
-13
lines changed

6 files changed

+330
-13
lines changed
 

‎experimental/FTheoryTools/src/AbstractFTheoryModels/attributes.jl

+26
Original file line numberDiff line numberDiff line change
@@ -1996,3 +1996,29 @@ end
19961996
@attr QQMatrix function matrix_rational_quant_transverse_nobreak(m::AbstractFTheoryModel)
19971997
return matrix_rational(special_flux_family(m, not_breaking = true; check = check))
19981998
end
1999+
2000+
# Fluxes are offset by -1/2 * c2. Compute the vector which corresponds to this in terms of the internally chosen basis.
2001+
@attr Vector{QQFieldElem} function flux_family_offset_vector(m::AbstractFTheoryModel; check::Bool = true)
2002+
internal_basis = [polynomial(k) for k in basis_of_h22(ambient_space(m), check = check)]
2003+
converter_dict = get_attribute(ambient_space(m), :converter_dict_h22)
2004+
to_be_transformed_poly = lift(polynomial(chern_classes(m)[3]))
2005+
M = collect(exponents(to_be_transformed_poly))
2006+
non_zero_exponents = map(M) do row
2007+
i1 = findfirst(!iszero, row)
2008+
row[i1] -= 1
2009+
i2 = findfirst(!iszero, row)
2010+
(i1, i2)
2011+
end
2012+
coeffs = (-1) * (1//2) * collect(coefficients(to_be_transformed_poly))
2013+
converted_poly = sum(coeffs[l] * lift(polynomial(converter_dict[non_zero_exponents[l]])) for l in eachindex(coeffs))
2014+
final_mons = monomials(converted_poly)
2015+
final_coeffs = coefficients(converted_poly)
2016+
offset_vector = zeros(QQ, length(internal_basis))
2017+
for (mon, coeff) in zip(final_mons, final_coeffs)
2018+
idx = findfirst(==(mon), internal_basis)
2019+
if idx !== nothing
2020+
offset_vector[idx] = coeff
2021+
end
2022+
end
2023+
return offset_vector
2024+
end

‎experimental/FTheoryTools/src/FamilyOfG4Fluxes/special_constructors.jl

+13-13
Original file line numberDiff line numberDiff line change
@@ -298,7 +298,7 @@ end
298298

299299

300300
# (9) Remember computed data
301-
fgs = family_of_g4_fluxes(m, res[1], res[2])
301+
fgs = family_of_g4_fluxes(m, res[1], res[2], flux_family_offset_vector(m, check = check))
302302
set_attribute!(m, :matrix_integral_quant, res[1])
303303
set_attribute!(m, :matrix_rational_quant, res[2])
304304
set_attribute!(fgs, :is_well_quantized, true)
@@ -317,7 +317,10 @@ end
317317

318318
# (0) Has this result been computed before?
319319
if has_attribute(m, :matrix_integral_quant_transverse) && has_attribute(m, :matrix_rational_quant_transverse)
320-
fgs = family_of_g4_fluxes(m, matrix_integral_quant_transverse(m, check = check), matrix_rational_quant_transverse(m, check = check))
320+
fgs_m_int = matrix_integral_quant_transverse(m, check = check)
321+
fgs_m_rat = matrix_rational_quant_transverse(m, check = check)
322+
fgs_offset = flux_family_offset_vector(m, check = check)
323+
fgs = family_of_g4_fluxes(m, fgs_m_int, fgs_m_rat, fgs_offset)
321324
set_attribute!(fgs, :is_well_quantized, true)
322325
set_attribute!(fgs, :passes_transversality_checks, true)
323326
set_attribute!(fgs, :breaks_non_abelian_gauge_group, true)
@@ -522,18 +525,15 @@ end
522525
res = (sol_mat[:,1:r], sol_mat[:,r+1:ncols(solution_matrix)])
523526

524527

525-
# (11) Remember computed data
526-
fgs = family_of_g4_fluxes(m, res[1], res[2])
528+
# (11) Remember computed data and return the result
529+
fgs = family_of_g4_fluxes(m, res[1], res[2], flux_family_offset_vector(m, check = check))
527530
set_attribute!(m, :matrix_integral_quant_transverse, res[1])
528531
set_attribute!(m, :matrix_rational_quant_transverse, res[2])
529532
set_attribute!(fgs, :is_well_quantized, true)
530533
set_attribute!(fgs, :passes_transversality_checks, true)
531534
set_attribute!(fgs, :breaks_non_abelian_gauge_group, true)
532535
set_attribute!(m, :inter_dict, inter_dict)
533536
set_attribute!(m, :s_inter_dict, s_inter_dict)
534-
535-
536-
# (12) Finally, return the result
537537
return fgs
538538
end
539539

@@ -542,7 +542,10 @@ end
542542

543543
# (0) Has this result been computed before?
544544
if has_attribute(m, :matrix_integral_quant_transverse_nobreak) && has_attribute(m, :matrix_rational_quant_transverse_nobreak)
545-
fgs = family_of_g4_fluxes(m, matrix_integral_quant_transverse_nobreak(m, check = check), matrix_rational_quant_transverse_nobreak(m, check = check))
545+
fgs_m_int = matrix_integral_quant_transverse_nobreak(m, check = check)
546+
fgs_m_rat = matrix_rational_quant_transverse_nobreak(m, check = check)
547+
fgs_offset = flux_family_offset_vector(m, check = check)
548+
fgs = family_of_g4_fluxes(m, fgs_m_int, fgs_m_rat, fgs_offset)
546549
set_attribute!(fgs, :is_well_quantized, true)
547550
set_attribute!(fgs, :passes_transversality_checks, true)
548551
set_attribute!(fgs, :breaks_non_abelian_gauge_group, false)
@@ -772,17 +775,14 @@ end
772775
res = (sol_mat[:,1:r], sol_mat[:,r+1:ncols(solution_matrix)])
773776

774777

775-
# (11) Remember computed data
776-
fgs = family_of_g4_fluxes(m, res[1], res[2])
778+
# (11) Remember computed data and return result
779+
fgs = family_of_g4_fluxes(m, res[1], res[2], flux_family_offset_vector(m, check = check))
777780
set_attribute!(m, :matrix_integral_quant_transverse_nobreak, res[1])
778781
set_attribute!(m, :matrix_rational_quant_transverse_nobreak, res[2])
779782
set_attribute!(fgs, :is_well_quantized, true)
780783
set_attribute!(fgs, :passes_transversality_checks, true)
781784
set_attribute!(fgs, :breaks_non_abelian_gauge_group, false)
782785
set_attribute!(m, :inter_dict, inter_dict)
783786
set_attribute!(m, :s_inter_dict, s_inter_dict)
784-
785-
786-
# (12) Finally, return the result
787787
return fgs
788788
end

‎experimental/FTheoryTools/src/G4Fluxes/auxiliary.jl

+285
Original file line numberDiff line numberDiff line change
@@ -327,6 +327,291 @@ true
327327
end
328328

329329

330+
@attr Vector{CohomologyClass} function converter_dict_h22(v::NormalToricVariety; check::Bool = true)
331+
332+
# (0) Some initial checks
333+
if check
334+
@req is_complete(v) "Computation of converter dict for H22 is currently only supported for complete toric varieties"
335+
@req is_simplicial(v) "Computation of converter dict for H22 is currently only supported for simplicial toric varieties"
336+
end
337+
if dim(v) < 4
338+
return Vector{CohomologyClass}()
339+
end
340+
341+
# (1) Prepare some data of the variety
342+
mnf = Oscar._minimal_nonfaces(v)
343+
ignored_sets = Set([Tuple(sort(Vector{Int}(Polymake.row(mnf, i)))) for i in 1:Polymake.nrows(mnf)])
344+
345+
# (2) Prepare a dict that converts the "naive" generating set into our chosen basis
346+
converter_dict = Dict{Tuple{Int, Int}, Any}()
347+
for k in 1:n_rays(v)
348+
for l in k:n_rays(v)
349+
my_tuple = (k, l)
350+
if (my_tuple in ignored_sets)
351+
converter_dict[my_tuple] = 0
352+
else
353+
converter_dict[my_tuple] = nothing
354+
end
355+
end
356+
end
357+
358+
# (3) Prepare the linear relations
359+
N_lin_rel, my_mat = rref(transpose(matrix(QQ, rays(v))))
360+
@req N_lin_rel == nrows(my_mat) "Cannot remove as many variables as there are linear relations - weird!"
361+
bad_positions = [findfirst(!iszero, row) for row in eachrow(my_mat)]
362+
lin_rels = Dict{Int, Vector{QQFieldElem}}()
363+
for k in 1:nrows(my_mat)
364+
my_relation = (-1) * my_mat[k, :]
365+
my_relation[bad_positions[k]] = 0
366+
@req all(k -> k == 0, my_relation[bad_positions]) "Inconsistency!"
367+
lin_rels[bad_positions[k]] = my_relation
368+
end
369+
370+
# (4) Apply linear relations to remaining entries in converter_dict
371+
# (4) The code within the following for loop might need optimizing.
372+
crg = gens(base_ring(cohomology_ring(v)))
373+
for (key, value) in converter_dict
374+
if value === nothing
375+
image = Vector{Any}()
376+
377+
# Only the first entry needs replacing by the linear relations
378+
if (key[1] in keys(lin_rels)) && (key[2] in keys(lin_rels)) == false
379+
my_relation = lin_rels[key[1]]
380+
posi = findall(k -> k != 0, my_relation)
381+
coeffs = my_relation[posi]
382+
for k in 1:length(posi)
383+
push!(image, [coeffs[k], (posi[k], key[2])])
384+
end
385+
end
386+
387+
# Only the second entry needs replacing by the linear relations
388+
if (key[2] in keys(lin_rels)) && (key[1] in keys(lin_rels)) == false
389+
my_relation = lin_rels[key[2]]
390+
posi = findall(k -> k != 0, my_relation)
391+
coeffs = my_relation[posi]
392+
for k in 1:length(posi)
393+
push!(image, [coeffs[k], (key[1], posi[k])])
394+
end
395+
end
396+
397+
# Both entry needs replacing by the linear relations
398+
if (key[1] in keys(lin_rels)) && key[2] in keys(lin_rels)
399+
my_relation = lin_rels[key[1]]
400+
posi = findall(k -> k != 0, my_relation)
401+
coeffs = my_relation[posi]
402+
for k in 1:length(posi)
403+
push!(image, [coeffs[k], (posi[k], key[2])])
404+
end
405+
my_relation = lin_rels[key[2]]
406+
posi = findall(k -> k != 0, my_relation)
407+
coeffs = my_relation[posi]
408+
old_image = copy(image)
409+
image = Vector{Any}()
410+
for i in 1:length(old_image)
411+
for k in 1:length(posi)
412+
old_coeff = old_image[i][1]
413+
push!(image, [old_coeff * coeffs[k], (old_image[i][2][1], posi[k])])
414+
end
415+
end
416+
end
417+
418+
# If there was a replacement, update the key in the dict
419+
if length(image) > 0
420+
#image_as_cohomology_class = CohomologyClass(v, cohomology_ring(v)(sum(i[1] * crg[i[2][1]] * crg[i[2][2]] for i in image)))
421+
#converter_dict[key] = image_as_cohomology_class
422+
converter_dict[key] = image
423+
end
424+
end
425+
end
426+
427+
# (5) Prepare a list of those variables that we keep, a.k.a. a basis of H^(1,1)
428+
good_positions = setdiff(1:n_rays(v), bad_positions)
429+
n_good_positions = length(good_positions)
430+
431+
# (6) Make a list of all quadratic elements in the cohomology ring, which are not generators of the SR-ideal.
432+
N_filtered_quadratic_elements = 0
433+
dict_of_filtered_quadratic_elements = Dict{Tuple{Int64, Int64}, Int64}()
434+
for k in 1:n_good_positions
435+
for l in k:n_good_positions
436+
my_tuple = (min(good_positions[k], good_positions[l]), max(good_positions[k], good_positions[l]))
437+
if !(my_tuple in ignored_sets)
438+
N_filtered_quadratic_elements += 1
439+
dict_of_filtered_quadratic_elements[my_tuple] = N_filtered_quadratic_elements
440+
end
441+
end
442+
end
443+
444+
# (7) Consistency check
445+
l1 = sort(collect(keys(converter_dict))[findall(k -> converter_dict[k] === nothing, collect(keys(converter_dict)))])
446+
l2 = sort(collect(keys(dict_of_filtered_quadratic_elements)))
447+
@req l1 == l2 "Inconsistency found"
448+
449+
# (8) We only care about the SR-ideal gens of degree 2. Above, we took care of all relations,
450+
# (8) for which both variables are not replaced by one of the linear relations. So, let us identify
451+
# (8) all remaining relations of the SR-ideal, and apply the linear relations to them.
452+
remaining_relations = Vector{Vector{QQFieldElem}}()
453+
for my_tuple in ignored_sets
454+
455+
# The generator must have degree 2 and at least one variable is to be replaced
456+
if length(my_tuple) == 2 && (my_tuple[1] in bad_positions || my_tuple[2] in bad_positions)
457+
458+
# Represent first variable by list of coefficients, after plugging in the linear relation
459+
var1 = zeros(QQ, ncols(my_mat))
460+
var1[my_tuple[1]] = 1
461+
if my_tuple[1] in bad_positions
462+
var1 = lin_rels[my_tuple[1]]
463+
end
464+
465+
# Represent second variable by list of coefficients, after plugging in the linear relation
466+
var2 = zeros(QQ, ncols(my_mat))
467+
var2[my_tuple[2]] = 1
468+
if my_tuple[2] in bad_positions
469+
var2 = lin_rels[my_tuple[2]]
470+
end
471+
472+
# Compute the product of the two variables, which represents the new relation
473+
prod = zeros(QQ, N_filtered_quadratic_elements)
474+
for k in 1:length(var1)
475+
if var1[k] != 0
476+
for l in 1:length(var2)
477+
if var2[l] != 0
478+
my_tuple = (min(k, l), max(k, l))
479+
if haskey(dict_of_filtered_quadratic_elements, my_tuple)
480+
prod[dict_of_filtered_quadratic_elements[my_tuple]] += var1[k] * var2[l]
481+
end
482+
end
483+
end
484+
end
485+
end
486+
487+
# Remember the result
488+
push!(remaining_relations, prod)
489+
490+
end
491+
492+
end
493+
494+
# (9) Identify variables that we can remove with the remaining relations
495+
new_good_positions = 1:N_filtered_quadratic_elements
496+
if length(remaining_relations) != 0
497+
remaining_relations_matrix = matrix(QQ, remaining_relations)
498+
r, new_mat = rref(remaining_relations_matrix)
499+
@req r == nrows(remaining_relations_matrix) "Cannot remove a variable via linear relations - weird!"
500+
new_bad_positions = [findfirst(!iszero, row) for row in eachrow(new_mat)]
501+
new_good_positions = setdiff(1:N_filtered_quadratic_elements, new_bad_positions)
502+
end
503+
504+
# (10) Some of the remaining variables are replaced by the final remaining variables
505+
# (10) Above, we identified the remaining variables. Now we identify how the other variables
506+
# (10) that appear in dict_of_filtered_quadratic_elements are replaced.
507+
if length(remaining_relations) != 0
508+
new_basis = collect(keys(dict_of_filtered_quadratic_elements))
509+
for (key, value) in dict_of_filtered_quadratic_elements
510+
if (value in new_good_positions) == false
511+
512+
# Find relation to repalce this basis element by
513+
tuple_to_be_replaced = key
514+
index_of_element_to_be_replaced = value
515+
row_that_defines_relation = findfirst(k -> k == 1, new_mat[:,index_of_element_to_be_replaced])
516+
applicable_relation = new_mat[row_that_defines_relation, :]
517+
applicable_relation[index_of_element_to_be_replaced] = 0
518+
relation_to_be_applied = (-1) * applicable_relation
519+
relation_to_be_applied = [[relation_to_be_applied[ivalue], ikey] for (ikey, ivalue) in dict_of_filtered_quadratic_elements if relation_to_be_applied[ivalue] != 0]
520+
if length(relation_to_be_applied) == 0
521+
relation_to_be_applied = 0
522+
end
523+
524+
# Apply this relation throughout converter_dict, so that this tuple is never used in the values
525+
for (ikey, ivalue) in converter_dict
526+
527+
# If the entry maps to zero or is not yet specified, then nothing is to be done. Continue!
528+
if ivalue == 0 || ivalue === nothing
529+
continue
530+
end
531+
532+
# Is replacement needed?
533+
tuple_list = [k[2] for k in ivalue]
534+
position_of_key = findfirst(k -> k == key, tuple_list)
535+
if position_of_key !== nothing
536+
537+
# Prepare new lists for the tuples and coefficients
538+
new_tuple_list = copy(tuple_list)
539+
new_coeff_list = [k[1] for k in ivalue]
540+
541+
# Extract the coefficient of interest
542+
coeff_in_question = new_coeff_list[position_of_key]
543+
544+
# Remove the tuple to be replaced, and its corresponding coefficient
545+
deleteat!(new_tuple_list, position_of_key)
546+
deleteat!(new_coeff_list, position_of_key)
547+
548+
# Is the list empty after the removal? If so, we map to zero
549+
if length(new_tuple_list) == 0 && length(new_coeff_list) == 0
550+
converter_dict[ikey] = 0
551+
continue
552+
end
553+
554+
# Apply relation for element in question
555+
if relation_to_be_applied == 0
556+
converter_dict[ikey] = [[new_coeff_list[a], new_tuple_list[a]] for a in 1:length(new_tuple_list)]
557+
else
558+
for a in 1:length(relation_to_be_applied)
559+
if relation_to_be_applied[a][2] in new_tuple_list
560+
position_of_tuple = findfirst(k -> k == relation_to_be_applied[a][2], new_tuple_list)
561+
new_coeff_list[position_of_tuple] += relation_to_be_applied[a][1]
562+
else
563+
push!(new_tuple_list, relation_to_be_applied[a][2])
564+
push!(new_coeff_list, relation_to_be_applied[a][1])
565+
end
566+
end
567+
converter_dict[ikey] == [[new_coeff_list[a], new_tuple_list[a]] for a in 1:length(new_tuple_list)]
568+
end
569+
570+
end
571+
end
572+
573+
# Assign this value to the tuple to be replaced
574+
converter_dict[key] = relation_to_be_applied
575+
576+
end
577+
end
578+
end
579+
580+
# (11) Return the basis elements in terms of cohomology classes
581+
S = cohomology_ring(v, check = check)
582+
c_ds = [k.f for k in gens(S)]
583+
final_list_of_tuples = Tuple{Int64, Int64}[]
584+
for (key, value) in dict_of_filtered_quadratic_elements
585+
if value in new_good_positions
586+
push!(final_list_of_tuples, key)
587+
end
588+
end
589+
basis_of_h22 = [cohomology_class(v, MPolyQuoRingElem(c_ds[my_tuple[1]]*c_ds[my_tuple[2]], S)) for my_tuple in final_list_of_tuples]
590+
set_attribute!(v, :basis_of_h22_indices, final_list_of_tuples)
591+
592+
# (12) Consistency check
593+
l1 = sort(collect(keys(converter_dict))[findall(k -> converter_dict[k] === nothing, collect(keys(converter_dict)))])
594+
@req l1 == sort(final_list_of_tuples) "Inconsistency found"
595+
596+
# (13) Convert all entries in converter_dict to cohomology classes and return the result
597+
final_converter_dict = Dict{Tuple{Int, Int}, CohomologyClass}()
598+
for (key, value) in converter_dict
599+
if value == nothing
600+
final_converter_dict[key] = CohomologyClass(v, cohomology_ring(v)(crg[key[1]] *crg[key[2]]))
601+
elseif value == 0
602+
final_converter_dict[key] = CohomologyClass(v, zero(cohomology_ring(v, check = check)))
603+
else
604+
poly = sum(t[1] * crg[t[2][1]] * crg[t[2][2]] for t in value)
605+
image_as_cohomology_class = CohomologyClass(v, cohomology_ring(v)(poly))
606+
final_converter_dict[key] = image_as_cohomology_class
607+
end
608+
end
609+
return converter_dict_h22
610+
611+
end
612+
613+
614+
330615
# The following is an internal function, that is being used to identify all well-quantized G4-fluxes.
331616
# Let G4 in H^(2,2)(toric_ambient_space) a G4-flux ambient space candidate, i.e. the physically
332617
# truly relevant quantity is the restriction of G4 to a hypersurface V(pt) in the toric_ambient_space.

0 commit comments

Comments
 (0)
Please sign in to comment.