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}