karpal_schubert_types/
intersection.rs1use amari_enumerative::{IntersectionResult, SchubertCalculus};
2
3use crate::schubert_type::SchubertType;
4
5#[derive(Debug, Clone)]
7pub struct Intersection {
8 kind: IntersectionKind,
9 multiplicity: u64,
10 decomposition: Vec<SchubertType>,
13}
14
15impl Intersection {
16 fn structural_zero() -> Self {
17 Self {
18 kind: IntersectionKind::StructuralZero,
19 multiplicity: 0,
20 decomposition: Vec::new(),
21 }
22 }
23
24 fn geometric_zero() -> Self {
25 Self {
26 kind: IntersectionKind::GeometricZero,
27 multiplicity: 0,
28 decomposition: Vec::new(),
29 }
30 }
31
32 fn positive(multiplicity: u64, decomposition: Vec<SchubertType>) -> Self {
33 Self {
34 kind: IntersectionKind::Positive,
35 multiplicity,
36 decomposition,
37 }
38 }
39
40 pub fn kind(&self) -> IntersectionKind {
42 self.kind
43 }
44
45 pub fn multiplicity(&self) -> u64 {
47 self.multiplicity
48 }
49
50 pub fn decomposition(&self) -> &[SchubertType] {
52 &self.decomposition
53 }
54
55 pub fn into_schubert(self) -> Option<SchubertType> {
58 if self.kind == IntersectionKind::Positive && !self.decomposition.is_empty() {
59 Some(self.decomposition.into_iter().next().unwrap())
60 } else {
61 None
62 }
63 }
64}
65
66#[derive(Debug, Clone, Copy, PartialEq, Eq)]
73pub enum IntersectionKind {
74 StructuralZero,
75 GeometricZero,
76 Positive,
77 Underdetermined,
78}
79
80impl IntersectionKind {
81 pub fn is_zero(&self) -> bool {
83 matches!(self, Self::StructuralZero | Self::GeometricZero)
84 }
85}
86
87pub fn check_intersection(a: &SchubertType, b: &SchubertType) -> Intersection {
92 let mut calc = SchubertCalculus::new(a.grassmannian_dim());
93
94 let classes = [a.as_inner().clone(), b.as_inner().clone()];
96 let result = calc.multi_intersect(&classes);
97
98 match result {
99 IntersectionResult::Empty => {
100 let total_codim = a.codimension() + b.codimension();
102 let dim = calc.grassmannian_dimension();
103 if total_codim > dim {
104 Intersection::structural_zero()
105 } else {
106 Intersection::geometric_zero()
107 }
108 }
109 IntersectionResult::Finite(n) => Intersection::positive(n, Vec::new()),
110 IntersectionResult::PositiveDimensional {
111 dimension: _,
112 degree,
113 } => {
114 let multiplicity = degree.unwrap_or(1);
116 Intersection::positive(multiplicity, Vec::new())
117 }
118 }
119}