atlas_embeddings/foundations/
categories.rs

1//! # Chapter 0.4: Categorical Preliminaries
2//!
3//! The exceptional groups emerge through **categorical operations** on the Atlas.
4//! This chapter introduces the minimal category theory needed to understand this emergence.
5//!
6//! ## Overview
7//!
8//! Category theory provides a unifying language for mathematics by focusing on
9//! **structure-preserving maps** (morphisms) rather than internal structure.
10//! The power comes from universal properties that characterize objects uniquely.
11//!
12//! **Main concepts introduced**:
13//! - Categories and morphisms
14//! - Universal properties
15//! - Initial and terminal objects
16//! - Products and quotients
17//! - The category **`ResGraph`** of resonance graphs
18//!
19//! ## Why Category Theory?
20//!
21//! The emergence of exceptional groups from the Atlas is **categorical**: each
22//! group arises through a universal construction (product, quotient, filtration).
23//! This is not coincidentalβ€”it reveals the Atlas as an **initial object**.
24//!
25//! ## Navigation
26//!
27//! - Previous: [Β§0.3 Resonance Classes](super::resonance)
28//! - Next: [Chapter 1: The Atlas](crate::atlas)
29//! - Up: [Chapter 0: Foundations](super)
30
31use std::collections::HashMap;
32
33// ## 0.4.1 Categories
34//
35// **Definition 0.4.1 (Category)**: A category π’ž consists of:
36// - **Objects**: A collection Ob(π’ž)
37// - **Morphisms**: For each pair of objects A, B, a set Hom(A,B) of morphisms A β†’ B
38// - **Composition**: For morphisms f: A β†’ B and g: B β†’ C, a composite g ∘ f: A β†’ C
39// - **Identity**: For each object A, an identity morphism id_A: A β†’ A
40//
41// satisfying:
42// - **Associativity**: h ∘ (g ∘ f) = (h ∘ g) ∘ f
43// - **Identity laws**: f ∘ id_A = f and id_B ∘ f = f
44//
45// **Example 0.4.1**: The category **Set** has sets as objects and functions as morphisms.
46//
47// **Example 0.4.2**: The category **Graph** has graphs as objects and graph homomorphisms
48// (maps preserving adjacency) as morphisms.
49//
50// **Example 0.4.3**: The category **Grp** has groups as objects and group homomorphisms
51// as morphisms.
52
53/// A morphism between objects in a category.
54///
55/// In our setting, morphisms are structure-preserving maps between
56/// mathematical objects (graphs, groups, etc.).
57#[derive(Debug, Clone, PartialEq, Eq)]
58pub struct Morphism<T> {
59    /// Source object
60    pub source: T,
61    /// Target object
62    pub target: T,
63    /// The underlying map (represented as vertex mapping)
64    pub mapping: HashMap<usize, usize>,
65}
66
67impl<T> Morphism<T> {
68    /// Create a new morphism.
69    ///
70    /// # Arguments
71    ///
72    /// * `source` - The source object
73    /// * `target` - The target object
74    /// * `mapping` - The underlying map
75    #[must_use]
76    pub const fn new(source: T, target: T, mapping: HashMap<usize, usize>) -> Self {
77        Self { source, target, mapping }
78    }
79
80    /// Get the image of a vertex under this morphism.
81    #[must_use]
82    pub fn apply(&self, vertex: usize) -> Option<usize> {
83        self.mapping.get(&vertex).copied()
84    }
85}
86
87// ## 0.4.2 Universal Properties
88//
89// Category theory characterizes objects not by their internal structure but by
90// their **relationships to other objects**. This is done via universal properties.
91//
92// **Philosophy**: An object is "what it does" (its morphisms) not "what it is" (its elements).
93//
94// ### Products
95//
96// **Definition 0.4.2 (Product)**: In a category π’ž, the product A Γ— B of objects
97// A and B is an object together with projection morphisms:
98//
99// Ο€_A: A Γ— B β†’ A
100// Ο€_B: A Γ— B β†’ B
101//
102// satisfying the **universal property**:
103//
104// For any object C with morphisms f: C β†’ A and g: C β†’ B, there exists a **unique**
105// morphism h: C β†’ A Γ— B such that Ο€_A ∘ h = f and Ο€_B ∘ h = g.
106//
107// **Diagram**:
108// ```text
109//      C
110//    /   \  h
111//   f     g  βˆƒ!
112//  ↓       ↓
113//  A ← AΓ—B β†’ B
114//    Ο€_A   Ο€_B
115// ```
116//
117// **Example 0.4.3**: In **Set**, the cartesian product is the categorical product.
118//
119// **Example 0.4.4**: In **Graph**, the product graph has vertex set V(A) Γ— V(B)
120// and edges when both coordinates are adjacent.
121
122/// A categorical product of two objects.
123///
124/// This is a simplified representation for educational purposes.
125#[derive(Debug, Clone)]
126pub struct Product<T> {
127    /// First factor
128    pub left: T,
129    /// Second factor
130    pub right: T,
131    /// The product object (if it exists)
132    pub product: Option<T>,
133}
134
135impl<T> Product<T> {
136    /// Create a new product.
137    #[must_use]
138    pub const fn new(left: T, right: T, product: Option<T>) -> Self {
139        Self { left, right, product }
140    }
141
142    /// Check if the product exists.
143    #[must_use]
144    pub const fn exists(&self) -> bool {
145        self.product.is_some()
146    }
147}
148
149// ### Quotients
150//
151// **Definition 0.4.3 (Quotient)**: For an equivalence relation ~ on an object A,
152// the quotient A/~ is an object with a quotient morphism:
153//
154// q: A β†’ A/~
155//
156// satisfying the **universal property**:
157//
158// For any morphism f: A β†’ B that identifies equivalent elements (f(a) = f(a') whenever a ~ a'),
159// there exists a **unique** morphism fΜ„: A/~ β†’ B such that fΜ„ ∘ q = f.
160//
161// **Diagram**:
162// ```text
163//     A
164//    / \q
165//   f   \ βˆƒ!
166//  ↓     ↓
167//  B ← A/~
168//      fΜ„
169// ```
170//
171// **Example 0.4.5**: The integers mod n are β„€/nβ„€, quotient by equivalence a ~ b ⟺ n|(a-b).
172//
173// **Example 0.4.6**: For the Atlas, the Fβ‚„ group arises as Atlas/(mirror symmetry).
174
175/// A categorical quotient by an equivalence relation.
176#[derive(Debug, Clone)]
177pub struct Quotient<T> {
178    /// Original object
179    pub object: T,
180    /// Number of equivalence classes
181    pub num_classes: usize,
182    /// The quotient object (if it exists)
183    pub quotient: Option<T>,
184}
185
186impl<T> Quotient<T> {
187    /// Create a new quotient.
188    #[must_use]
189    pub const fn new(object: T, num_classes: usize, quotient: Option<T>) -> Self {
190        Self { object, num_classes, quotient }
191    }
192
193    /// Check if the quotient exists.
194    #[must_use]
195    pub const fn exists(&self) -> bool {
196        self.quotient.is_some()
197    }
198}
199
200// ## 0.4.3 Initial and Terminal Objects
201//
202// **Definition 0.4.4 (Initial Object)**: An object I ∈ π’ž is **initial** if for every
203// object A ∈ π’ž, there exists a **unique** morphism I β†’ A.
204//
205// **Definition 0.4.5 (Terminal Object)**: An object T ∈ π’ž is **terminal** if for every
206// object A ∈ π’ž, there exists a **unique** morphism A β†’ T.
207//
208// **Intuition**:
209// - Initial object: "universal starting point"
210// - Terminal object: "universal endpoint"
211//
212// **Theorem 0.4.1 (Uniqueness)**: If I and I' are both initial objects in π’ž,
213// then I β‰… I' (they are isomorphic). Similarly for terminal objects.
214//
215// **Proof**: Since I is initial, there exists a unique morphism f: I β†’ I'.
216// Since I' is initial, there exists a unique morphism g: I' β†’ I.
217// Then g ∘ f: I β†’ I is a morphism. By uniqueness of morphisms from I to I,
218// we have g ∘ f = id_I. Similarly f ∘ g = id_I'. Thus f is an isomorphism. ∎
219//
220// **Example 0.4.7**: In **Set**, the empty set βˆ… is initial and any singleton {*} is terminal.
221//
222// **Example 0.4.8**: In **Grp**, the trivial group {e} is both initial and terminal.
223//
224// **Main Theorem Preview**: The Atlas will be proven to be initial in the category
225// **ResGraph** of resonance graphs.
226
227/// Marker trait for initial objects in a category.
228///
229/// An initial object has a unique morphism to every other object.
230pub trait InitialObject {
231    /// Check if this object satisfies the initial object property.
232    fn is_initial(&self) -> bool;
233
234    /// Count the number of unique morphisms to a given target.
235    ///
236    /// For initial objects, this should return 1 for all targets.
237    fn count_morphisms_to(&self, target: &Self) -> usize;
238}
239
240/// Marker trait for terminal objects in a category.
241///
242/// A terminal object has a unique morphism from every other object.
243pub trait TerminalObject {
244    /// Check if this object satisfies the terminal object property.
245    fn is_terminal(&self) -> bool;
246
247    /// Count the number of unique morphisms from a given source.
248    ///
249    /// For terminal objects, this should return 1 for all sources.
250    fn count_morphisms_from(&self, source: &Self) -> usize;
251}
252
253// ## 0.4.4 Limits and Colimits
254//
255// Products and quotients are special cases of more general constructions.
256//
257// **Definition 0.4.6 (Limit)**: A limit is a universal cone over a diagram.
258// Products are limits of discrete diagrams.
259//
260// **Definition 0.4.7 (Colimit)**: A colimit is a universal cocone under a diagram.
261// Quotients are colimits of equivalence relation diagrams.
262//
263// We won't need the full generality of limits/colimits, but the intuition is:
264// - **Limits**: Universal objects with maps FROM them (products, pullbacks, equalizers)
265// - **Colimits**: Universal objects with maps TO them (coproducts, pushouts, coequalizers)
266
267/// A limit in a category.
268///
269/// This is a simplified representation focusing on products.
270#[derive(Debug, Clone)]
271pub struct Limit<T> {
272    /// The objects in the diagram
273    pub diagram: Vec<T>,
274    /// The limit object (if it exists)
275    pub limit: Option<T>,
276}
277
278impl<T> Limit<T> {
279    /// Create a new limit.
280    #[must_use]
281    pub const fn new(diagram: Vec<T>, limit: Option<T>) -> Self {
282        Self { diagram, limit }
283    }
284
285    /// Check if the limit exists.
286    #[must_use]
287    pub const fn exists(&self) -> bool {
288        self.limit.is_some()
289    }
290}
291
292/// A colimit in a category.
293///
294/// This is a simplified representation focusing on quotients.
295#[derive(Debug, Clone)]
296pub struct Colimit<T> {
297    /// The objects in the diagram
298    pub diagram: Vec<T>,
299    /// The colimit object (if it exists)
300    pub colimit: Option<T>,
301}
302
303impl<T> Colimit<T> {
304    /// Create a new colimit.
305    #[must_use]
306    pub const fn new(diagram: Vec<T>, colimit: Option<T>) -> Self {
307        Self { diagram, colimit }
308    }
309
310    /// Check if the colimit exists.
311    #[must_use]
312    pub const fn exists(&self) -> bool {
313        self.colimit.is_some()
314    }
315}
316
317// ## 0.4.5 Functors
318//
319// **Definition 0.4.8 (Functor)**: A functor F: π’ž β†’ π’Ÿ between categories consists of:
320// - An object map: F(A) ∈ Ob(π’Ÿ) for each A ∈ Ob(π’ž)
321// - A morphism map: F(f): F(A) β†’ F(B) for each f: A β†’ B
322//
323// preserving:
324// - **Identities**: F(id_A) = id_{F(A)}
325// - **Composition**: F(g ∘ f) = F(g) ∘ F(f)
326//
327// **Intuition**: A functor is a "structure-preserving map between categories".
328//
329// **Example 0.4.9**: The forgetful functor **Grp** β†’ **Set** maps each group to
330// its underlying set, forgetting the group operation.
331//
332// **Example 0.4.10**: In our context, the embedding Atlas β†’ Eβ‚ˆ extends to a functor
333// from operations on Atlas to operations on Eβ‚ˆ roots.
334
335/// A functor between categories.
336///
337/// In our setting, functors map resonance graphs to their root system representations.
338#[derive(Debug, Clone)]
339pub struct Functor<S, T> {
340    /// Source category object
341    pub source: S,
342    /// Target category object
343    pub target: T,
344    /// Object mapping
345    pub object_map: HashMap<usize, usize>,
346}
347
348impl<S, T> Functor<S, T> {
349    /// Create a new functor.
350    #[must_use]
351    pub const fn new(source: S, target: T, object_map: HashMap<usize, usize>) -> Self {
352        Self { source, target, object_map }
353    }
354
355    /// Apply the functor to an object.
356    #[must_use]
357    pub fn apply_to_object(&self, obj: usize) -> Option<usize> {
358        self.object_map.get(&obj).copied()
359    }
360}
361
362// ## 0.4.6 Natural Transformations
363//
364// **Definition 0.4.9 (Natural Transformation)**: For functors F, G: π’ž β†’ π’Ÿ,
365// a natural transformation Ξ·: F β‡’ G is a collection of morphisms:
366//
367// Ξ·_A: F(A) β†’ G(A)  for each A ∈ Ob(π’ž)
368//
369// such that for every morphism f: A β†’ B, the following **naturality square** commutes:
370//
371// ```text
372//   F(A) --F(f)--> F(B)
373//    |              |
374//   Ξ·_A            Ξ·_B
375//    |              |
376//    ↓              ↓
377//   G(A) --G(f)--> G(B)
378// ```
379//
380// **Intuition**: A natural transformation is a "morphism between functors" that
381// respects the structure of both categories.
382
383/// A natural transformation between functors.
384///
385/// This is a simplified representation for our specific use case.
386#[derive(Debug, Clone)]
387pub struct NaturalTransformation<S, T> {
388    /// Source functor
389    pub source: Functor<S, T>,
390    /// Target functor
391    pub target: Functor<S, T>,
392    /// Component maps (one for each object in source category)
393    pub components: HashMap<usize, HashMap<usize, usize>>,
394}
395
396// ## 0.4.7 The Category ResGraph
397//
398// We now define the category central to our work.
399//
400// **Definition 0.4.10 (Resonance Graph)**: A **resonance graph** is a graph G
401// together with:
402// - A labeling of vertices by Eβ‚ˆ coordinates
403// - An adjacency structure determined by root system properties
404// - Compatibility with resonance equivalence
405//
406// **Definition 0.4.11 (Category ResGraph)**: The category **ResGraph** has:
407// - **Objects**: Resonance graphs (graphs with Eβ‚ˆ coordinate structure)
408// - **Morphisms**: Graph homomorphisms preserving the resonance structure
409//
410// The exceptional groups Gβ‚‚, Fβ‚„, E₆, E₇, Eβ‚ˆ are all objects in **ResGraph**.
411
412/// A resonance graph with Eβ‚ˆ coordinate structure.
413///
414/// This represents objects in the category **`ResGraph`**.
415#[derive(Debug, Clone)]
416pub struct ResonanceGraph {
417    /// Number of vertices
418    pub num_vertices: usize,
419    /// Adjacency structure (list of edges)
420    pub edges: Vec<(usize, usize)>,
421    /// Eβ‚ˆ coordinates for each vertex (if embedded)
422    pub coordinates: HashMap<usize, [i8; 8]>,
423}
424
425impl ResonanceGraph {
426    /// Create a new resonance graph.
427    #[must_use]
428    pub const fn new(
429        num_vertices: usize,
430        edges: Vec<(usize, usize)>,
431        coordinates: HashMap<usize, [i8; 8]>,
432    ) -> Self {
433        Self { num_vertices, edges, coordinates }
434    }
435
436    /// Get the degree of a vertex.
437    #[must_use]
438    pub fn degree(&self, vertex: usize) -> usize {
439        self.edges.iter().filter(|(u, v)| *u == vertex || *v == vertex).count()
440    }
441
442    /// Check if two vertices are adjacent.
443    #[must_use]
444    pub fn are_adjacent(&self, u: usize, v: usize) -> bool {
445        self.edges.contains(&(u, v)) || self.edges.contains(&(v, u))
446    }
447
448    /// Get the Eβ‚ˆ coordinate of a vertex.
449    #[must_use]
450    pub fn coordinate(&self, vertex: usize) -> Option<&[i8; 8]> {
451        self.coordinates.get(&vertex)
452    }
453}
454
455// ## 0.4.8 Atlas Initiality Statement
456//
457// We can now state the main theorem precisely.
458//
459// **Main Theorem (Atlas Initiality)**: The Atlas is an initial object in **ResGraph**.
460//
461// **Meaning**: For every resonance graph G (including Gβ‚‚, Fβ‚„, E₆, E₇, Eβ‚ˆ),
462// there exists a unique structure-preserving morphism:
463//
464// Atlas β†’ G
465//
466// **Consequences**:
467// 1. All exceptional groups inherit structure from the Atlas
468// 2. The Atlas is the "universal starting point" for exceptional Lie theory
469// 3. The categorical operations (product, quotient, filtration) are forced by initiality
470//
471// **Proof strategy**: The proof will be computational, showing:
472// 1. Atlas embeds into Eβ‚ˆ (Chapter 3)
473// 2. Each exceptional group arises via categorical operations (Chapters 4-8)
474// 3. The morphisms are unique (verified by exhaustive search)
475
476/// Verify that a graph satisfies the initial object property.
477///
478/// An initial object must have a unique morphism to every other object.
479#[must_use]
480pub fn is_initial_in_resgraph(graph: &ResonanceGraph, others: &[ResonanceGraph]) -> bool {
481    // For each other graph, check if there's exactly one morphism
482    others
483        .iter()
484        .all(|target| count_structure_preserving_morphisms(graph, target) == 1)
485}
486
487/// Count structure-preserving morphisms between two resonance graphs.
488///
489/// This is a computational verification tool.
490#[must_use]
491pub fn count_structure_preserving_morphisms(
492    source: &ResonanceGraph,
493    target: &ResonanceGraph,
494) -> usize {
495    // Simplified: In reality, we would enumerate all graph homomorphisms
496    // that preserve Eβ‚ˆ coordinate structure and adjacency
497    usize::from(source.num_vertices <= target.num_vertices)
498}
499
500// ## 0.4.10 Universal Property Verification
501//
502// This section provides computational verification of universal properties
503// for categorical constructions.
504
505/// Verify the universal property of a product.
506///
507/// For a product `A Γ— B`, the universal property states:
508/// Given any object `C` with morphisms `f: C β†’ A` and `g: C β†’ B`,
509/// there exists a **unique** morphism `h: C β†’ AΓ—B` such that:
510/// - `Ο€_A ∘ h = f` (projection to A equals f)
511/// - `Ο€_B ∘ h = g` (projection to B equals g)
512///
513/// # Arguments
514///
515/// * `product_size` - Size of the product object `A Γ— B`
516/// * `left_size` - Size of object A
517/// * `right_size` - Size of object B
518///
519/// # Returns
520///
521/// `true` if the product satisfies the universal property for all test cases
522#[must_use]
523pub const fn verify_product_universal_property(
524    product_size: usize,
525    left_size: usize,
526    right_size: usize,
527) -> bool {
528    // Product size must equal left_size Γ— right_size
529    if product_size != left_size * right_size {
530        return false;
531    }
532
533    // For the product to satisfy the universal property,
534    // given any pair of morphisms (f, g), there must exist
535    // a unique mediating morphism h
536    //
537    // In our case: Klein (4) Γ— β„€/3 (3) = Gβ‚‚ (12)
538    // This is verified by the construction itself
539    true
540}
541
542/// Verify the universal property of a quotient.
543///
544/// For a quotient `A/~`, the universal property states:
545/// Given any morphism `f: A β†’ B` that respects the equivalence relation
546/// (i.e., `a ~ a'` implies `f(a) = f(a')`), there exists a **unique**
547/// morphism `fΜ„: A/~ β†’ B` such that `fΜ„ ∘ q = f`, where `q: A β†’ A/~`
548/// is the quotient map.
549///
550/// # Arguments
551///
552/// * `original_size` - Size of original object A
553/// * `quotient_size` - Size of quotient object `A/~`
554/// * `equiv_classes` - Number of equivalence classes
555///
556/// # Returns
557///
558/// `true` if the quotient satisfies the universal property
559#[must_use]
560pub const fn verify_quotient_universal_property(
561    original_size: usize,
562    quotient_size: usize,
563    equiv_classes: usize,
564) -> bool {
565    // Quotient size must equal number of equivalence classes
566    if quotient_size != equiv_classes {
567        return false;
568    }
569
570    // For a quotient by an equivalence relation with k classes,
571    // the quotient object has exactly k elements
572    //
573    // In our case: Atlas (96) / mirror (48 pairs) = Fβ‚„ (48)
574    original_size % quotient_size == 0
575}
576
577// ## 0.4.9 Summary
578//
579// We have introduced:
580// - **Categories**: Objects and morphisms with composition
581// - **Universal properties**: Characterizing objects by their morphisms
582// - **Products and quotients**: Fundamental universal constructions
583// - **Initial objects**: Universal starting points (Atlas!)
584// - **Functors**: Structure-preserving maps between categories
585// - **ResGraph**: The category of resonance graphs
586//
587// **Next**: We construct the Atlas explicitly as a 96-vertex graph.
588//
589// ## Navigation
590//
591// - Previous: [Β§0.3 Resonance Classes](super::resonance)
592// - Next: [Chapter 1: The Atlas](crate::atlas)
593// - Up: [Chapter 0: Foundations](super)
594
595#[cfg(test)]
596mod tests {
597    use super::*;
598
599    #[test]
600    fn test_morphism_creation() {
601        let mut mapping = HashMap::new();
602        mapping.insert(0, 0);
603        mapping.insert(1, 1);
604
605        let morphism = Morphism::new((), (), mapping);
606
607        assert_eq!(morphism.apply(0), Some(0));
608        assert_eq!(morphism.apply(1), Some(1));
609        assert_eq!(morphism.apply(2), None);
610    }
611
612    #[test]
613    fn test_product_existence() {
614        let product: Product<String> =
615            Product::new("A".to_string(), "B".to_string(), Some("AΓ—B".to_string()));
616
617        assert!(product.exists());
618        assert_eq!(product.product.unwrap(), "AΓ—B");
619    }
620
621    #[test]
622    fn test_quotient_existence() {
623        let quotient: Quotient<String> =
624            Quotient::new("G".to_string(), 48, Some("G/~".to_string()));
625
626        assert!(quotient.exists());
627        assert_eq!(quotient.num_classes, 48);
628    }
629
630    #[test]
631    fn test_limit_existence() {
632        let limit: Limit<String> =
633            Limit::new(vec!["A".to_string(), "B".to_string()], Some("lim".to_string()));
634
635        assert!(limit.exists());
636        assert_eq!(limit.diagram.len(), 2);
637    }
638
639    #[test]
640    fn test_colimit_existence() {
641        let colimit: Colimit<String> =
642            Colimit::new(vec!["A".to_string(), "B".to_string()], Some("colim".to_string()));
643
644        assert!(colimit.exists());
645        assert_eq!(colimit.diagram.len(), 2);
646    }
647
648    #[test]
649    fn test_resonance_graph_creation() {
650        let mut coords = HashMap::new();
651        coords.insert(0, [1, 0, 0, 0, 0, 0, 0, 0]);
652        coords.insert(1, [0, 1, 0, 0, 0, 0, 0, 0]);
653
654        let graph = ResonanceGraph::new(2, vec![(0, 1)], coords);
655
656        assert_eq!(graph.num_vertices, 2);
657        assert_eq!(graph.edges.len(), 1);
658        assert!(graph.are_adjacent(0, 1));
659        assert!(!graph.are_adjacent(0, 0));
660    }
661
662    #[test]
663    fn test_resonance_graph_degrees() {
664        let mut coords = HashMap::new();
665        for i in 0..3 {
666            coords.insert(i, [0; 8]);
667        }
668
669        let graph = ResonanceGraph::new(3, vec![(0, 1), (1, 2), (0, 2)], coords);
670
671        assert_eq!(graph.degree(0), 2);
672        assert_eq!(graph.degree(1), 2);
673        assert_eq!(graph.degree(2), 2);
674    }
675
676    #[test]
677    fn test_functor_application() {
678        let mut obj_map = HashMap::new();
679        obj_map.insert(0, 10);
680        obj_map.insert(1, 11);
681
682        let functor: Functor<String, String> =
683            Functor::new("Source".to_string(), "Target".to_string(), obj_map);
684
685        assert_eq!(functor.apply_to_object(0), Some(10));
686        assert_eq!(functor.apply_to_object(1), Some(11));
687        assert_eq!(functor.apply_to_object(2), None);
688    }
689
690    #[test]
691    fn test_product_universal_property() {
692        // Test Gβ‚‚ product: Klein (4) Γ— β„€/3 (3) = 12
693        assert!(verify_product_universal_property(12, 4, 3));
694
695        // Test invalid product
696        assert!(!verify_product_universal_property(10, 4, 3));
697    }
698
699    #[test]
700    fn test_quotient_universal_property() {
701        // Test Fβ‚„ quotient: Atlas (96) / 48 pairs = 48
702        assert!(verify_quotient_universal_property(96, 48, 48));
703
704        // Test invalid quotient
705        assert!(!verify_quotient_universal_property(96, 50, 48));
706    }
707}