use super::functions::*;
#[derive(Debug, Clone)]
pub struct TropicalConic {
pub coefficients: Vec<f64>,
}
#[derive(Debug, Clone)]
pub struct TropicalLine {
pub coefficients: (f64, f64, f64),
}
#[derive(Debug, Clone)]
pub struct NewtonPolytope {
pub vertices: Vec<Vec<i32>>,
pub dimension: usize,
}
impl NewtonPolytope {
pub fn new(dimension: usize) -> Self {
NewtonPolytope {
vertices: Vec::new(),
dimension,
}
}
pub fn add_vertex(&mut self, v: Vec<i32>) {
debug_assert_eq!(v.len(), self.dimension, "vertex dimension mismatch");
self.vertices.push(v);
}
pub fn is_lattice_polytope(&self) -> bool {
true
}
pub fn volume(&self) -> f64 {
match self.dimension {
1 => {
if self.vertices.is_empty() {
return 0.0;
}
let vals: Vec<i32> = self.vertices.iter().map(|v| v[0]).collect();
let mn = *vals
.iter()
.min()
.expect("vals is non-empty: vertices.is_empty() check returned early");
let mx = *vals
.iter()
.max()
.expect("vals is non-empty: vertices.is_empty() check returned early");
(mx - mn) as f64
}
2 => {
let n = self.vertices.len();
if n < 3 {
return 0.0;
}
let mut area2 = 0i64;
for i in 0..n {
let j = (i + 1) % n;
let xi = self.vertices[i][0] as i64;
let yi = self.vertices[i][1] as i64;
let xj = self.vertices[j][0] as i64;
let yj = self.vertices[j][1] as i64;
area2 += xi * yj - xj * yi;
}
(area2.abs() as f64) / 2.0
}
_ => 0.0,
}
}
pub fn num_interior_lattice_points(&self) -> usize {
if self.dimension != 2 || self.vertices.len() < 3 {
return 0;
}
let area = self.volume();
let n = self.vertices.len();
let mut boundary = 0usize;
for i in 0..n {
let j = (i + 1) % n;
let dx = (self.vertices[j][0] - self.vertices[i][0]).unsigned_abs() as usize;
let dy = (self.vertices[j][1] - self.vertices[i][1]).unsigned_abs() as usize;
boundary += gcd(dx, dy);
}
let interior_f = area - (boundary as f64) / 2.0 + 1.0;
interior_f.round().max(0.0) as usize
}
}
#[derive(Debug, Clone)]
pub struct TropicalPolynomial {
pub terms: Vec<TropicalMonomial>,
pub n_vars: usize,
}
impl TropicalPolynomial {
pub fn new(n_vars: usize) -> Self {
TropicalPolynomial {
terms: Vec::new(),
n_vars,
}
}
pub fn add_term(&mut self, coeff: f64, exponents: Vec<i32>) {
debug_assert_eq!(
exponents.len(),
self.n_vars,
"exponent length must match n_vars"
);
self.terms.push(TropicalMonomial {
coefficient: coeff,
exponents,
});
}
pub fn evaluate(&self, point: &[f64]) -> f64 {
self.terms
.iter()
.map(|m| {
let dot: f64 = m
.exponents
.iter()
.zip(point.iter())
.map(|(&e, &x)| (e as f64) * x)
.sum();
m.coefficient + dot
})
.fold(f64::INFINITY, f64::min)
}
pub fn degree(&self) -> i32 {
self.terms
.iter()
.map(|m| m.exponents.iter().copied().sum::<i32>())
.max()
.unwrap_or(0)
}
}
impl TropicalPolynomial {
pub fn evaluate_tropical(&self, point: &[f64]) -> f64 {
self.evaluate(point)
}
pub fn newton_polytope(&self) -> NewtonPolytope {
let mut np = NewtonPolytope::new(self.n_vars);
for term in &self.terms {
np.vertices.push(term.exponents.clone());
}
np
}
}
#[derive(Debug, Clone)]
pub struct KrullValuation {
pub ring: String,
pub value_group: String,
}
impl KrullValuation {
pub fn new(ring: impl Into<String>, value_group: impl Into<String>) -> Self {
KrullValuation {
ring: ring.into(),
value_group: value_group.into(),
}
}
pub fn is_discrete(&self) -> bool {
self.value_group == "ℤ" || self.value_group == "Z"
}
pub fn valuation_ring_is_dvr(&self) -> bool {
self.is_discrete()
}
}
#[allow(dead_code)]
#[derive(Debug, Clone)]
pub struct TropicalGrassmannianExt {
pub k: usize,
pub n: usize,
}
impl TropicalGrassmannianExt {
#[allow(dead_code)]
pub fn new(k: usize, n: usize) -> Self {
assert!(k <= n);
Self { k, n }
}
#[allow(dead_code)]
pub fn dimension(&self) -> usize {
self.k * (self.n - self.k)
}
#[allow(dead_code)]
pub fn is_tropical_linear_space_of_g24(&self) -> bool {
self.k == 2 && self.n == 4
}
#[allow(dead_code)]
pub fn plucker_description(&self) -> String {
format!(
"Trop(Gr({},{})) lives in R^C(n,k) via tropicalized Plucker coords",
self.k, self.n
)
}
}
#[derive(Debug, Clone)]
pub struct TropicalMatrix {
pub n: usize,
pub data: Vec<TropicalNumber>,
}
impl TropicalMatrix {
pub fn zero(n: usize) -> Self {
TropicalMatrix {
n,
data: vec![TropicalNumber::PosInfinity; n * n],
}
}
pub fn identity(n: usize) -> Self {
let mut m = Self::zero(n);
for i in 0..n {
m.set(i, i, TropicalNumber::Finite(0.0));
}
m
}
pub fn get(&self, i: usize, j: usize) -> &TropicalNumber {
&self.data[i * self.n + j]
}
pub fn set(&mut self, i: usize, j: usize, v: TropicalNumber) {
self.data[i * self.n + j] = v;
}
pub fn trop_mul(&self, other: &Self) -> Self {
debug_assert_eq!(self.n, other.n, "matrix size mismatch");
let n = self.n;
let mut result = Self::zero(n);
for i in 0..n {
for j in 0..n {
let mut best = TropicalNumber::PosInfinity;
for k in 0..n {
let candidate = self.get(i, k).mul(other.get(k, j));
best = best.add(&candidate);
}
result.set(i, j, best);
}
}
result
}
pub fn trop_pow(&self, k: u32) -> Self {
if k == 0 {
return Self::identity(self.n);
}
let mut result = self.clone();
for _ in 1..k {
result = result.trop_mul(self);
}
result
}
}
#[allow(dead_code)]
#[derive(Debug, Clone)]
pub struct RegularSubdivision {
pub points: Vec<Vec<i64>>,
pub heights: Vec<f64>,
pub num_cells: usize,
}
impl RegularSubdivision {
#[allow(dead_code)]
pub fn new(points: Vec<Vec<i64>>, heights: Vec<f64>) -> Self {
let num_cells = if points.len() > 2 {
points.len() - 1
} else {
1
};
Self {
points,
heights,
num_cells,
}
}
#[allow(dead_code)]
pub fn is_unimodular(&self) -> bool {
true
}
#[allow(dead_code)]
pub fn dual_tropical_hypersurface_description(&self) -> String {
format!(
"Regular subdivision with {} cells dualizes to tropical hypersurface",
self.num_cells
)
}
}
#[derive(Debug, Clone)]
pub struct TropicalLinearSpace {
pub matroid: String,
pub dimension: usize,
}
impl TropicalLinearSpace {
pub fn new(matroid: impl Into<String>, dimension: usize) -> Self {
TropicalLinearSpace {
matroid: matroid.into(),
dimension,
}
}
pub fn bergman_fan(&self) -> String {
format!(
"Bergman fan of matroid '{}' (dim {})",
self.matroid, self.dimension
)
}
}
#[derive(Debug, Clone)]
pub struct TropicalSemiring;
impl TropicalSemiring {
pub fn zero() -> TropicalElement {
TropicalElement::NegInfinity
}
pub fn one() -> TropicalElement {
TropicalElement::Finite(0.0)
}
pub fn add_identity() -> TropicalElement {
Self::zero()
}
pub fn mul_identity() -> TropicalElement {
Self::one()
}
}
impl TropicalSemiring {
pub fn tropical_add(a: f64, b: f64) -> f64 {
a.min(b)
}
pub fn tropical_mul(a: f64, b: f64) -> f64 {
a + b
}
}
#[allow(dead_code)]
#[derive(Debug, Clone)]
pub struct ValuatedMatroid {
pub ground_set_size: usize,
pub rank: usize,
pub name: String,
}
impl ValuatedMatroid {
#[allow(dead_code)]
pub fn new(n: usize, r: usize, name: &str) -> Self {
Self {
ground_set_size: n,
rank: r,
name: name.to_string(),
}
}
#[allow(dead_code)]
pub fn tropical_linear_space_description(&self) -> String {
format!(
"Valuated ({},{}) matroid -> tropical linear space of dim {} in R^{}",
self.rank,
self.ground_set_size,
self.ground_set_size - self.rank,
self.ground_set_size
)
}
#[allow(dead_code)]
pub fn is_realizable(&self) -> bool {
true
}
}
#[derive(Debug, Clone)]
pub struct TropicalHyperplane {
pub normal: Vec<f64>,
pub constant: f64,
}
impl TropicalHyperplane {
pub fn new(normal: Vec<f64>, constant: f64) -> Self {
TropicalHyperplane { normal, constant }
}
pub fn evaluate_tropical(&self, point: &[f64]) -> f64 {
let linear_min = self
.normal
.iter()
.zip(point.iter())
.map(|(c, x)| c + x)
.fold(f64::INFINITY, f64::min);
linear_min.min(self.constant)
}
}
#[allow(dead_code)]
#[derive(Debug, Clone)]
pub struct TropicalAbelianVariety {
pub genus: usize,
pub lattice_rank: usize,
}
impl TropicalAbelianVariety {
#[allow(dead_code)]
pub fn jacobian(genus: usize) -> Self {
Self {
genus,
lattice_rank: genus,
}
}
#[allow(dead_code)]
pub fn dimension(&self) -> usize {
self.genus
}
#[allow(dead_code)]
pub fn is_principally_polarized_description(&self) -> String {
format!(
"Trop Jac^{}: principally polarized tropical abelian variety",
self.genus
)
}
}
#[allow(dead_code)]
#[derive(Debug, Clone)]
pub struct NewtonPolytopeExt {
pub vertices: Vec<Vec<i64>>,
pub dimension: usize,
}
impl NewtonPolytopeExt {
#[allow(dead_code)]
pub fn new(vertices: Vec<Vec<i64>>) -> Self {
let dim = vertices.first().map(|v| v.len()).unwrap_or(0);
Self {
vertices,
dimension: dim,
}
}
#[allow(dead_code)]
pub fn num_vertices(&self) -> usize {
self.vertices.len()
}
#[allow(dead_code)]
pub fn mixed_volume_description(&self) -> String {
format!("Mixed volume of Newton polytopes governs root count via BKK theorem")
}
#[allow(dead_code)]
pub fn bkk_bound_description(&self) -> String {
"BKK: #solutions of generic system = mixed volume of Newton polytopes".to_string()
}
}
#[derive(Debug, Clone, PartialEq)]
pub enum TropicalElement {
Finite(f64),
NegInfinity,
}
impl TropicalElement {
pub fn tropical_add(&self, other: &Self) -> Self {
match (self, other) {
(TropicalElement::NegInfinity, _) => other.clone(),
(_, TropicalElement::NegInfinity) => self.clone(),
(TropicalElement::Finite(a), TropicalElement::Finite(b)) => {
TropicalElement::Finite(a.min(*b))
}
}
}
pub fn tropical_mul(&self, other: &Self) -> Self {
match (self, other) {
(TropicalElement::NegInfinity, _) | (_, TropicalElement::NegInfinity) => {
TropicalElement::NegInfinity
}
(TropicalElement::Finite(a), TropicalElement::Finite(b)) => {
TropicalElement::Finite(a + b)
}
}
}
pub fn is_zero(&self) -> bool {
matches!(self, TropicalElement::NegInfinity)
}
pub fn is_one(&self) -> bool {
matches!(self, TropicalElement::Finite(v) if * v == 0.0)
}
}
#[derive(Debug, Clone)]
pub struct PluckerCoordinates {
pub k: usize,
pub n: usize,
pub coords: Vec<f64>,
}
impl PluckerCoordinates {
pub fn new(k: usize, n: usize, coords: Vec<f64>) -> Self {
PluckerCoordinates { k, n, coords }
}
pub fn num_coords(&self) -> usize {
binomial(self.n, self.k)
}
}
#[allow(dead_code)]
#[derive(Debug, Clone)]
pub struct TropicalRiemannSurface {
pub genus: u64,
pub num_edges: usize,
pub num_vertices: usize,
pub edge_lengths: Vec<f64>,
}
impl TropicalRiemannSurface {
#[allow(dead_code)]
pub fn new(genus: u64, edges: usize, vertices: usize) -> Self {
let lengths = vec![1.0; edges];
Self {
genus,
num_edges: edges,
num_vertices: vertices,
edge_lengths: lengths,
}
}
#[allow(dead_code)]
pub fn jacobian_dimension(&self) -> u64 {
self.genus
}
#[allow(dead_code)]
pub fn abel_jacobi_map_description(&self) -> String {
format!(
"Abel-Jacobi map: tropical curve -> Jac^{} (tropical torus = R^g / Lambda)",
self.genus
)
}
#[allow(dead_code)]
pub fn chip_firing_equivalence(&self) -> String {
"Divisors: chip firing game; linear equivalence = chip firing moves".to_string()
}
}
#[allow(dead_code)]
#[derive(Debug, Clone)]
pub struct TropicalLinearProgram {
pub num_variables: usize,
pub num_constraints: usize,
pub objective: Vec<f64>,
pub constraint_matrix: Vec<Vec<f64>>,
pub rhs: Vec<f64>,
}
impl TropicalLinearProgram {
#[allow(dead_code)]
pub fn new(vars: usize, obj: Vec<f64>, matrix: Vec<Vec<f64>>, rhs: Vec<f64>) -> Self {
let num_constraints = matrix.len();
Self {
num_variables: vars,
num_constraints,
objective: obj,
constraint_matrix: matrix,
rhs,
}
}
#[allow(dead_code)]
pub fn tropical_feasibility_description(&self) -> String {
format!(
"Tropical LP: min_{{x in R^{}}} c'x s.t. Ax >= b (tropically)",
self.num_variables
)
}
#[allow(dead_code)]
pub fn optimal_value_lower_bound(&self) -> f64 {
self.objective.iter().cloned().fold(f64::INFINITY, f64::min)
}
}
#[allow(dead_code)]
#[derive(Debug, Clone)]
pub struct TropicalHypersurfaceExt {
pub polynomial_support: Vec<Vec<i64>>,
pub coefficients: Vec<f64>,
pub ambient_dimension: usize,
}
impl TropicalHypersurfaceExt {
#[allow(dead_code)]
pub fn new(support: Vec<Vec<i64>>, coefficients: Vec<f64>) -> Self {
let dim = support.first().map(|v| v.len()).unwrap_or(0);
Self {
polynomial_support: support,
coefficients,
ambient_dimension: dim,
}
}
#[allow(dead_code)]
pub fn evaluate_at(&self, point: &[f64]) -> f64 {
self.polynomial_support
.iter()
.zip(&self.coefficients)
.map(|(alpha, &a)| {
let inner: f64 = alpha
.iter()
.zip(point)
.map(|(&ai, &xi)| ai as f64 * xi)
.sum();
a + inner
})
.fold(f64::NEG_INFINITY, f64::max)
}
#[allow(dead_code)]
pub fn is_on_hypersurface(&self, point: &[f64]) -> bool {
let vals: Vec<f64> = self
.polynomial_support
.iter()
.zip(&self.coefficients)
.map(|(alpha, &a)| {
let inner: f64 = alpha
.iter()
.zip(point)
.map(|(&ai, &xi)| ai as f64 * xi)
.sum();
a + inner
})
.collect();
let max_val = vals.iter().cloned().fold(f64::NEG_INFINITY, f64::max);
vals.iter()
.filter(|&&v| (v - max_val).abs() < 1e-10)
.count()
>= 2
}
}
pub struct TropicalEigenvalueComputer {
pub matrix: Vec<Vec<f64>>,
}
impl TropicalEigenvalueComputer {
pub fn new(matrix: Vec<Vec<f64>>) -> Self {
TropicalEigenvalueComputer { matrix }
}
fn max_plus_mul(a: &[Vec<f64>], b: &[Vec<f64>]) -> Vec<Vec<f64>> {
let n = a.len();
let mut c = vec![vec![f64::NEG_INFINITY; n]; n];
for i in 0..n {
for j in 0..n {
for k in 0..n {
let v = a[i][k] + b[k][j];
if v > c[i][j] {
c[i][j] = v;
}
}
}
}
c
}
fn power(&self, k: usize) -> Vec<Vec<f64>> {
let n = self.matrix.len();
if k == 0 {
let mut id = vec![vec![f64::NEG_INFINITY; n]; n];
for i in 0..n {
id[i][i] = 0.0;
}
return id;
}
let mut result = self.matrix.clone();
for _ in 1..k {
result = Self::max_plus_mul(&result, &self.matrix);
}
result
}
pub fn compute_eigenvalue(&self) -> Option<f64> {
let n = self.matrix.len();
if n == 0 {
return None;
}
let powers: Vec<Vec<Vec<f64>>> = (0..=n).map(|k| self.power(k)).collect();
let mut global_max = f64::NEG_INFINITY;
for i in 0..n {
let mut node_min = f64::INFINITY;
for k in 0..n {
let a_n = powers[n][i][i];
let a_k = powers[k][i][i];
if a_n.is_finite() && a_k.is_finite() {
let val = (a_n - a_k) / (n - k) as f64;
if val < node_min {
node_min = val;
}
}
}
if node_min.is_finite() && node_min > global_max {
global_max = node_min;
}
}
if global_max.is_finite() {
Some(global_max)
} else {
None
}
}
}
#[derive(Debug, Clone)]
pub struct TropicalConvexHull {
pub points: Vec<Vec<f64>>,
}
impl TropicalConvexHull {
pub fn new() -> Self {
TropicalConvexHull { points: Vec::new() }
}
pub fn add_point(&mut self, point: Vec<f64>) {
self.points.push(point);
}
pub fn contains_tropical(&self, point: &[f64]) -> bool {
if self.points.is_empty() {
return false;
}
self.points.iter().any(|v| {
if v.len() != point.len() {
return false;
}
let diffs: Vec<f64> = point.iter().zip(v.iter()).map(|(z, vi)| z - vi).collect();
let min_diff = diffs.iter().cloned().fold(f64::INFINITY, f64::min);
diffs.iter().all(|&d| (d - min_diff).abs() < 1e-10)
})
}
pub fn tropical_vertices(&self) -> Vec<Vec<f64>> {
self.points.clone()
}
}
#[derive(Debug, Clone)]
pub struct DrinfeldModule {
pub rank: usize,
pub characteristic: u64,
}
impl DrinfeldModule {
pub fn new(rank: usize, characteristic: u64) -> Self {
DrinfeldModule {
rank,
characteristic,
}
}
pub fn is_ordinary(&self) -> bool {
self.rank <= 1 || self.characteristic % 2 != 0
}
pub fn is_supersingular(&self) -> bool {
!self.is_ordinary()
}
pub fn height(&self) -> usize {
if self.is_ordinary() {
0
} else {
self.rank
}
}
}
#[derive(Debug, Clone)]
pub struct TropicalGrassmannian {
pub k: usize,
pub n: usize,
}
impl TropicalGrassmannian {
pub fn new(k: usize, n: usize) -> Self {
TropicalGrassmannian { k, n }
}
pub fn dimension(&self) -> usize {
self.k * (self.n.saturating_sub(self.k))
}
pub fn is_valid_plucker_coords(&self, coords: &[f64]) -> bool {
let expected = binomial(self.n, self.k);
coords.len() == expected
}
}
#[derive(Debug, Clone, PartialEq, PartialOrd)]
pub enum TropicalNumber {
Finite(f64),
PosInfinity,
}
impl TropicalNumber {
pub fn zero() -> Self {
TropicalNumber::PosInfinity
}
pub fn one() -> Self {
TropicalNumber::Finite(0.0)
}
pub fn add(&self, other: &Self) -> Self {
match (self, other) {
(TropicalNumber::PosInfinity, x) | (x, TropicalNumber::PosInfinity) => x.clone(),
(TropicalNumber::Finite(a), TropicalNumber::Finite(b)) => {
TropicalNumber::Finite(a.min(*b))
}
}
}
pub fn mul(&self, other: &Self) -> Self {
match (self, other) {
(TropicalNumber::PosInfinity, _) | (_, TropicalNumber::PosInfinity) => {
TropicalNumber::PosInfinity
}
(TropicalNumber::Finite(a), TropicalNumber::Finite(b)) => TropicalNumber::Finite(a + b),
}
}
pub fn to_f64(&self) -> f64 {
match self {
TropicalNumber::Finite(v) => *v,
TropicalNumber::PosInfinity => f64::INFINITY,
}
}
pub fn from_f64(v: f64) -> Self {
if v.is_infinite() && v > 0.0 {
TropicalNumber::PosInfinity
} else {
TropicalNumber::Finite(v)
}
}
}
pub struct TropicalConvexHullComputer {
pub generators: Vec<Vec<f64>>,
pub dim: usize,
}
impl TropicalConvexHullComputer {
pub fn new(generators: Vec<Vec<f64>>) -> Option<Self> {
if generators.is_empty() {
return None;
}
let dim = generators[0].len();
if generators.iter().any(|g| g.len() != dim) {
return None;
}
Some(TropicalConvexHullComputer { generators, dim })
}
pub fn contains(&self, point: &[f64]) -> bool {
if point.len() != self.dim {
return false;
}
self.generators.iter().any(|v| {
let diffs: Vec<f64> = point.iter().zip(v.iter()).map(|(z, vi)| z - vi).collect();
let min_diff = diffs.iter().cloned().fold(f64::INFINITY, f64::min);
diffs.iter().all(|&d| (d - min_diff).abs() < 1e-10)
})
}
pub fn tropical_vertices(&self) -> Vec<Vec<f64>> {
let m = self.generators.len();
let mut vertices = Vec::new();
for i in 0..m {
let others: Vec<Vec<f64>> = self
.generators
.iter()
.enumerate()
.filter(|(j, _)| *j != i)
.map(|(_, g)| g.clone())
.collect();
if others.is_empty() {
vertices.push(self.generators[i].clone());
continue;
}
let sub_hull = TropicalConvexHullComputer {
generators: others,
dim: self.dim,
};
if !sub_hull.contains(&self.generators[i]) {
vertices.push(self.generators[i].clone());
}
}
vertices
}
pub fn tropical_centroid(&self) -> Vec<f64> {
let mut centroid = vec![f64::INFINITY; self.dim];
for g in &self.generators {
for (j, &gj) in g.iter().enumerate() {
if gj < centroid[j] {
centroid[j] = gj;
}
}
}
centroid
}
}
#[allow(dead_code)]
#[derive(Debug, Clone)]
pub struct TropicalCurveExt2 {
pub genus: u64,
pub degree: u64,
pub ambient_dimension: usize,
}
impl TropicalCurveExt2 {
#[allow(dead_code)]
pub fn new(genus: u64, degree: u64, ambient_dim: usize) -> Self {
Self {
genus,
degree,
ambient_dimension: ambient_dim,
}
}
#[allow(dead_code)]
pub fn in_tropical_plane(degree: u64) -> Self {
let genus = if degree >= 2 {
(degree - 1) * (degree - 2) / 2
} else {
0
};
Self {
genus,
degree,
ambient_dimension: 2,
}
}
#[allow(dead_code)]
pub fn euler_characteristic(&self) -> i64 {
2 - 2 * self.genus as i64
}
#[allow(dead_code)]
pub fn num_edges_description(&self) -> String {
format!(
"Tropical curve of degree {} genus {}: bounded edges",
self.degree, self.genus
)
}
}
#[allow(dead_code)]
#[derive(Debug, Clone)]
pub struct TropicalGroebnerBasis {
pub ideal_name: String,
pub initial_ideal_name: String,
pub tropical_variety_description: String,
}
impl TropicalGroebnerBasis {
#[allow(dead_code)]
pub fn new(ideal: &str) -> Self {
Self {
ideal_name: ideal.to_string(),
initial_ideal_name: format!("in_w({})", ideal),
tropical_variety_description: format!("Trop({}) = union of cones", ideal),
}
}
#[allow(dead_code)]
pub fn fundamental_theorem_description(&self) -> String {
format!(
"Fundamental theorem of tropical geometry: Trop({}) = closure of amoeba",
self.ideal_name
)
}
}
#[allow(dead_code)]
#[derive(Debug, Clone)]
pub struct TropicalScheme {
pub name: String,
pub is_reduced: bool,
}
impl TropicalScheme {
#[allow(dead_code)]
pub fn new(name: &str) -> Self {
Self {
name: name.to_string(),
is_reduced: true,
}
}
#[allow(dead_code)]
pub fn functor_of_points_description(&self) -> String {
format!(
"Trop scheme {}: functor Sch^op -> Set via tropical semiring",
self.name
)
}
}
#[allow(dead_code)]
#[derive(Debug, Clone)]
pub struct TropicalFan {
pub name: String,
pub ambient_dimension: usize,
pub fan_dimension: usize,
pub is_balanced: bool,
}
impl TropicalFan {
#[allow(dead_code)]
pub fn new(name: &str, ambient_dim: usize, fan_dim: usize) -> Self {
Self {
name: name.to_string(),
ambient_dimension: ambient_dim,
fan_dimension: fan_dim,
is_balanced: true,
}
}
#[allow(dead_code)]
pub fn balancing_condition(&self) -> String {
"Sum of primitive generators weighted by multiplicities = 0 at each ridge".to_string()
}
#[allow(dead_code)]
pub fn represents_tropical_variety(&self) -> bool {
self.is_balanced
}
}
#[allow(dead_code)]
#[derive(Debug, Clone)]
pub struct TropicalIntersection {
pub variety_a: String,
pub variety_b: String,
pub codimension_a: usize,
pub codimension_b: usize,
}
impl TropicalIntersection {
#[allow(dead_code)]
pub fn new(a: &str, b: &str, codim_a: usize, codim_b: usize) -> Self {
Self {
variety_a: a.to_string(),
variety_b: b.to_string(),
codimension_a: codim_a,
codimension_b: codim_b,
}
}
#[allow(dead_code)]
pub fn expected_codimension(&self) -> usize {
self.codimension_a + self.codimension_b
}
#[allow(dead_code)]
pub fn stable_intersection_description(&self) -> String {
format!(
"Stable intersection {} cap {}: perturbation-independent",
self.variety_a, self.variety_b
)
}
}
#[derive(Debug, Clone)]
pub struct TropicalCurveVertex {
pub position: (f64, f64),
pub valence: usize,
}
#[derive(Debug, Clone)]
pub struct MirrorSymmetry {
pub a_model: String,
pub b_model: String,
pub is_homological: bool,
}
impl MirrorSymmetry {
pub fn new(
a_model: impl Into<String>,
b_model: impl Into<String>,
is_homological: bool,
) -> Self {
MirrorSymmetry {
a_model: a_model.into(),
b_model: b_model.into(),
is_homological,
}
}
pub fn hodge_numbers_match(&self) -> bool {
true
}
pub fn mirror_map_description(&self) -> String {
if self.is_homological {
format!(
"Homological mirror symmetry: Fuk({}) ≃ D^b Coh({})",
self.a_model, self.b_model
)
} else {
format!(
"SYZ mirror symmetry: T-duality fibers of {} ↔ {}",
self.a_model, self.b_model
)
}
}
}
#[allow(dead_code)]
#[derive(Debug, Clone)]
pub struct TropicalModuliM0n {
pub n: usize,
}
impl TropicalModuliM0n {
#[allow(dead_code)]
pub fn new(n: usize) -> Self {
assert!(n >= 3);
Self { n }
}
#[allow(dead_code)]
pub fn dimension(&self) -> usize {
self.n - 3
}
#[allow(dead_code)]
pub fn num_rays_description(&self) -> String {
format!(
"Trop M_{{0,{}}} has rays indexed by 2-subsets of [{}]",
self.n, self.n
)
}
#[allow(dead_code)]
pub fn space_of_phylogenetic_trees(&self) -> String {
format!(
"Trop M_{{0,{}}} = space of metric trees with {} labeled leaves",
self.n, self.n
)
}
}
#[derive(Debug, Clone)]
pub struct Valuation {
pub name: String,
pub field: String,
pub value_group: String,
}
#[derive(Debug, Clone)]
pub struct TropicalCurveExt {
pub degree: usize,
pub genus: usize,
pub vertices: Vec<TropicalCurveVertex>,
pub edges: Vec<(usize, usize, f64)>,
}
impl TropicalCurveExt {
pub fn new(degree: usize) -> Self {
let d = degree as i64;
let genus = if d >= 1 {
((d - 1) * (d - 2) / 2).max(0) as usize
} else {
0
};
TropicalCurveExt {
degree,
genus,
vertices: Vec::new(),
edges: Vec::new(),
}
}
pub fn genus_formula(&self) -> i64 {
let d = self.degree as i64;
(d - 1) * (d - 2) / 2
}
pub fn is_smooth(&self) -> bool {
let expected_genus = self.genus_formula().max(0) as usize;
if self.genus != expected_genus {
return false;
}
self.vertices.iter().all(|v| v.valence == 3)
}
}
impl TropicalCurveExt {
pub fn genus(&self) -> usize {
self.genus
}
pub fn num_marked_points(&self) -> usize {
3 * self.degree
}
}
#[derive(Debug, Clone)]
pub struct TropicalMonomial {
pub coefficient: f64,
pub exponents: Vec<i32>,
}
#[derive(Debug, Clone)]
pub struct TropicalVariety {
pub polynomial_system: Vec<TropicalPolynomial>,
pub n_vars: usize,
}
impl TropicalVariety {
pub fn new(n_vars: usize) -> Self {
TropicalVariety {
polynomial_system: Vec::new(),
n_vars,
}
}
pub fn add_equation(&mut self, poly: TropicalPolynomial) {
self.polynomial_system.push(poly);
}
pub fn dimension(&self) -> usize {
self.n_vars.saturating_sub(self.polynomial_system.len())
}
}
impl TropicalVariety {
pub fn stable_intersection(&self) -> String {
format!(
"Stable intersection of tropical variety in ℝ^{} (dim {})",
self.n_vars,
self.dimension()
)
}
}
#[derive(Debug, Clone)]
pub struct LaurentSeriesValuation {
pub variable: String,
}
#[derive(Debug, Clone)]
pub struct PAdicValuation {
pub p: u64,
}
impl PAdicValuation {
pub fn new(p: u64) -> Self {
PAdicValuation { p }
}
pub fn valuation(&self, n: i64) -> i64 {
if n == 0 {
return 0;
}
let mut n = n.unsigned_abs();
let mut k = 0i64;
while n % self.p == 0 {
n /= self.p;
k += 1;
}
k
}
pub fn ultrametric_triangle_inequality(&self) -> bool {
true
}
}
#[derive(Debug, Clone)]
pub struct TropicalHypersurface {
pub polynomial: String,
}
impl TropicalHypersurface {
pub fn new(polynomial: impl Into<String>) -> Self {
TropicalHypersurface {
polynomial: polynomial.into(),
}
}
pub fn dual_subdivision(&self) -> String {
format!(
"Regular subdivision of Newton polytope dual to V({})",
self.polynomial
)
}
pub fn skeleton(&self) -> String {
format!("Polyhedral skeleton of V({})", self.polynomial)
}
}
#[derive(Debug, Clone)]
pub struct TropicalSegment {
pub start: Vec<f64>,
pub end: Vec<f64>,
}
impl TropicalSegment {
pub fn new(start: Vec<f64>, end: Vec<f64>) -> Self {
TropicalSegment { start, end }
}
pub fn parametric_point(&self, t: f64) -> Vec<f64> {
self.start
.iter()
.zip(self.end.iter())
.map(|(s, e)| (s + t).min(*e))
.collect()
}
}