Skip to main content

amari_enumerative/
phantom.rs

1//! Phantom types for compile-time verification of enumerative geometry properties.
2//!
3//! This module provides zero-cost phantom types that encode mathematical properties
4//! of partitions, tableaux, and Schubert classes at the type level.
5//!
6//! # Partition Validity
7//!
8//! - [`ValidPartition`]: Partition has been validated (weakly decreasing, positive parts)
9//! - [`UnvalidatedPartition`]: Partition has not been validated
10//!
11//! # Tableau Properties
12//!
13//! - [`Semistandard`]: Tableau satisfies semistandard conditions
14//! - [`LatticeWord`]: Tableau satisfies lattice word condition
15//!
16//! # Capability States
17//!
18//! - [`Granted`]: Capability has been granted to a namespace
19//! - [`Pending`]: Capability is pending grant approval
20//!
21//! # Intersection States
22//!
23//! - [`Transverse`]: Intersection is transverse (codimensions sum to dimension)
24//! - [`Excess`]: Intersection is overdetermined
25
26use core::marker::PhantomData;
27
28// Sealed trait pattern to prevent external implementations
29mod private {
30    pub trait Sealed {}
31}
32
33// ============================================================================
34// Partition Validity Properties
35// ============================================================================
36
37/// Marker trait for partition validity states.
38pub trait PartitionValidity: private::Sealed + Clone + Copy + Default + 'static {}
39
40/// Valid partition: weakly decreasing positive integers.
41///
42/// A partition λ = (λ_1, λ_2, ..., λ_k) where λ_1 ≥ λ_2 ≥ ... ≥ λ_k > 0.
43#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)]
44pub struct ValidPartition;
45
46impl private::Sealed for ValidPartition {}
47impl PartitionValidity for ValidPartition {}
48
49/// Unvalidated partition: may not satisfy partition constraints.
50#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)]
51pub struct UnvalidatedPartition;
52
53impl private::Sealed for UnvalidatedPartition {}
54impl PartitionValidity for UnvalidatedPartition {}
55
56// ============================================================================
57// Tableau Properties
58// ============================================================================
59
60/// Marker trait for tableau validity states.
61pub trait TableauValidity: private::Sealed + Clone + Copy + Default + 'static {}
62
63/// Semistandard tableau: rows weakly increasing, columns strictly increasing.
64#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)]
65pub struct Semistandard;
66
67impl private::Sealed for Semistandard {}
68impl TableauValidity for Semistandard {}
69
70/// Tableau satisfies the lattice word (Yamanouchi) condition.
71#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)]
72pub struct LatticeWord;
73
74impl private::Sealed for LatticeWord {}
75impl TableauValidity for LatticeWord {}
76
77/// Unverified tableau: validity not yet checked.
78#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)]
79pub struct UnverifiedTableau;
80
81impl private::Sealed for UnverifiedTableau {}
82impl TableauValidity for UnverifiedTableau {}
83
84// ============================================================================
85// Capability Grant States
86// ============================================================================
87
88/// Marker trait for capability grant states.
89pub trait GrantState: private::Sealed + Clone + Copy + Default + 'static {}
90
91/// Capability has been granted and is active.
92#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)]
93pub struct Granted;
94
95impl private::Sealed for Granted {}
96impl GrantState for Granted {}
97
98/// Capability is pending grant (dependencies not yet satisfied).
99#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)]
100pub struct Pending;
101
102impl private::Sealed for Pending {}
103impl GrantState for Pending {}
104
105/// Capability is revoked.
106#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)]
107pub struct Revoked;
108
109impl private::Sealed for Revoked {}
110impl GrantState for Revoked {}
111
112// ============================================================================
113// Intersection Properties
114// ============================================================================
115
116/// Marker trait for intersection dimension properties.
117pub trait IntersectionDimension: private::Sealed + Clone + Copy + Default + 'static {}
118
119/// Transverse intersection: codimensions sum to ambient dimension.
120///
121/// The expected number of intersection points is finite.
122#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)]
123pub struct Transverse;
124
125impl private::Sealed for Transverse {}
126impl IntersectionDimension for Transverse {}
127
128/// Excess intersection: codimensions sum exceeds ambient dimension.
129///
130/// The intersection is generically empty.
131#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)]
132pub struct Excess;
133
134impl private::Sealed for Excess {}
135impl IntersectionDimension for Excess {}
136
137/// Deficient intersection: codimensions sum is less than ambient dimension.
138///
139/// The intersection has positive dimension.
140#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)]
141pub struct Deficient;
142
143impl private::Sealed for Deficient {}
144impl IntersectionDimension for Deficient {}
145
146/// Unknown intersection dimension (not yet computed).
147#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)]
148pub struct UnknownDimension;
149
150impl private::Sealed for UnknownDimension {}
151impl IntersectionDimension for UnknownDimension {}
152
153// ============================================================================
154// Grassmannian Containment
155// ============================================================================
156
157/// Marker trait for partition containment in a Grassmannian box.
158pub trait BoxContainment: private::Sealed + Clone + Copy + Default + 'static {}
159
160/// Partition fits in k × (n-k) box.
161#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)]
162pub struct FitsInBox;
163
164impl private::Sealed for FitsInBox {}
165impl BoxContainment for FitsInBox {}
166
167/// Partition may not fit in box (not verified).
168#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)]
169pub struct UnverifiedBox;
170
171impl private::Sealed for UnverifiedBox {}
172impl BoxContainment for UnverifiedBox {}
173
174// ============================================================================
175// Type Aliases for Common Combinations
176// ============================================================================
177
178/// A valid LR tableau (semistandard + lattice word condition).
179pub type ValidLRTableau = (Semistandard, LatticeWord);
180
181/// A Schubert class verified to fit in a Grassmannian.
182pub type ValidSchubertClass = (ValidPartition, FitsInBox);
183
184/// Properties wrapper for zero-cost phantom data.
185#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)]
186pub struct Properties<T>(PhantomData<T>);
187
188impl<T> Properties<T> {
189    /// Create a new properties marker.
190    #[must_use]
191    pub const fn new() -> Self {
192        Self(PhantomData)
193    }
194}
195
196#[cfg(test)]
197mod tests {
198    use super::*;
199    use core::mem::size_of;
200
201    #[test]
202    fn test_phantom_types_are_zero_sized() {
203        assert_eq!(size_of::<ValidPartition>(), 0);
204        assert_eq!(size_of::<UnvalidatedPartition>(), 0);
205        assert_eq!(size_of::<Semistandard>(), 0);
206        assert_eq!(size_of::<LatticeWord>(), 0);
207        assert_eq!(size_of::<Granted>(), 0);
208        assert_eq!(size_of::<Pending>(), 0);
209        assert_eq!(size_of::<Transverse>(), 0);
210        assert_eq!(size_of::<FitsInBox>(), 0);
211        assert_eq!(size_of::<Properties<ValidLRTableau>>(), 0);
212    }
213
214    #[test]
215    fn test_phantom_types_implement_traits() {
216        fn assert_partition_validity<T: PartitionValidity>() {}
217        fn assert_tableau_validity<T: TableauValidity>() {}
218        fn assert_grant_state<T: GrantState>() {}
219        fn assert_intersection_dim<T: IntersectionDimension>() {}
220        fn assert_box_containment<T: BoxContainment>() {}
221
222        assert_partition_validity::<ValidPartition>();
223        assert_partition_validity::<UnvalidatedPartition>();
224
225        assert_tableau_validity::<Semistandard>();
226        assert_tableau_validity::<LatticeWord>();
227        assert_tableau_validity::<UnverifiedTableau>();
228
229        assert_grant_state::<Granted>();
230        assert_grant_state::<Pending>();
231        assert_grant_state::<Revoked>();
232
233        assert_intersection_dim::<Transverse>();
234        assert_intersection_dim::<Excess>();
235        assert_intersection_dim::<Deficient>();
236
237        assert_box_containment::<FitsInBox>();
238        assert_box_containment::<UnverifiedBox>();
239    }
240
241    #[test]
242    fn test_phantom_types_are_copy() {
243        let v1 = ValidPartition;
244        let v2 = v1;
245        assert_eq!(v1, v2);
246
247        let s1 = Semistandard;
248        let s2 = s1;
249        assert_eq!(s1, s2);
250    }
251}