#![allow(clippy::items_after_test_module)]
use oxilean_kernel::{BinderInfo, Declaration, Environment, Expr, Level, Name};
use super::types::{
BezoutBound, ChowRingElem, CycleClass, IntersectionMatrix, QuantumCohomologyP2, SchubertCalc,
VectorBundleData,
};
pub fn app(f: Expr, a: Expr) -> Expr {
Expr::App(Box::new(f), Box::new(a))
}
pub fn app2(f: Expr, a: Expr, b: Expr) -> Expr {
app(app(f, a), b)
}
pub fn app3(f: Expr, a: Expr, b: Expr, c: Expr) -> Expr {
app(app2(f, a, b), c)
}
pub fn cst(s: &str) -> Expr {
Expr::Const(Name::str(s), vec![])
}
pub fn prop() -> Expr {
Expr::Sort(Level::zero())
}
pub fn type0() -> Expr {
Expr::Sort(Level::succ(Level::zero()))
}
pub fn type1() -> Expr {
Expr::Sort(Level::succ(Level::succ(Level::zero())))
}
pub fn pi(bi: BinderInfo, name: &str, dom: Expr, body: Expr) -> Expr {
Expr::Pi(bi, Name::str(name), Box::new(dom), Box::new(body))
}
pub fn arrow(a: Expr, b: Expr) -> Expr {
pi(BinderInfo::Default, "_", a, b)
}
pub fn bvar(n: u32) -> Expr {
Expr::BVar(n)
}
pub fn nat_ty() -> Expr {
cst("Nat")
}
pub fn int_ty() -> Expr {
cst("Int")
}
pub fn real_ty() -> Expr {
cst("Real")
}
pub fn bool_ty() -> Expr {
cst("Bool")
}
pub fn list_ty(elem: Expr) -> Expr {
app(cst("List"), elem)
}
pub fn chow_group_ty() -> Expr {
arrow(cst("Scheme"), arrow(nat_ty(), type0()))
}
pub fn chow_ring_ty() -> Expr {
arrow(cst("Scheme"), type0())
}
pub fn algebraic_cycle_ty() -> Expr {
arrow(cst("Scheme"), arrow(nat_ty(), type0()))
}
pub fn rational_equiv_ty() -> Expr {
arrow(
app2(cst("AlgebraicCycle"), cst("Scheme"), cst("k")),
arrow(app2(cst("AlgebraicCycle"), cst("Scheme"), cst("k")), prop()),
)
}
pub fn intersection_product_ty() -> Expr {
arrow(cst("ChowRing"), arrow(cst("ChowRing"), cst("ChowRing")))
}
pub fn pushforward_cycle_ty() -> Expr {
arrow(cst("Morphism"), arrow(cst("ChowGroup"), cst("ChowGroup")))
}
pub fn pullback_cycle_ty() -> Expr {
arrow(cst("Morphism"), arrow(cst("ChowGroup"), cst("ChowGroup")))
}
pub fn fundamental_class_ty() -> Expr {
arrow(cst("Scheme"), cst("ChowGroup"))
}
pub fn bezout_intersection_ty() -> Expr {
arrow(list_ty(nat_ty()), nat_ty())
}
pub fn bezout_theorem_ty() -> Expr {
arrow(
list_ty(nat_ty()),
arrow(prop(), app2(cst("Eq"), cst("Nat"), nat_ty())),
)
}
pub fn excess_intersection_formula_ty() -> Expr {
arrow(
cst("Morphism"),
arrow(cst("Scheme"), arrow(cst("ExcessBundle"), cst("ChowGroup"))),
)
}
pub fn chern_class_ty() -> Expr {
arrow(cst("VectorBundle"), arrow(nat_ty(), cst("ChowGroup")))
}
pub fn total_chern_class_ty() -> Expr {
arrow(cst("VectorBundle"), cst("ChowRing"))
}
pub fn chern_character_ty() -> Expr {
arrow(cst("VectorBundle"), cst("ChowRing"))
}
pub fn whitney_sum_formula_ty() -> Expr {
arrow(
cst("VectorBundle"),
arrow(
cst("VectorBundle"),
app2(
cst("Eq"),
cst("ChowRing"),
app(
cst("TotalChernClass"),
app2(cst("DirectSum"), bvar(1), bvar(0)),
),
),
),
)
}
pub fn splitting_principle_ty() -> Expr {
arrow(cst("VectorBundle"), arrow(cst("Morphism"), prop()))
}
pub fn segre_class_ty() -> Expr {
arrow(cst("Subscheme"), arrow(cst("Scheme"), cst("ChowGroup")))
}
pub fn self_intersection_formula_ty() -> Expr {
arrow(
cst("Morphism"),
arrow(cst("Scheme"), arrow(cst("NormalBundle"), cst("ChowGroup"))),
)
}
pub fn segre_chern_relation_ty() -> Expr {
arrow(
cst("VectorBundle"),
app2(
cst("Eq"),
cst("ChowRing"),
app(cst("InverseChow"), app(cst("TotalChernClass"), bvar(0))),
),
)
}
pub fn todd_class_ty() -> Expr {
arrow(cst("VectorBundle"), cst("ChowRing"))
}
pub fn grothendieck_riemann_roch_ty() -> Expr {
arrow(
cst("Morphism"),
arrow(
cst("CoherentSheaf"),
app2(
cst("Eq"),
cst("ChowRing"),
app2(
cst("ChowMul"),
app(cst("ChernCharacter"), cst("PushforwardSheaf")),
app(cst("ToddClass"), cst("TangentBundle")),
),
),
),
)
}
pub fn hirzebruch_riemann_roch_ty() -> Expr {
arrow(
cst("SmoothProj"),
arrow(
cst("VectorBundle"),
app2(cst("Eq"), int_ty(), app(cst("EulerChar"), cst("E"))),
),
)
}
pub fn obstruction_theory_ty() -> Expr {
arrow(cst("Morphism"), type0())
}
pub fn virtual_fundamental_class_ty() -> Expr {
arrow(cst("ObstructionTheory"), cst("ChowGroup"))
}
pub fn virtual_dimension_ty() -> Expr {
arrow(cst("ObstructionTheory"), int_ty())
}
pub fn stable_map_ty() -> Expr {
arrow(
nat_ty(),
arrow(cst("Scheme"), arrow(list_ty(nat_ty()), type1())),
)
}
pub fn gromov_witten_invariant_ty() -> Expr {
arrow(
cst("Scheme"),
arrow(nat_ty(), arrow(list_ty(cst("ChowClass")), int_ty())),
)
}
pub fn wdvv_equation_ty() -> Expr {
arrow(
cst("Scheme"),
arrow(
cst("ChowClass"),
arrow(
cst("ChowClass"),
arrow(cst("ChowClass"), arrow(cst("ChowClass"), prop())),
),
),
)
}
pub fn degeneration_formula_ty() -> Expr {
arrow(
cst("Morphism"),
arrow(cst("GromovWittenInvariant"), cst("GromovWittenInvariant")),
)
}
pub fn quantum_cohomology_ty() -> Expr {
arrow(cst("Scheme"), type0())
}
pub fn quantum_product_ty() -> Expr {
arrow(
cst("QuantumCohomology"),
arrow(cst("QuantumCohomology"), cst("QuantumCohomology")),
)
}
pub fn quantum_ring_associativity_ty() -> Expr {
arrow(
cst("QuantumCohomology"),
arrow(
cst("QuantumCohomology"),
arrow(
cst("QuantumCohomology"),
app2(
cst("Eq"),
cst("QuantumCohomology"),
app2(
cst("QuantumProduct"),
app2(cst("QuantumProduct"), bvar(2), bvar(1)),
bvar(0),
),
),
),
),
)
}
pub fn conway_potential_ty() -> Expr {
arrow(cst("Scheme"), arrow(nat_ty(), real_ty()))
}
pub fn dt_invariant_ty() -> Expr {
arrow(cst("Scheme"), arrow(cst("CurveClass"), int_ty()))
}
pub fn dt_gw_correspondence_ty() -> Expr {
arrow(
cst("Scheme"),
app2(
cst("Eq"),
cst("FormalPowerSeries"),
app(cst("DTPartitionFunction"), bvar(0)),
),
)
}
pub fn vertex_formalism_ty() -> Expr {
arrow(
cst("ToricVariety"),
arrow(
cst("Partition"),
arrow(cst("Partition"), cst("DTInvariant")),
),
)
}
pub fn hilbert_scheme_dt_ty() -> Expr {
arrow(cst("Surface"), arrow(nat_ty(), cst("DTInvariant")))
}
pub fn schubert_variety_ty() -> Expr {
arrow(cst("Grassmannian"), arrow(cst("Partition"), cst("Scheme")))
}
pub fn schubert_class_ty() -> Expr {
arrow(
cst("Grassmannian"),
arrow(cst("Partition"), cst("ChowGroup")),
)
}
pub fn pieri_formula_ty() -> Expr {
arrow(cst("SchubertClass"), arrow(nat_ty(), cst("ChowGroup")))
}
pub fn giambelli_formula_ty() -> Expr {
arrow(cst("Partition"), cst("ChowGroup"))
}
pub fn littlewood_richardson_ty() -> Expr {
arrow(
cst("Partition"),
arrow(cst("Partition"), list_ty(cst("ChowGroup"))),
)
}
pub fn grassmannian_chow_ring_ty() -> Expr {
arrow(nat_ty(), arrow(nat_ty(), type0()))
}
pub fn flag_variety_ty() -> Expr {
arrow(list_ty(nat_ty()), type0())
}
pub fn schubert_polynomial_ty() -> Expr {
arrow(cst("Permutation"), cst("Polynomial"))
}
pub fn blowup_ty() -> Expr {
arrow(cst("Scheme"), arrow(cst("Subscheme"), cst("Scheme")))
}
pub fn exceptional_divisor_ty() -> Expr {
arrow(cst("BlowupScheme"), cst("Divisor"))
}
pub fn blowup_chow_ring_map_ty() -> Expr {
arrow(cst("Scheme"), arrow(cst("Subscheme"), cst("ChowRing")))
}
pub fn strict_transform_ty() -> Expr {
arrow(cst("Scheme"), arrow(cst("BlowupScheme"), cst("Scheme")))
}
pub fn blowup_formula_ty() -> Expr {
arrow(
cst("Scheme"),
arrow(
cst("Subscheme"),
app2(cst("Eq"), cst("ChowRing"), cst("ChowRing")),
),
)
}
pub fn degeneracy_locus_ty() -> Expr {
arrow(cst("BundleMap"), arrow(nat_ty(), cst("Scheme")))
}
pub fn thom_porteous_formula_ty() -> Expr {
arrow(cst("BundleMap"), arrow(cst("Partition"), cst("ChowGroup")))
}
pub fn euler_class_ty() -> Expr {
arrow(cst("VectorBundle"), cst("ChowGroup"))
}
pub fn euler_class_zero_locus_ty() -> Expr {
arrow(
cst("VectorBundle"),
arrow(
cst("BundleSection"),
app2(cst("Eq"), cst("ChowGroup"), app(cst("EulerClass"), bvar(1))),
),
)
}
pub fn moduli_curves_ty() -> Expr {
arrow(nat_ty(), arrow(nat_ty(), type1()))
}
pub fn deligne_mumford_ty() -> Expr {
arrow(nat_ty(), arrow(nat_ty(), type1()))
}
pub fn kontsevich_space_ty() -> Expr {
arrow(cst("Scheme"), arrow(nat_ty(), arrow(nat_ty(), type1())))
}
pub fn psi_class_ty() -> Expr {
arrow(cst("ModuliCurvesType"), arrow(nat_ty(), cst("ChowGroup")))
}
pub fn lambda_class_ty() -> Expr {
arrow(cst("ModuliCurvesType"), arrow(nat_ty(), cst("ChowGroup")))
}
pub fn virasoro_constraints_ty() -> Expr {
arrow(nat_ty(), arrow(cst("GWPotential"), prop()))
}
pub fn dilation_equation_ty() -> Expr {
arrow(cst("GWPotential"), prop())
}
pub fn motivic_cohomology_ty() -> Expr {
arrow(cst("Scheme"), arrow(nat_ty(), arrow(nat_ty(), type0())))
}
pub fn algebraic_k_theory_ty() -> Expr {
arrow(cst("Scheme"), arrow(nat_ty(), type0()))
}
pub fn chern_character_k_theory_ty() -> Expr {
arrow(cst("KTheoryClass"), cst("ChowRing"))
}
pub fn atiyah_hirzebruch_ty() -> Expr {
arrow(
cst("Scheme"),
app2(cst("Eq"), type0(), app(cst("K0Ring"), bvar(0))),
)
}
pub fn motivic_integration_ty() -> Expr {
arrow(cst("Scheme"), real_ty())
}
pub fn hilbert_scheme_points_ty() -> Expr {
arrow(cst("Scheme"), arrow(nat_ty(), type1()))
}
pub fn hilbert_chow_ty() -> Expr {
arrow(cst("HilbertSchemeType"), cst("SymmetricProduct"))
}
pub fn nakajima_operator_ty() -> Expr {
arrow(
cst("HilbertSchemeType"),
arrow(cst("ChowGroup"), cst("ChowGroup")),
)
}
pub fn gottsche_formula_ty() -> Expr {
arrow(cst("Surface"), arrow(nat_ty(), int_ty()))
}
pub fn intersection_multiplicity_ty() -> Expr {
arrow(
cst("Scheme"),
arrow(cst("Scheme"), arrow(cst("Scheme"), nat_ty())),
)
}
pub fn polynomial_resultant_ty() -> Expr {
arrow(
cst("Polynomial"),
arrow(cst("Polynomial"), cst("Polynomial")),
)
}
pub fn intersection_multiplicity_formula_ty() -> Expr {
arrow(list_ty(cst("Polynomial")), arrow(nat_ty(), prop()))
}
pub fn build_intersection_theory_env(env: &mut Environment) {
let base_types: &[(&str, Expr)] = &[
("Scheme", type1()),
("VectorBundle", type0()),
("CoherentSheaf", type0()),
("ChowGroup", type0()),
("ChowRing", type0()),
("ChowClass", type0()),
("AlgebraicCycle", type0()),
("Morphism", type0()),
("Subscheme", type0()),
("NormalBundle", type0()),
("ExcessBundle", type0()),
("ObstructionTheory", type0()),
("FormalPowerSeries", type0()),
("ToricVariety", type0()),
("Surface", type0()),
("SmoothProj", type0()),
("Partition", type0()),
("CurveClass", type0()),
("GromovWittenInvariant", type0()),
("QuantumCohomology", type0()),
("DTInvariant", type0()),
("Nat", type0()),
("Int", type0()),
("Real", type0()),
("Bool", type0()),
("Eq", arrow(type0(), arrow(type0(), prop()))),
("And", arrow(prop(), arrow(prop(), prop()))),
("Exists", arrow(type0(), arrow(type0(), prop()))),
("List", arrow(type0(), type0())),
(
"DirectSum",
arrow(
cst("VectorBundle"),
arrow(cst("VectorBundle"), cst("VectorBundle")),
),
),
(
"ChowMul",
arrow(cst("ChowRing"), arrow(cst("ChowRing"), cst("ChowRing"))),
),
("InverseChow", arrow(cst("ChowRing"), cst("ChowRing"))),
("PushforwardSheaf", cst("CoherentSheaf")),
("TangentBundle", cst("VectorBundle")),
("EulerChar", arrow(cst("CoherentSheaf"), int_ty())),
(
"DTPartitionFunction",
arrow(cst("Scheme"), cst("FormalPowerSeries")),
),
(
"GWPartitionFunction",
arrow(cst("Scheme"), cst("FormalPowerSeries")),
),
("Grassmannian", type0()),
("SchubertClass", type0()),
("Permutation", type0()),
("Polynomial", type0()),
("BlowupScheme", type0()),
("Divisor", type0()),
("BundleMap", type0()),
("BundleSection", type0()),
("ModuliCurvesType", type0()),
("GWPotential", type0()),
("KTheoryClass", type0()),
("K0Ring", arrow(cst("Scheme"), type0())),
("HilbertSchemeType", type0()),
("SymmetricProduct", type0()),
("EulerClass", arrow(cst("VectorBundle"), cst("ChowGroup"))),
];
for (name, ty) in base_types {
env.add(Declaration::Axiom {
name: Name::str(*name),
univ_params: vec![],
ty: ty.clone(),
})
.ok();
}
let type_axioms: &[(&str, fn() -> Expr)] = &[
("chow_group", chow_group_ty),
("chow_ring", chow_ring_ty),
("algebraic_cycle", algebraic_cycle_ty),
("intersection_product", intersection_product_ty),
("pushforward_cycle", pushforward_cycle_ty),
("pullback_cycle", pullback_cycle_ty),
("fundamental_class", fundamental_class_ty),
("bezout_intersection", bezout_intersection_ty),
("chern_class", chern_class_ty),
("total_chern_class", total_chern_class_ty),
("chern_character", chern_character_ty),
("segre_class", segre_class_ty),
("todd_class", todd_class_ty),
("obstruction_theory", obstruction_theory_ty),
("virtual_fundamental_class", virtual_fundamental_class_ty),
("virtual_dimension", virtual_dimension_ty),
("stable_map", stable_map_ty),
("gromov_witten_invariant", gromov_witten_invariant_ty),
("quantum_cohomology", quantum_cohomology_ty),
("quantum_product", quantum_product_ty),
("dt_invariant", dt_invariant_ty),
("schubert_variety", schubert_variety_ty),
("schubert_class", schubert_class_ty),
("pieri_formula", pieri_formula_ty),
("giambelli_formula", giambelli_formula_ty),
("littlewood_richardson", littlewood_richardson_ty),
("grassmannian_chow_ring", grassmannian_chow_ring_ty),
("flag_variety", flag_variety_ty),
("schubert_polynomial", schubert_polynomial_ty),
("blowup", blowup_ty),
("exceptional_divisor", exceptional_divisor_ty),
("blowup_chow_ring_map", blowup_chow_ring_map_ty),
("strict_transform", strict_transform_ty),
("degeneracy_locus", degeneracy_locus_ty),
("euler_class", euler_class_ty),
("moduli_curves", moduli_curves_ty),
("deligne_mumford", deligne_mumford_ty),
("kontsevich_space", kontsevich_space_ty),
("psi_class", psi_class_ty),
("lambda_class", lambda_class_ty),
("motivic_cohomology", motivic_cohomology_ty),
("algebraic_k_theory", algebraic_k_theory_ty),
("chern_character_k_theory", chern_character_k_theory_ty),
("motivic_integration", motivic_integration_ty),
("hilbert_scheme_points", hilbert_scheme_points_ty),
("hilbert_chow", hilbert_chow_ty),
("nakajima_operator", nakajima_operator_ty),
("gottsche_formula", gottsche_formula_ty),
("intersection_multiplicity", intersection_multiplicity_ty),
("polynomial_resultant", polynomial_resultant_ty),
];
for (name, mk_ty) in type_axioms {
let ty = mk_ty();
env.add(Declaration::Axiom {
name: Name::str(*name),
univ_params: vec![],
ty,
})
.ok();
}
let theorem_axioms: &[(&str, fn() -> Expr)] = &[
("bezout_theorem", bezout_theorem_ty),
(
"excess_intersection_formula",
excess_intersection_formula_ty,
),
("whitney_sum_formula", whitney_sum_formula_ty),
("splitting_principle", splitting_principle_ty),
("self_intersection_formula", self_intersection_formula_ty),
("segre_chern_relation", segre_chern_relation_ty),
("grothendieck_riemann_roch", grothendieck_riemann_roch_ty),
("hirzebruch_riemann_roch", hirzebruch_riemann_roch_ty),
("wdvv_equation", wdvv_equation_ty),
("degeneration_formula", degeneration_formula_ty),
("quantum_ring_associativity", quantum_ring_associativity_ty),
("dt_gw_correspondence", dt_gw_correspondence_ty),
("thom_porteous_formula", thom_porteous_formula_ty),
("euler_class_zero_locus", euler_class_zero_locus_ty),
("blowup_formula", blowup_formula_ty),
("virasoro_constraints", virasoro_constraints_ty),
("dilation_equation", dilation_equation_ty),
("atiyah_hirzebruch", atiyah_hirzebruch_ty),
(
"intersection_multiplicity_formula",
intersection_multiplicity_formula_ty,
),
];
for (name, mk_ty) in theorem_axioms {
let ty = mk_ty();
env.add(Declaration::Axiom {
name: Name::str(*name),
univ_params: vec![],
ty,
})
.ok();
}
}
pub fn bezout_number(degrees: &[u64]) -> u64 {
degrees.iter().product()
}
pub fn euler_characteristic_from_betti(betti: &[i64]) -> i64 {
betti
.iter()
.enumerate()
.map(|(i, &b)| if i % 2 == 0 { b } else { -b })
.sum()
}
pub fn projective_line_bundle_degree(n: usize, power: u64) -> u64 {
if power == n as u64 {
1
} else if power > n as u64 {
0
} else {
1
}
}
pub fn intersection_number(c1: &CycleClass, c2: &CycleClass, dim: usize) -> Option<i64> {
if c1.codim + c2.codim == dim {
Some(c1.multiplicity * c2.multiplicity)
} else {
None
}
}
pub fn gw_invariant_pn(n: usize, d: u64, a1: usize, a2: usize, a3: usize) -> i64 {
let lhs = a1 + a2 + a3;
let rhs = n + (n as i64 - 3) as usize * d as usize;
if lhs == rhs && d > 0 {
(d as i64).pow((n as u32).saturating_sub(1))
} else if d == 0 && lhs == n {
1
} else {
0
}
}
pub fn dt_partition_function_coeff(euler_char: i64, degree: usize) -> f64 {
let mut coeff = vec![0.0f64; degree + 1];
coeff[0] = 1.0;
for n in 1..=degree {
for _k in 1..=n {
for j in (n..=degree).rev() {
coeff[j] += coeff[j - n];
}
}
}
let sign: f64 = if euler_char % 2 == 0 { 1.0 } else { -1.0 };
sign * coeff[degree]
}
pub fn todd_class_projective_space(n: usize) -> Vec<f64> {
let n1 = (n + 1) as f64;
let mut td = vec![0.0f64; n + 1];
if n + 1 > 0 {
td[0] = 1.0;
}
if n + 1 > 1 {
td[1] = n1 / 2.0;
}
if n + 1 > 2 {
td[2] = n1 * (n1 + 1.0) / 12.0;
}
if n + 1 > 3 {
td[3] = n1 * n1 * (n1 + 1.0) / 24.0;
}
td
}
pub fn hrr_projective_space(n: usize, d: i64) -> i64 {
if d >= 0 {
binomial(n as i64 + d, n as i64)
} else {
let sign = if n % 2 == 0 { 1 } else { -1 };
sign * hrr_projective_space(n, -(n as i64) - 1 - d)
}
}
pub fn binomial(n: i64, k: i64) -> i64 {
if k < 0 || k > n {
return 0;
}
if k == 0 || k == n {
return 1;
}
let k = k.min(n - k) as usize;
let mut result = 1i64;
for i in 0..k as i64 {
result = result * (n - i) / (i + 1);
}
result
}
#[cfg(test)]
mod tests {
use super::*;
use oxilean_kernel::Environment;
#[test]
fn test_bezout_number() {
assert_eq!(bezout_number(&[2, 2, 2]), 8);
assert_eq!(bezout_number(&[1, 2]), 2);
assert_eq!(bezout_number(&[]), 1);
}
#[test]
fn test_vector_bundle_direct_sum() {
let e = VectorBundleData::line_bundle(1);
let f = VectorBundleData::line_bundle(2);
let ef = e.direct_sum(&f);
assert_eq!(ef.rank, 2);
assert_eq!(ef.chern_numbers[0], 3);
assert_eq!(ef.chern_numbers[1], 2);
}
#[test]
fn test_chern_character_line_bundle() {
let e = VectorBundleData::line_bundle(3);
let ch = e.chern_character_coeffs();
assert_eq!(ch.len(), 3);
assert_eq!(ch[0], 1.0);
assert_eq!(ch[1], 3.0);
assert!((ch[2] - 4.5).abs() < 1e-10);
}
#[test]
fn test_cycle_class_operations() {
let h = CycleClass::new(1, 1, "H");
let h2 = h.scale(2);
assert_eq!(h2.multiplicity, 2);
assert_eq!(h2.codim, 1);
let h3 = CycleClass::new(1, 3, "3H");
let sum = h.add(&h3).expect("add should succeed");
assert_eq!(sum.multiplicity, 4);
let pt = CycleClass::new(2, 1, "pt");
assert!(h.add(&pt).is_none());
}
#[test]
fn test_intersection_number() {
let h = CycleClass::new(1, 1, "H");
let result = intersection_number(&h, &h, 2);
assert_eq!(result, Some(1));
let pt = CycleClass::new(2, 1, "pt");
assert_eq!(intersection_number(&h, &pt, 2), None);
}
#[test]
fn test_hrr_projective_space() {
assert_eq!(hrr_projective_space(2, 0), 1);
assert_eq!(hrr_projective_space(2, 1), 3);
assert_eq!(hrr_projective_space(2, 2), 6);
assert_eq!(hrr_projective_space(1, 3), 4);
}
#[test]
fn test_quantum_cohomology_p2() {
let qh = QuantumCohomologyP2::new(1.0);
let (c1, c_h, c_h2) = qh.quantum_product_h_powers(1, 2);
assert!((c1 - 1.0).abs() < 1e-10);
assert!((c_h).abs() < 1e-10);
assert!((c_h2).abs() < 1e-10);
}
#[test]
fn test_build_intersection_theory_env() {
let mut env = Environment::new();
build_intersection_theory_env(&mut env);
assert!(env.get(&Name::str("chow_group")).is_some());
assert!(env.get(&Name::str("chern_class")).is_some());
assert!(env.get(&Name::str("bezout_theorem")).is_some());
assert!(env.get(&Name::str("grothendieck_riemann_roch")).is_some());
assert!(env.get(&Name::str("wdvv_equation")).is_some());
assert!(env.get(&Name::str("dt_gw_correspondence")).is_some());
assert!(env.get(&Name::str("quantum_product")).is_some());
assert!(env.get(&Name::str("schubert_class")).is_some());
assert!(env.get(&Name::str("pieri_formula")).is_some());
assert!(env.get(&Name::str("giambelli_formula")).is_some());
assert!(env.get(&Name::str("littlewood_richardson")).is_some());
assert!(env.get(&Name::str("grassmannian_chow_ring")).is_some());
assert!(env.get(&Name::str("flag_variety")).is_some());
assert!(env.get(&Name::str("schubert_polynomial")).is_some());
assert!(env.get(&Name::str("blowup")).is_some());
assert!(env.get(&Name::str("exceptional_divisor")).is_some());
assert!(env.get(&Name::str("strict_transform")).is_some());
assert!(env.get(&Name::str("blowup_formula")).is_some());
assert!(env.get(&Name::str("degeneracy_locus")).is_some());
assert!(env.get(&Name::str("thom_porteous_formula")).is_some());
assert!(env.get(&Name::str("euler_class")).is_some());
assert!(env.get(&Name::str("deligne_mumford")).is_some());
assert!(env.get(&Name::str("kontsevich_space")).is_some());
assert!(env.get(&Name::str("psi_class")).is_some());
assert!(env.get(&Name::str("lambda_class")).is_some());
assert!(env.get(&Name::str("virasoro_constraints")).is_some());
assert!(env.get(&Name::str("motivic_cohomology")).is_some());
assert!(env.get(&Name::str("algebraic_k_theory")).is_some());
assert!(env.get(&Name::str("atiyah_hirzebruch")).is_some());
assert!(env.get(&Name::str("hilbert_scheme_points")).is_some());
assert!(env.get(&Name::str("nakajima_operator")).is_some());
assert!(env.get(&Name::str("gottsche_formula")).is_some());
assert!(env.get(&Name::str("intersection_multiplicity")).is_some());
assert!(env.get(&Name::str("polynomial_resultant")).is_some());
}
#[test]
fn test_todd_class_projective_space() {
let td = todd_class_projective_space(2);
assert!((td[0] - 1.0).abs() < 1e-10);
assert!((td[1] - 1.5).abs() < 1e-10);
}
#[test]
fn test_chow_ring_elem_arithmetic() {
let h = ChowRingElem::hyperplane(2);
let h2 = h.mul(&h).expect("mul should succeed");
assert_eq!(h2.coeffs, vec![0, 0, 1]);
let h3 = h2.mul(&h).expect("mul should succeed");
assert_eq!(h3.degree(), 0);
let one = ChowRingElem::one(2);
let one_plus_h = one.add(&h).expect("add should succeed");
assert_eq!(one_plus_h.coeffs[0], 1);
assert_eq!(one_plus_h.coeffs[1], 1);
}
#[test]
fn test_intersection_matrix() {
let mat = IntersectionMatrix::new(vec![vec![-1]]);
assert_eq!(mat.self_intersections(), vec![-1]);
assert_eq!(mat.determinant(), Some(-1));
let mat2 = IntersectionMatrix::new(vec![vec![-2, 1], vec![1, -2]]);
assert_eq!(mat2.determinant(), Some(3));
assert!(mat2.is_negative_definite());
}
#[test]
fn test_schubert_calc_grassmannian() {
let calc = SchubertCalc::new(2, 4);
assert_eq!(calc.dim(), 4);
assert!(calc.is_valid_partition(&[2, 1]));
assert!(calc.is_valid_partition(&[1]));
assert!(!calc.is_valid_partition(&[3]));
assert_eq!(calc.degree(), 2);
}
#[test]
fn test_bezout_bound() {
let b = BezoutBound::new(vec![2, 3, 4]);
assert_eq!(b.bound(), 24);
assert_eq!(b.mixed_bound(&[0, 1]), 6);
assert!(b.is_overdetermined(2));
assert!(!b.is_overdetermined(3));
assert!(b.is_underdetermined(4));
}
#[test]
fn test_vector_bundle_euler_and_todd() {
let e = VectorBundleData::line_bundle(3);
assert_eq!(e.euler_class(), 3);
let td = e.todd_class_coeffs();
assert!((td[0] - 1.0).abs() < 1e-10);
assert!((td[1] - 1.5).abs() < 1e-10);
}
}
pub fn it_ext_chow_group_hom_ty() -> Expr {
arrow(cst("ChowGroup"), arrow(cst("ChowGroup"), prop()))
}
pub fn it_ext_chow_ring_iso_ty() -> Expr {
arrow(cst("ChowRing"), arrow(cst("ChowRing"), prop()))
}
pub fn it_ext_cycle_map_ty() -> Expr {
arrow(
cst("Scheme"),
arrow(cst("MotivicCohomology"), cst("ChowGroup")),
)
}
pub fn it_ext_rational_equiv_class_ty() -> Expr {
arrow(cst("AlgebraicCycle"), cst("ChowGroup"))
}
pub fn it_ext_numerical_equivalence_ty() -> Expr {
arrow(cst("AlgebraicCycle"), arrow(cst("AlgebraicCycle"), prop()))
}
pub fn it_ext_homological_equivalence_ty() -> Expr {
arrow(cst("AlgebraicCycle"), arrow(cst("AlgebraicCycle"), prop()))
}
pub fn it_ext_proper_pushforward_ty() -> Expr {
arrow(cst("Morphism"), arrow(cst("ChowGroup"), cst("ChowGroup")))
}
pub fn it_ext_flat_pullback_ty() -> Expr {
arrow(cst("Morphism"), arrow(cst("ChowGroup"), cst("ChowGroup")))
}
pub fn it_ext_lci_pullback_ty() -> Expr {
arrow(cst("Morphism"), arrow(cst("ChowGroup"), cst("ChowGroup")))
}
pub fn it_ext_projection_formula_ty() -> Expr {
arrow(
cst("Morphism"),
arrow(
cst("ChowGroup"),
arrow(
cst("ChowGroup"),
app2(cst("Eq"), cst("ChowGroup"), cst("ChowGroup")),
),
),
)
}
pub fn it_ext_degree_of_map_ty() -> Expr {
arrow(cst("Morphism"), nat_ty())
}
pub fn it_ext_chern_class_funct_ty() -> Expr {
arrow(
cst("Morphism"),
arrow(
cst("VectorBundle"),
app2(cst("Eq"), cst("ChowGroup"), cst("ChowGroup")),
),
)
}
pub fn it_ext_chern_root_decomp_ty() -> Expr {
arrow(cst("VectorBundle"), arrow(nat_ty(), cst("ChowGroup")))
}
pub fn it_ext_grothendieck_group_ty() -> Expr {
arrow(cst("Scheme"), type0())
}
pub fn it_ext_adams_operation_ty() -> Expr {
arrow(cst("KTheoryClass"), arrow(nat_ty(), cst("KTheoryClass")))
}
pub fn it_ext_riemann_roch_transform_ty() -> Expr {
arrow(
cst("Morphism"),
arrow(
cst("CoherentSheaf"),
app2(cst("Eq"), cst("ChowRing"), cst("ChowRing")),
),
)
}
pub fn it_ext_lefschetz_number_ty() -> Expr {
arrow(cst("Morphism"), int_ty())
}
pub fn it_ext_lefschetz_fpt_ty() -> Expr {
arrow(
cst("Morphism"),
arrow(app2(cst("Eq"), int_ty(), int_ty()), prop()),
)
}
pub fn it_ext_riemann_hurwitz_ty() -> Expr {
arrow(cst("Morphism"), arrow(nat_ty(), arrow(nat_ty(), prop())))
}
pub fn it_ext_zeta_function_ty() -> Expr {
arrow(cst("Scheme"), cst("FormalPowerSeries"))
}
pub fn it_ext_weil_conjectures_ty() -> Expr {
arrow(cst("Scheme"), prop())
}
pub fn it_ext_kontsevich_formula_ty() -> Expr {
arrow(nat_ty(), nat_ty())
}
pub fn it_ext_quantum_frobenius_ty() -> Expr {
arrow(cst("QuantumCohomology"), prop())
}
pub fn it_ext_mirror_symmetry_ty() -> Expr {
arrow(cst("Scheme"), arrow(cst("Scheme"), prop()))
}
pub fn it_ext_topological_vertex_ty() -> Expr {
arrow(
cst("Partition"),
arrow(cst("Partition"), arrow(cst("Partition"), int_ty())),
)
}
pub fn it_ext_gw_potential_genus0_ty() -> Expr {
arrow(cst("Scheme"), arrow(list_ty(real_ty()), real_ty()))
}
pub fn it_ext_string_equation_ty() -> Expr {
arrow(cst("GWPotential"), prop())
}
pub fn it_ext_perfect_obstruction_ty() -> Expr {
arrow(cst("Scheme"), arrow(cst("Morphism"), type0()))
}
pub fn it_ext_virtual_normal_bundle_ty() -> Expr {
arrow(cst("ObstructionTheory"), cst("VectorBundle"))
}
pub fn it_ext_virtual_pushforward_ty() -> Expr {
arrow(cst("ObstructionTheory"), arrow(cst("ChowGroup"), int_ty()))
}
pub fn it_ext_deformation_invariance_ty() -> Expr {
arrow(cst("ObstructionTheory"), prop())
}
pub fn it_ext_schur_determinant_ty() -> Expr {
arrow(
cst("Partition"),
arrow(
cst("VectorBundle"),
arrow(cst("VectorBundle"), cst("ChowGroup")),
),
)
}
pub fn it_ext_grassmann_bundle_formula_ty() -> Expr {
arrow(
cst("Scheme"),
arrow(cst("VectorBundle"), arrow(nat_ty(), cst("ChowRing"))),
)
}
pub fn it_ext_projective_bundle_formula_ty() -> Expr {
arrow(cst("Scheme"), arrow(cst("VectorBundle"), cst("ChowRing")))
}
pub fn it_ext_motivic_spectral_seq_ty() -> Expr {
arrow(cst("Scheme"), arrow(nat_ty(), arrow(nat_ty(), type0())))
}
pub fn it_ext_bloch_ogus_ty() -> Expr {
arrow(cst("Scheme"), arrow(nat_ty(), type0()))
}
pub fn it_ext_gersten_resolution_ty() -> Expr {
arrow(cst("Scheme"), type0())
}
pub fn it_ext_milnor_k_theory_ty() -> Expr {
arrow(cst("Scheme"), arrow(nat_ty(), type0()))
}
pub fn register_intersection_theory_extended(env: &mut Environment) -> Result<(), String> {
let extra_types: &[(&str, Expr)] = &[("MotivicCohomology", type0()), ("Frobenius", type0())];
for (name, ty) in extra_types {
env.add(Declaration::Axiom {
name: Name::str(*name),
univ_params: vec![],
ty: ty.clone(),
})
.ok();
}
let axioms: &[(&str, fn() -> Expr)] = &[
("ChowGroupHom", it_ext_chow_group_hom_ty),
("ChowRingIso", it_ext_chow_ring_iso_ty),
("CycleMap", it_ext_cycle_map_ty),
("RationalEquivClass", it_ext_rational_equiv_class_ty),
("NumericalEquivalence", it_ext_numerical_equivalence_ty),
("HomologicalEquivalence", it_ext_homological_equivalence_ty),
("ProperPushforward", it_ext_proper_pushforward_ty),
("FlatPullback", it_ext_flat_pullback_ty),
("LciPullback", it_ext_lci_pullback_ty),
("ProjectionFormula", it_ext_projection_formula_ty),
("DegreeOfMap", it_ext_degree_of_map_ty),
("ChernClassFunct", it_ext_chern_class_funct_ty),
("ChernRootDecomp", it_ext_chern_root_decomp_ty),
("GrothendieckGroupExt", it_ext_grothendieck_group_ty),
("AdamsOperation", it_ext_adams_operation_ty),
("RiemannRochTransform", it_ext_riemann_roch_transform_ty),
("LefschetzNumber", it_ext_lefschetz_number_ty),
("LefschetzFpt", it_ext_lefschetz_fpt_ty),
("RiemannHurwitz", it_ext_riemann_hurwitz_ty),
("ZetaFunction", it_ext_zeta_function_ty),
("WeilConjectures", it_ext_weil_conjectures_ty),
("KontsevichFormula", it_ext_kontsevich_formula_ty),
("QuantumFrobenius", it_ext_quantum_frobenius_ty),
("MirrorSymmetry", it_ext_mirror_symmetry_ty),
("TopologicalVertex", it_ext_topological_vertex_ty),
("GwPotentialGenus0", it_ext_gw_potential_genus0_ty),
("StringEquation", it_ext_string_equation_ty),
("PerfectObstruction", it_ext_perfect_obstruction_ty),
("VirtualNormalBundle", it_ext_virtual_normal_bundle_ty),
("VirtualPushforward", it_ext_virtual_pushforward_ty),
("DeformationInvariance", it_ext_deformation_invariance_ty),
("SchurDeterminant", it_ext_schur_determinant_ty),
("GrassmannBundleFormula", it_ext_grassmann_bundle_formula_ty),
(
"ProjectiveBundleFormula",
it_ext_projective_bundle_formula_ty,
),
("MotivicSpectralSeq", it_ext_motivic_spectral_seq_ty),
("BlochOgus", it_ext_bloch_ogus_ty),
("GerstenResolution", it_ext_gersten_resolution_ty),
("MilnorKTheory", it_ext_milnor_k_theory_ty),
];
for (name, mk_ty) in axioms {
let ty = mk_ty();
env.add(Declaration::Axiom {
name: Name::str(*name),
univ_params: vec![],
ty,
})
.ok();
}
Ok(())
}
pub fn kontsevich_nd(d: usize) -> u64 {
if d == 1 {
return 1;
}
let mut n = vec![0u64; d + 1];
n[1] = 1;
for dd in 2..=d {
let mut sum = 0u64;
for d1 in 1..dd {
let d2 = dd - d1;
let d1u = d1 as u64;
let d2u = d2 as u64;
let top = 3 * dd - 4;
let c1 = binomial_u64(top as i64, (3 * d1 - 2) as i64);
let c2 = if 3 * d1 >= 1 {
binomial_u64(top as i64, (3 * d1 - 1) as i64)
} else {
0
};
let term1 = n[d1]
.saturating_mul(n[d2])
.saturating_mul(d1u * d1u)
.saturating_mul(d2u * d2u)
.saturating_mul(c1);
let term2 = n[d1]
.saturating_mul(n[d2])
.saturating_mul(d1u * d1u * d1u)
.saturating_mul(d2u)
.saturating_mul(c2);
sum = sum.saturating_add(term1).saturating_sub(term2.min(sum));
}
n[dd] = sum;
}
n[d]
}
pub fn binomial_u64(n: i64, k: i64) -> u64 {
if k < 0 || k > n || n < 0 {
return 0;
}
let k = k.min(n - k) as usize;
let mut result = 1u64;
for i in 0..k as i64 {
result = result.saturating_mul((n - i) as u64) / (i as u64 + 1);
}
result
}
pub fn whitney_sum_chern(c_e: &[i64], c_f: &[i64]) -> Vec<i64> {
let deg = c_e.len() + c_f.len() - 1;
let mut result = vec![0i64; deg];
for (i, &a) in c_e.iter().enumerate() {
for (j, &b) in c_f.iter().enumerate() {
result[i + j] += a * b;
}
}
result
}
pub fn segre_class_from_chern(c: &[i64], max_terms: usize) -> Vec<i64> {
let mut s = vec![0i64; max_terms];
if max_terms == 0 {
return s;
}
s[0] = 1;
for k in 1..max_terms {
let mut val = 0i64;
for j in 1..=k {
if j < c.len() {
val += c[j] * s[k - j];
}
}
s[k] = -val;
}
s
}
pub fn chern_character_from_classes(c: &[i64]) -> Vec<f64> {
let c1 = c.get(1).copied().unwrap_or(0) as f64;
let c2 = c.get(2).copied().unwrap_or(0) as f64;
let c3 = c.get(3).copied().unwrap_or(0) as f64;
let rank = c.first().copied().unwrap_or(1) as f64;
vec![
rank,
c1,
(c1 * c1 - 2.0 * c2) / 2.0,
(c1 * c1 * c1 - 3.0 * c1 * c2 + 3.0 * c3) / 6.0,
]
}
pub fn it_binomial(n: i64, k: i64) -> i64 {
if k < 0 || k > n || n < 0 {
return 0;
}
let k = k.min(n - k) as usize;
let mut result = 1i64;
for i in 0..k as i64 {
result = result * (n - i) / (i + 1);
}
result
}