use oxilean_kernel::{BinderInfo, Declaration, Environment, Expr, Level, Name};
use super::types::{
AbundanceData, BlowUpData, ContractionType, ExtremeRay, IitakaFibration, KVVanishingData,
KodairaDim, LogPair, LogPairData, MMPOperation, MMPStepData, MmpFlowchart, MmpStep, MoriCone,
SarkisovLinkType, SingularityType, ZariskiDecomp,
};
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 function_field_ty() -> Expr {
arrow(cst("Variety"), cst("Field"))
}
pub fn rational_map_ty() -> Expr {
arrow(cst("Variety"), arrow(cst("Variety"), type0()))
}
pub fn birational_equiv_ty() -> Expr {
arrow(cst("Variety"), arrow(cst("Variety"), prop()))
}
pub fn birational_equiv_iff_function_fields_ty() -> Expr {
arrow(
cst("Variety"),
arrow(
cst("Variety"),
app2(
cst("Iff"),
app2(cst("BiratEquiv"), bvar(1), bvar(0)),
app2(
cst("FieldIso"),
app(cst("FunctionField"), bvar(1)),
app(cst("FunctionField"), bvar(0)),
),
),
),
)
}
pub fn luroth_theorem_ty() -> Expr {
arrow(
cst("Field"),
arrow(cst("Field"), arrow(cst("Field"), prop())),
)
}
pub fn resolution_ty() -> Expr {
arrow(cst("Variety"), cst("Morphism"))
}
pub fn hironaka_resolution_ty() -> Expr {
arrow(
cst("Variety"),
arrow(
prop(),
arrow(
cst("Morphism"),
app2(
cst("And"),
app(cst("IsSmooth"), bvar(0)),
app(cst("IsBirational"), bvar(0)),
),
),
),
)
}
pub fn embedded_resolution_ty() -> Expr {
arrow(
cst("Variety"),
arrow(
cst("ClosedSubscheme"),
arrow(
cst("Morphism"),
app2(
cst("And"),
app(cst("IsSmooth"), cst("BlownUp")),
app(cst("IsNormalCrossing"), cst("ExceptionalPreimage")),
),
),
),
)
}
pub fn blow_up_ty() -> Expr {
arrow(cst("Variety"), arrow(cst("Subscheme"), cst("Variety")))
}
pub fn exceptional_divisor_ty() -> Expr {
arrow(cst("BlowUpData"), cst("Divisor"))
}
pub fn blow_up_projective_bundle_ty() -> Expr {
arrow(
cst("Variety"),
arrow(
cst("Subscheme"),
arrow(
nat_ty(),
app(cst("IsProjBundle"), cst("ExceptionalDivisor")),
),
),
)
}
pub fn normal_bundle_exceptional_ty() -> Expr {
arrow(
cst("BlowUpData"),
app2(
cst("Iso"),
app(cst("NormalBundle"), cst("ExceptionalDivisor")),
app(cst("Tautological"), cst("ExceptionalDivisor")),
),
)
}
pub fn blow_up_chow_ring_ty() -> Expr {
arrow(
cst("Variety"),
arrow(
cst("Subscheme"),
app2(cst("Iso"), cst("ChowRing"), cst("BlowUpChowRing")),
),
)
}
pub fn canonical_divisor_ty() -> Expr {
arrow(cst("SmoothVariety"), cst("Divisor"))
}
pub fn discrepancy_ty() -> Expr {
arrow(cst("LogPair"), arrow(cst("Divisor"), cst("Rat")))
}
pub fn is_klt_ty() -> Expr {
arrow(cst("LogPair"), prop())
}
pub fn is_dlt_ty() -> Expr {
arrow(cst("LogPair"), prop())
}
pub fn is_lc_ty() -> Expr {
arrow(cst("LogPair"), prop())
}
pub fn adjunction_formula_ty() -> Expr {
arrow(
cst("LogPair"),
arrow(
cst("Divisor"),
app2(cst("Eq"), cst("Divisor"), cst("RestrictedKanDiv")),
),
)
}
pub fn extremal_ray_ty() -> Expr {
arrow(cst("Variety"), cst("NECurve"))
}
pub fn contraction_morphism_ty() -> Expr {
arrow(cst("NECurve"), cst("Morphism"))
}
pub fn mori_cone_theorem_ty() -> Expr {
arrow(
cst("Variety"),
arrow(
prop(),
app2(cst("Eq"), cst("NECone"), cst("SumExtremalRays")),
),
)
}
pub fn base_point_free_theorem_ty() -> Expr {
arrow(cst("LogPair"), arrow(prop(), arrow(nat_ty(), prop())))
}
pub fn kawamata_viehweg_vanishing_ty() -> Expr {
arrow(
cst("SmoothVariety"),
arrow(
cst("Divisor"),
arrow(
prop(),
arrow(nat_ty(), app2(cst("Eq"), type0(), cst("ZeroModule"))),
),
),
)
}
pub fn flip_ty() -> Expr {
arrow(cst("LogPair"), cst("LogPair"))
}
pub fn flop_ty() -> Expr {
arrow(cst("Variety"), cst("Variety"))
}
pub fn divisorial_contraction_ty() -> Expr {
arrow(cst("LogPair"), cst("Morphism"))
}
pub fn flip_existence_ty() -> Expr {
arrow(
cst("LogPair"),
arrow(
cst("Morphism"),
arrow(prop(), arrow(cst("LogPair"), prop())),
),
)
}
pub fn flop_symmetry_ty() -> Expr {
arrow(
cst("Variety"),
arrow(
cst("Variety"),
app2(cst("And"), cst("KNumericallyTrivial"), cst("DerivedEquiv")),
),
)
}
pub fn flop_terminates_ty() -> Expr {
arrow(cst("LogPair"), prop())
}
pub fn kodaira_dimension_ty() -> Expr {
arrow(cst("Variety"), int_ty())
}
pub fn iitaka_fibration_ty() -> Expr {
arrow(cst("Variety"), cst("Morphism"))
}
pub fn kodaira_dim_additive_ty() -> Expr {
arrow(
cst("Variety"),
arrow(
cst("Variety"),
app2(
cst("Eq"),
int_ty(),
app(
cst("KodairaDimension"),
app2(cst("Product"), bvar(1), bvar(0)),
),
),
),
)
}
pub fn castelnuovo_mumford_regularity_ty() -> Expr {
arrow(cst("CoherentSheaf"), int_ty())
}
pub fn is_fano_ty() -> Expr {
arrow(cst("Variety"), prop())
}
pub fn fano_index_ty() -> Expr {
arrow(cst("FanoVariety"), nat_ty())
}
pub fn del_pezzo_surface_ty() -> Expr {
arrow(nat_ty(), cst("Variety"))
}
pub fn kobayashi_ochiai_ty() -> Expr {
arrow(
cst("FanoVariety"),
arrow(prop(), app2(cst("Iso"), bvar(1), cst("ProjectiveSpace"))),
)
}
pub fn mori_mukai_classification_ty() -> Expr {
arrow(cst("FanoVariety"), arrow(nat_ty(), prop()))
}
pub fn log_minimal_model_ty() -> Expr {
arrow(cst("LogPair"), cst("LogPair"))
}
pub fn abundance_conjecture_ty() -> Expr {
arrow(cst("LogPair"), arrow(prop(), arrow(prop(), prop())))
}
pub fn bchm_theorem_ty() -> Expr {
arrow(cst("LogPair"), arrow(prop(), arrow(cst("LogPair"), prop())))
}
pub fn non_vanishing_theorem_ty() -> Expr {
arrow(cst("LogPair"), arrow(prop(), arrow(prop(), prop())))
}
pub fn cone_theorem_ty() -> Expr {
arrow(
cst("LogPair"),
arrow(
prop(),
app2(cst("Eq"), cst("NECone"), cst("SumExtremalRaysKNeg")),
),
)
}
pub fn contraction_theorem_ty() -> Expr {
arrow(cst("Variety"), arrow(cst("NECurve"), cst("Morphism")))
}
pub fn mori_fiber_space_ty() -> Expr {
arrow(cst("Variety"), arrow(cst("Variety"), prop()))
}
pub fn rationality_theorem_ty() -> Expr {
arrow(
cst("SmoothVariety"),
arrow(
cst("NECurve"),
app2(cst("Le"), cst("RayLength"), cst("RayBound")),
),
)
}
pub fn is_terminal_singularity_ty() -> Expr {
arrow(cst("Variety"), prop())
}
pub fn is_canonical_singularity_ty() -> Expr {
arrow(cst("Variety"), prop())
}
pub fn terminal_implies_canonical_ty() -> Expr {
arrow(
cst("Variety"),
arrow(
app(cst("IsTerminal"), bvar(0)),
app(cst("IsCanonical"), bvar(1)),
),
)
}
pub fn is_klt_singularity_ty() -> Expr {
arrow(cst("LogPair"), prop())
}
pub fn is_log_canonical_pair_ty() -> Expr {
arrow(cst("LogPair"), prop())
}
pub fn kodaira_surface_classification_ty() -> Expr {
arrow(
cst("SmoothVariety"),
arrow(prop(), app(cst("KodairaDimInRange"), bvar(1))),
)
}
pub fn is_curve_ty() -> Expr {
arrow(cst("Variety"), prop())
}
pub fn is_rational_surface_ty() -> Expr {
arrow(cst("Variety"), prop())
}
pub fn is_k3_surface_ty() -> Expr {
arrow(cst("Variety"), prop())
}
pub fn is_enriques_surface_ty() -> Expr {
arrow(cst("Variety"), prop())
}
pub fn is_general_type_surface_ty() -> Expr {
arrow(cst("Variety"), prop())
}
pub fn is_ruled_surface_ty() -> Expr {
arrow(cst("Variety"), prop())
}
pub fn castelnuovo_rationality_ty() -> Expr {
arrow(
cst("SmoothVariety"),
arrow(prop(), arrow(prop(), app(cst("IsRational"), bvar(2)))),
)
}
pub fn is_minimal_surface_ty() -> Expr {
arrow(cst("Variety"), prop())
}
pub fn grauert_riemenschneider_vanishing_ty() -> Expr {
arrow(
cst("SmoothVariety"),
arrow(cst("Morphism"), arrow(nat_ty(), prop())),
)
}
pub fn kodaira_vanishing_ty() -> Expr {
arrow(
cst("SmoothVariety"),
arrow(cst("Divisor"), arrow(prop(), arrow(nat_ty(), prop()))),
)
}
pub fn nadel_vanishing_ty() -> Expr {
arrow(
cst("Variety"),
arrow(cst("Divisor"), arrow(prop(), arrow(nat_ty(), prop()))),
)
}
pub fn zariski_decomposition_ty() -> Expr {
arrow(
cst("Divisor"),
app2(cst("Prod"), cst("Divisor"), cst("Divisor")),
)
}
pub fn zariski_decomposition_uniqueness_ty() -> Expr {
arrow(cst("Divisor"), arrow(prop(), prop()))
}
pub fn sarkisov_link_ty() -> Expr {
arrow(cst("MoriModel"), arrow(cst("MoriModel"), nat_ty()))
}
pub fn sarkisov_program_ty() -> Expr {
arrow(
cst("MoriModel"),
arrow(cst("MoriModel"), arrow(prop(), prop())),
)
}
pub fn is_rationally_connected_ty() -> Expr {
arrow(cst("Variety"), prop())
}
pub fn is_non_uniruled_ty() -> Expr {
arrow(cst("Variety"), prop())
}
pub fn miyaoka_mori_theorem_ty() -> Expr {
arrow(
cst("SmoothVariety"),
arrow(prop(), app(cst("IsUniruled"), bvar(1))),
)
}
pub fn rationally_connected_implies_fano_type_ty() -> Expr {
arrow(
cst("Variety"),
arrow(
app(cst("IsRationallyConnected"), bvar(0)),
app2(cst("Eq"), int_ty(), app(cst("KodairaDimension"), bvar(1))),
),
)
}
pub fn bogomolov_miyaoka_yau_ty() -> Expr {
arrow(
cst("SmoothVariety"),
arrow(
prop(),
app2(
cst("Le"),
app(cst("ChernNumberSq"), bvar(1)),
app(cst("ChernNumberTwo"), bvar(1)),
),
),
)
}
pub fn noether_inequality_ty() -> Expr {
arrow(cst("SmoothVariety"), arrow(prop(), prop()))
}
pub fn is_mori_dream_space_ty() -> Expr {
arrow(cst("Variety"), prop())
}
pub fn cox_ring_ty() -> Expr {
arrow(cst("Variety"), cst("Ring"))
}
pub fn mori_dream_space_mmp_ty() -> Expr {
arrow(
cst("Variety"),
arrow(app(cst("IsMoriDreamSpace"), bvar(0)), prop()),
)
}
pub fn fano_is_mori_dream_space_ty() -> Expr {
arrow(cst("FanoVariety"), app(cst("IsMoriDreamSpace"), bvar(0)))
}
pub fn flip_termination_bchm_ty() -> Expr {
arrow(cst("LogPair"), arrow(prop(), prop()))
}
pub fn special_termination_ty() -> Expr {
arrow(cst("LogPair"), arrow(prop(), prop()))
}
pub fn is_flipping_ty() -> Expr {
arrow(cst("Morphism"), prop())
}
pub fn is_flopping_ty() -> Expr {
arrow(cst("Morphism"), prop())
}
pub fn relative_mmp_ty() -> Expr {
arrow(
cst("LogPair"),
arrow(cst("Morphism"), arrow(prop(), cst("LogPair"))),
)
}
pub fn build_birational_geometry_env(env: &mut Environment) {
let base_types: &[(&str, Expr)] = &[
("Variety", type1()),
("SmoothVariety", type1()),
("FanoVariety", type1()),
("Field", type0()),
("Divisor", type0()),
("NECurve", type0()),
("NECone", type0()),
("SumExtremalRays", cst("NECone")),
("SumExtremalRaysKNeg", cst("NECone")),
("Morphism", type0()),
("Subscheme", type0()),
("ClosedSubscheme", type0()),
("BlowUpData", type0()),
("LogPair", type0()),
("Rat", type0()),
("ChowRing", type0()),
("BlowUpChowRing", type0()),
("CoherentSheaf", type0()),
("ZeroModule", type0()),
("DerivedEquiv", prop()),
("KNumericallyTrivial", prop()),
("ExceptionalDivisor", cst("Divisor")),
("ExceptionalPreimage", cst("Divisor")),
("BlownUp", cst("Variety")),
("RestrictedKanDiv", cst("Divisor")),
("Nat", type0()),
("Int", type0()),
("Real", type0()),
("Bool", type0()),
("Ring", type0()),
("MoriModel", type0()),
("RayLength", nat_ty()),
("RayBound", nat_ty()),
("Eq", arrow(type0(), arrow(type0(), prop()))),
("Le", arrow(nat_ty(), arrow(nat_ty(), prop()))),
("And", arrow(prop(), arrow(prop(), prop()))),
("Iff", arrow(prop(), arrow(prop(), prop()))),
("Iso", arrow(type0(), arrow(type0(), prop()))),
("Prod", arrow(type0(), arrow(type0(), type0()))),
("FieldIso", arrow(cst("Field"), arrow(cst("Field"), prop()))),
(
"BiratEquiv",
arrow(cst("Variety"), arrow(cst("Variety"), prop())),
),
("FunctionField", arrow(cst("Variety"), cst("Field"))),
("IsSmooth", arrow(cst("Morphism"), prop())),
("IsBirational", arrow(cst("Morphism"), prop())),
("IsNormalCrossing", arrow(cst("Divisor"), prop())),
("IsProjBundle", arrow(cst("Divisor"), prop())),
("Tautological", arrow(cst("Divisor"), type0())),
("NormalBundle", arrow(cst("Divisor"), type0())),
(
"Product",
arrow(cst("Variety"), arrow(cst("Variety"), cst("Variety"))),
),
("KodairaDimension", arrow(cst("Variety"), int_ty())),
("ProjectiveSpace", cst("Variety")),
("List", arrow(type0(), type0())),
("IsTerminal", arrow(cst("Variety"), prop())),
("IsCanonical", arrow(cst("Variety"), prop())),
("KodairaDimInRange", arrow(cst("Variety"), prop())),
("IsRational", arrow(cst("Variety"), prop())),
("IsUniruled", arrow(cst("Variety"), prop())),
("IsRationallyConnected", arrow(cst("Variety"), prop())),
("IsMoriDreamSpace", arrow(cst("Variety"), prop())),
("CoxRing", arrow(cst("Variety"), cst("Ring"))),
("ChernNumberSq", arrow(cst("Variety"), nat_ty())),
("ChernNumberTwo", arrow(cst("Variety"), nat_ty())),
];
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)] = &[
("function_field", function_field_ty),
("rational_map", rational_map_ty),
("birational_equiv", birational_equiv_ty),
("resolution", resolution_ty),
("blow_up", blow_up_ty),
("exceptional_divisor", exceptional_divisor_ty),
("canonical_divisor", canonical_divisor_ty),
("discrepancy", discrepancy_ty),
("is_klt", is_klt_ty),
("is_dlt", is_dlt_ty),
("is_lc", is_lc_ty),
("extremal_ray", extremal_ray_ty),
("contraction_morphism", contraction_morphism_ty),
("flip", flip_ty),
("flop", flop_ty),
("divisorial_contraction", divisorial_contraction_ty),
("kodaira_dimension", kodaira_dimension_ty),
("iitaka_fibration", iitaka_fibration_ty),
(
"castelnuovo_mumford_regularity",
castelnuovo_mumford_regularity_ty,
),
("is_fano", is_fano_ty),
("fano_index", fano_index_ty),
("del_pezzo_surface", del_pezzo_surface_ty),
("log_minimal_model", log_minimal_model_ty),
("mori_fiber_space", mori_fiber_space_ty),
("is_terminal_singularity", is_terminal_singularity_ty),
("is_canonical_singularity", is_canonical_singularity_ty),
("is_klt_singularity", is_klt_singularity_ty),
("is_log_canonical_pair", is_log_canonical_pair_ty),
("is_curve", is_curve_ty),
("is_rational_surface", is_rational_surface_ty),
("is_k3_surface", is_k3_surface_ty),
("is_enriques_surface", is_enriques_surface_ty),
("is_general_type_surface", is_general_type_surface_ty),
("is_ruled_surface", is_ruled_surface_ty),
("is_minimal_surface", is_minimal_surface_ty),
("zariski_decomposition", zariski_decomposition_ty),
("sarkisov_link", sarkisov_link_ty),
("is_rationally_connected", is_rationally_connected_ty),
("is_non_uniruled", is_non_uniruled_ty),
("is_mori_dream_space", is_mori_dream_space_ty),
("cox_ring", cox_ring_ty),
("is_flipping", is_flipping_ty),
("is_flopping", is_flopping_ty),
("relative_mmp", relative_mmp_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)] = &[
(
"birational_equiv_iff_function_fields",
birational_equiv_iff_function_fields_ty,
),
("luroth_theorem", luroth_theorem_ty),
("hironaka_resolution", hironaka_resolution_ty),
("embedded_resolution", embedded_resolution_ty),
("blow_up_projective_bundle", blow_up_projective_bundle_ty),
("normal_bundle_exceptional", normal_bundle_exceptional_ty),
("blow_up_chow_ring", blow_up_chow_ring_ty),
("adjunction_formula", adjunction_formula_ty),
("mori_cone_theorem", mori_cone_theorem_ty),
("base_point_free_theorem", base_point_free_theorem_ty),
("kawamata_viehweg_vanishing", kawamata_viehweg_vanishing_ty),
("flip_existence", flip_existence_ty),
("flop_symmetry", flop_symmetry_ty),
("flop_terminates", flop_terminates_ty),
("kodaira_dim_additive", kodaira_dim_additive_ty),
("kobayashi_ochiai", kobayashi_ochiai_ty),
("mori_mukai_classification", mori_mukai_classification_ty),
("abundance_conjecture", abundance_conjecture_ty),
("bchm_theorem", bchm_theorem_ty),
("non_vanishing_theorem", non_vanishing_theorem_ty),
("cone_theorem", cone_theorem_ty),
("contraction_theorem", contraction_theorem_ty),
("rationality_theorem", rationality_theorem_ty),
("terminal_implies_canonical", terminal_implies_canonical_ty),
(
"kodaira_surface_classification",
kodaira_surface_classification_ty,
),
("castelnuovo_rationality", castelnuovo_rationality_ty),
(
"grauert_riemenschneider_vanishing",
grauert_riemenschneider_vanishing_ty,
),
("kodaira_vanishing", kodaira_vanishing_ty),
("nadel_vanishing", nadel_vanishing_ty),
(
"zariski_decomposition_uniqueness",
zariski_decomposition_uniqueness_ty,
),
("sarkisov_program", sarkisov_program_ty),
("miyaoka_mori_theorem", miyaoka_mori_theorem_ty),
(
"rationally_connected_implies_fano_type",
rationally_connected_implies_fano_type_ty,
),
("bogomolov_miyaoka_yau", bogomolov_miyaoka_yau_ty),
("noether_inequality", noether_inequality_ty),
("mori_dream_space_mmp", mori_dream_space_mmp_ty),
("fano_is_mori_dream_space", fano_is_mori_dream_space_ty),
("flip_termination_bchm", flip_termination_bchm_ty),
("special_termination", special_termination_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 discrepancy_smooth_blowup(codim: usize, boundary_coeff: f64) -> f64 {
let r = codim as f64;
r - 1.0 - boundary_coeff * (r - 1.0)
}
pub fn log_canonical_threshold(ambient_dim: usize, multiplicity: usize) -> f64 {
if multiplicity == 0 {
return f64::INFINITY;
}
f64::min(1.0, ambient_dim as f64 / multiplicity as f64)
}
pub fn kodaira_dim_product(kx: i64, ky: i64) -> i64 {
match (kx, ky) {
(-1, _) | (_, -1) => -1,
(a, b) => a + b,
}
}
pub fn classify_kodaira_dim(kappa: i64, dim: usize) -> &'static str {
if kappa < 0 {
"uniruled (κ = -∞)"
} else if kappa == 0 {
"Calabi-Yau type (κ = 0)"
} else if kappa == dim as i64 {
"general type (κ = dim X)"
} else {
"intermediate Kodaira dimension"
}
}
pub fn fano_index_projective_space(n: usize) -> usize {
n + 1
}
pub fn fano_index_quadric(n: usize) -> usize {
n
}
pub fn is_projective_space_by_fano_index(fano_index: usize, dim: usize) -> bool {
fano_index == dim + 1
}
pub fn is_quadric_by_fano_index(fano_index: usize, dim: usize) -> bool {
fano_index == dim
}
pub fn estimate_kodaira_dim(pluricanonical_dims: &[u64]) -> i64 {
if pluricanonical_dims.is_empty() || *pluricanonical_dims.iter().max().unwrap_or(&0) == 0 {
return -1;
}
let n = pluricanonical_dims.len();
if n < 2 {
return 0;
}
let first_nonzero = pluricanonical_dims.iter().position(|&d| d > 0);
let last = pluricanonical_dims[n - 1];
match first_nonzero {
None => -1,
Some(i) => {
let first = pluricanonical_dims[i];
if last <= first {
0
} else {
let ratio = last as f64 / first as f64;
let m_ratio = (n - 1 - i) as f64;
if m_ratio < 1.0 {
return 0;
}
let kappa = ratio.ln() / m_ratio.ln();
kappa.round() as i64
}
}
}
}
pub fn check_bmy_inequality(c1_sq: i64, c2: i64) -> bool {
c1_sq <= 3 * c2
}
pub fn check_noether_inequality(p_g: i64, k_sq: i64) -> bool {
2 * p_g - 4 <= k_sq
}
pub fn classify_surface(
kodaira_dim: KodairaDim,
irregularity: u32,
geometric_genus: u32,
) -> &'static str {
match kodaira_dim {
KodairaDim::NegInfinity => {
if irregularity == 0 {
"rational surface"
} else {
"ruled surface over a curve"
}
}
KodairaDim::Finite(0) => match (irregularity, geometric_genus) {
(0, 0) => "Enriques surface",
(0, 1) => "K3 surface",
(q, 0) if q > 0 => "bielliptic surface",
_ => "abelian surface",
},
KodairaDim::Finite(1) => "elliptic surface (Kodaira dim 1)",
KodairaDim::Finite(2) => "surface of general type",
_ => "unknown surface type",
}
}
#[cfg(test)]
mod tests {
use super::*;
use oxilean_kernel::Environment;
#[test]
fn test_log_pair_klt() {
let lp = LogPair::trivial("X")
.with_boundary("D1", 0.3)
.with_boundary("D2", 0.5);
assert!(lp.is_klt());
assert!(lp.is_log_canonical());
let lp2 = LogPair::trivial("X").with_boundary("D", 1.0);
assert!(!lp2.is_klt());
assert!(lp2.is_log_canonical());
}
#[test]
fn test_discrepancy_smooth_blowup() {
let d = discrepancy_smooth_blowup(3, 0.0);
assert!((d - 2.0).abs() < 1e-10);
let d2 = discrepancy_smooth_blowup(1, 0.0);
assert!(d2.abs() < 1e-10);
}
#[test]
fn test_lct_hypersurface() {
assert!((log_canonical_threshold(3, 2) - 1.0).abs() < 1e-10);
assert!((log_canonical_threshold(2, 3) - 2.0 / 3.0).abs() < 1e-10);
assert!((log_canonical_threshold(4, 1) - 1.0).abs() < 1e-10);
}
#[test]
fn test_kodaira_dim_product() {
assert_eq!(kodaira_dim_product(0, 0), 0);
assert_eq!(kodaira_dim_product(1, 2), 3);
assert_eq!(kodaira_dim_product(-1, 2), -1);
assert_eq!(kodaira_dim_product(2, -1), -1);
}
#[test]
fn test_mori_cone_p2() {
let cone = MoriCone::projective_space(2);
assert_eq!(cone.num_extremal_rays(), 1);
assert!(cone.is_fano());
assert_eq!(cone.extremal_rays[0], -3);
}
#[test]
fn test_mori_cone_del_pezzo() {
let cone = MoriCone::del_pezzo(5);
assert_eq!(cone.num_extremal_rays(), 5);
assert!(cone.is_fano());
}
#[test]
fn test_blow_up_data() {
let bu = BlowUpData::new("P^3", "pt", 3);
assert_eq!(bu.exceptional_discrepancy(), 2);
let bu2 = BlowUpData::new("S", "pt", 2);
assert_eq!(bu2.exceptional_self_intersection(), -1);
}
#[test]
fn test_build_birational_geometry_env() {
let mut env = Environment::new();
build_birational_geometry_env(&mut env);
assert!(env.get(&Name::str("hironaka_resolution")).is_some());
assert!(env.get(&Name::str("mori_cone_theorem")).is_some());
assert!(env.get(&Name::str("flip_existence")).is_some());
assert!(env.get(&Name::str("bchm_theorem")).is_some());
assert!(env.get(&Name::str("abundance_conjecture")).is_some());
assert!(env.get(&Name::str("kawamata_viehweg_vanishing")).is_some());
assert!(env.get(&Name::str("cone_theorem")).is_some());
assert!(env.get(&Name::str("contraction_theorem")).is_some());
assert!(env.get(&Name::str("rationality_theorem")).is_some());
assert!(env.get(&Name::str("terminal_implies_canonical")).is_some());
assert!(env.get(&Name::str("castelnuovo_rationality")).is_some());
assert!(env
.get(&Name::str("grauert_riemenschneider_vanishing"))
.is_some());
assert!(env.get(&Name::str("miyaoka_mori_theorem")).is_some());
assert!(env.get(&Name::str("bogomolov_miyaoka_yau")).is_some());
assert!(env.get(&Name::str("fano_is_mori_dream_space")).is_some());
assert!(env.get(&Name::str("flip_termination_bchm")).is_some());
}
#[test]
fn test_kodaira_dim_enum() {
let kd = KodairaDim::Finite(2);
assert!(kd.is_general_type(2));
assert!(!kd.is_uniruled());
assert_eq!(kd.classify(2), "general type");
let neg = KodairaDim::NegInfinity;
assert!(neg.is_uniruled());
assert!(!neg.is_general_type(3));
let z = KodairaDim::zero();
assert_eq!(z.classify(2), "Kodaira dim 0 (CY / K3 / abelian type)");
let prod = KodairaDim::Finite(1).product(KodairaDim::Finite(2));
assert_eq!(prod, KodairaDim::Finite(3));
let prod2 = KodairaDim::NegInfinity.product(KodairaDim::Finite(2));
assert_eq!(prod2, KodairaDim::NegInfinity);
}
#[test]
fn test_kodaira_dim_ordering() {
assert!(KodairaDim::NegInfinity < KodairaDim::Finite(0));
assert!(KodairaDim::Finite(0) < KodairaDim::Finite(1));
assert!(KodairaDim::Finite(2) > KodairaDim::NegInfinity);
}
#[test]
fn test_mmp_step_enum() {
let s = MmpStep::Contraction {
divisor: "E".to_string(),
singularity_type: SingularityType::Terminal,
};
assert!(!s.is_terminal());
assert!(s.description().contains("E"));
let f = MmpStep::Flip {
locus: "C".to_string(),
};
assert!(!f.is_terminal());
let m = MmpStep::MinimalModel;
assert!(m.is_terminal());
let fs = MmpStep::FiberSpace {
base: "B".to_string(),
fiber_dim: 1,
};
assert!(fs.is_terminal());
}
#[test]
fn test_singularity_type_order() {
let s = SingularityType::Smooth;
let t = SingularityType::Terminal;
let lc = SingularityType::LogCanonical;
assert!(s.at_least_as_mild_as(&t));
assert!(t.at_least_as_mild_as(&lc));
assert!(!lc.at_least_as_mild_as(&s));
}
#[test]
fn test_extreme_ray() {
let ray = ExtremeRay::new("l", -3, ContractionType::FiberType);
assert!(ray.is_k_negative());
let step = ray.mmp_step();
assert!(step.is_terminal());
}
#[test]
fn test_mmp_flowchart() {
let pair = LogPair::trivial("X").with_boundary("D", 0.3);
let mut chart = MmpFlowchart::new(pair, 3);
let steps = vec![
MmpStep::Contraction {
divisor: "E1".to_string(),
singularity_type: SingularityType::Terminal,
},
MmpStep::Flip {
locus: "C".to_string(),
},
MmpStep::MinimalModel,
];
chart.run(steps);
assert_eq!(chart.history.len(), 3);
assert_eq!(chart.picard_number, 2);
let summary = chart.summary();
assert!(summary.contains("Step 1"));
assert!(summary.contains("Step 3"));
}
#[test]
fn test_zariski_decomp() {
let z = ZariskiDecomp::new(
"D",
vec![("H".to_string(), 2.0)],
vec![("E".to_string(), 0.5)],
);
assert!(z.is_negative_part_effective());
assert!((z.nef_degree() - 2.0).abs() < 1e-10);
assert!((z.neg_degree() - 0.5).abs() < 1e-10);
}
#[test]
fn test_bmy_inequality() {
assert!(check_bmy_inequality(9, 3));
assert!(!check_bmy_inequality(10, 3));
}
#[test]
fn test_noether_inequality() {
assert!(check_noether_inequality(3, 4));
assert!(!check_noether_inequality(5, 2));
}
#[test]
fn test_classify_surface() {
assert_eq!(
classify_surface(KodairaDim::NegInfinity, 0, 0),
"rational surface"
);
assert_eq!(
classify_surface(KodairaDim::NegInfinity, 2, 0),
"ruled surface over a curve"
);
assert_eq!(classify_surface(KodairaDim::Finite(0), 0, 1), "K3 surface");
assert_eq!(
classify_surface(KodairaDim::Finite(0), 0, 0),
"Enriques surface"
);
assert_eq!(
classify_surface(KodairaDim::Finite(2), 0, 0),
"surface of general type"
);
}
#[test]
fn test_sarkisov_link_type() {
let t = SarkisovLinkType::TypeII;
assert_eq!(t.code(), 2);
assert!(t.description().contains("both"));
}
}
#[cfg(test)]
mod tests_birational_ext {
use super::*;
#[test]
fn test_mmp_step() {
let step = MMPStepData::new(MMPOperation::Flip, "X'").with_exceptional("E");
assert!(!step.is_final());
assert!(step.description().contains("Flip"));
let final_step = MMPStepData::new(MMPOperation::MinimalModel, "X_min");
assert!(final_step.is_final());
}
#[test]
fn test_log_pair() {
let mut lp = LogPairData::new("X");
lp.add_boundary("D1", 0.5);
lp.add_boundary("D2", 0.3);
lp.add_log_discrepancy(0.2);
lp.add_log_discrepancy(0.8);
assert!(lp.is_klt());
assert!(lp.is_log_canonical());
assert_eq!(lp.singularity_type(), "klt (Kawamata log terminal)");
assert!((lp.total_coefficient() - 0.8).abs() < 1e-10);
}
#[test]
fn test_log_pair_not_klt() {
let mut lp = LogPairData::new("X");
lp.add_log_discrepancy(-0.5);
lp.add_log_discrepancy(-1.0);
assert!(!lp.is_klt());
assert!(lp.is_log_canonical());
}
#[test]
fn test_abundance_data() {
let ad = AbundanceData::new("S", 2)
.with_kodaira_dim(0)
.nef()
.abundant();
assert!(ad.kx_nef && ad.kx_semi_ample);
assert!(ad.abundance_known());
assert!(ad.abundance_status().contains("holds"));
}
}
#[cfg(test)]
mod tests_birational_ext2 {
use super::*;
#[test]
fn test_kv_vanishing() {
let kv = KVVanishingData::new("X", 3).nef_and_big();
assert!(kv.vanishes_at(1));
assert!(kv.vanishes_at(3));
assert!(!kv.vanishes_at(0));
assert!(kv.vanishing_statement().contains("K_X + L"));
}
}
#[cfg(test)]
mod tests_birational_ext3 {
use super::*;
#[test]
fn test_iitaka_fibration() {
let if_data = IitakaFibration::new("X", "C", "F", 1);
assert_eq!(if_data.base_dim, 1);
assert!(if_data.addition_formula(0, 1));
assert!(!if_data.is_general_type(3));
let gt = IitakaFibration::new("X", "pt", "X", 3);
assert!(gt.is_general_type(3));
}
}