1use super::functions::*;
5
6#[allow(dead_code)]
8#[derive(Debug, Clone)]
9pub struct NoetherianRing {
10 pub name: String,
11 pub krull_dimension: Option<usize>,
12}
13impl NoetherianRing {
14 #[allow(dead_code)]
15 pub fn new(name: &str, krull_dim: Option<usize>) -> Self {
16 Self {
17 name: name.to_string(),
18 krull_dimension: krull_dim,
19 }
20 }
21 #[allow(dead_code)]
22 pub fn hilbert_basis_theorem(&self) -> String {
23 format!(
24 "If {} is Noetherian, then {}[x] is Noetherian",
25 self.name, self.name
26 )
27 }
28 #[allow(dead_code)]
29 pub fn primary_decomposition_exists(&self) -> bool {
30 true
31 }
32 #[allow(dead_code)]
33 pub fn krull_dimension_description(&self) -> String {
34 match self.krull_dimension {
35 Some(d) => {
36 format!("dim({}) = {} (max length of chain of primes)", self.name, d)
37 }
38 None => format!("dim({}) = infinity", self.name),
39 }
40 }
41}
42#[allow(dead_code)]
44#[derive(Debug, Clone)]
45pub struct Module {
46 pub ring: String,
47 pub name: String,
48 pub is_free: bool,
49 pub rank: Option<usize>,
50 pub is_finitely_generated: bool,
51}
52impl Module {
53 #[allow(dead_code)]
54 pub fn free(ring: &str, name: &str, rank: usize) -> Self {
55 Self {
56 ring: ring.to_string(),
57 name: name.to_string(),
58 is_free: true,
59 rank: Some(rank),
60 is_finitely_generated: true,
61 }
62 }
63 #[allow(dead_code)]
64 pub fn cyclic(ring: &str, name: &str) -> Self {
65 Self {
66 ring: ring.to_string(),
67 name: name.to_string(),
68 is_free: false,
69 rank: Some(1),
70 is_finitely_generated: true,
71 }
72 }
73 #[allow(dead_code)]
74 pub fn over_pid_structure_theorem(&self) -> String {
75 format!(
76 "M ~ R^r + R/d1R + ... + R/dk*R (invariant factors) over PID {}",
77 self.ring
78 )
79 }
80 #[allow(dead_code)]
81 pub fn is_projective(&self) -> bool {
82 self.is_free
83 }
84 #[allow(dead_code)]
85 pub fn is_flat(&self) -> bool {
86 self.is_projective()
87 }
88}
89#[allow(dead_code)]
91#[derive(Debug, Clone)]
92pub struct GaloisExtension {
93 pub base_field: String,
94 pub extension_field: String,
95 pub galois_group: String,
96 pub degree: usize,
97}
98impl GaloisExtension {
99 #[allow(dead_code)]
100 pub fn new(base: &str, ext: &str, gal: &str, degree: usize) -> Self {
101 Self {
102 base_field: base.to_string(),
103 extension_field: ext.to_string(),
104 galois_group: gal.to_string(),
105 degree,
106 }
107 }
108 #[allow(dead_code)]
109 pub fn cyclotomic(n: usize) -> Self {
110 Self {
111 base_field: "Q".to_string(),
112 extension_field: format!("Q(zeta_{n})"),
113 galois_group: format!("(Z/{}Z)*", n),
114 degree: euler_phi_algebra(n as u64) as usize,
115 }
116 }
117 #[allow(dead_code)]
118 pub fn fundamental_theorem(&self) -> String {
119 format!(
120 "Subgroups of Gal({}/{}) <-> subfields between {} and {}",
121 self.extension_field, self.base_field, self.base_field, self.extension_field
122 )
123 }
124 #[allow(dead_code)]
125 pub fn is_abelian_extension(&self) -> bool {
126 self.galois_group.contains("Z") || self.galois_group.contains("abelian")
127 }
128}
129#[allow(dead_code)]
131#[derive(Debug, Clone)]
132pub struct ShortExactSequence {
133 pub a: String,
134 pub b: String,
135 pub c: String,
136}
137impl ShortExactSequence {
138 #[allow(dead_code)]
139 pub fn new(a: &str, b: &str, c: &str) -> Self {
140 Self {
141 a: a.to_string(),
142 b: b.to_string(),
143 c: c.to_string(),
144 }
145 }
146 #[allow(dead_code)]
147 pub fn display(&self) -> String {
148 format!("0 -> {} -> {} -> {} -> 0", self.a, self.b, self.c)
149 }
150 #[allow(dead_code)]
151 pub fn is_split(&self) -> bool {
152 self.b.contains('+') || self.b.contains("oplus")
153 }
154}
155#[allow(dead_code)]
157#[derive(Debug, Clone)]
158pub struct GradedRing {
159 pub name: String,
160 pub grading_monoid: String,
161 pub is_commutative: bool,
162}
163impl GradedRing {
164 #[allow(dead_code)]
165 pub fn polynomial_ring(vars: &[&str]) -> Self {
166 Self {
167 name: format!("k[{}]", vars.join(",")),
168 grading_monoid: "N (by total degree)".to_string(),
169 is_commutative: true,
170 }
171 }
172 #[allow(dead_code)]
173 pub fn exterior_algebra(n: usize) -> Self {
174 Self {
175 name: format!("Lambda^* (n={n})"),
176 grading_monoid: "Z (by degree)".to_string(),
177 is_commutative: false,
178 }
179 }
180 #[allow(dead_code)]
181 pub fn is_noetherian(&self) -> bool {
182 true
183 }
184 #[allow(dead_code)]
185 pub fn hilbert_series_description(&self) -> String {
186 format!("H({}, t) = sum dim(R_n) t^n for {}", self.name, self.name)
187 }
188}
189#[allow(dead_code)]
191#[derive(Debug, Clone)]
192pub struct ProjectiveResolution {
193 pub module: String,
194 pub projective_dimension: Option<usize>,
195 pub length: usize,
196}
197impl ProjectiveResolution {
198 #[allow(dead_code)]
199 pub fn new(module: &str, pd: Option<usize>, len: usize) -> Self {
200 Self {
201 module: module.to_string(),
202 projective_dimension: pd,
203 length: len,
204 }
205 }
206 #[allow(dead_code)]
207 pub fn is_finite(&self) -> bool {
208 self.projective_dimension.is_some()
209 }
210 #[allow(dead_code)]
211 pub fn global_dimension_description(&self) -> String {
212 format!("gldim(R) = sup over M of pd(M) for all R-modules M")
213 }
214}
215#[allow(dead_code)]
217#[derive(Debug, Clone)]
218pub struct DerivedCategory {
219 pub abelian_category: String,
220}
221impl DerivedCategory {
222 #[allow(dead_code)]
223 pub fn new(cat: &str) -> Self {
224 Self {
225 abelian_category: cat.to_string(),
226 }
227 }
228 #[allow(dead_code)]
229 pub fn objects_are_complexes(&self) -> bool {
230 true
231 }
232 #[allow(dead_code)]
233 pub fn localization_description(&self) -> String {
234 format!(
235 "D({}) = K({})[quasi-isomorphisms^-1]",
236 self.abelian_category, self.abelian_category
237 )
238 }
239 #[allow(dead_code)]
240 pub fn t_structure_heart(&self) -> String {
241 format!(
242 "Heart of standard t-structure on D({}) = {}",
243 self.abelian_category, self.abelian_category
244 )
245 }
246}
247#[allow(dead_code)]
249#[derive(Debug, Clone)]
250pub struct AbelianCategory {
251 pub name: String,
252 pub has_zero_object: bool,
253 pub has_biproducts: bool,
254 pub every_morphism_has_kernel_cokernel: bool,
255}
256impl AbelianCategory {
257 #[allow(dead_code)]
258 pub fn new(name: &str) -> Self {
259 Self {
260 name: name.to_string(),
261 has_zero_object: true,
262 has_biproducts: true,
263 every_morphism_has_kernel_cokernel: true,
264 }
265 }
266 #[allow(dead_code)]
267 pub fn of_modules(ring: &str) -> Self {
268 Self::new(&format!("R-Mod (R={})", ring))
269 }
270 #[allow(dead_code)]
271 pub fn snake_lemma(&self) -> String {
272 "Snake lemma: long exact sequence from short exact sequences in an abelian category"
273 .to_string()
274 }
275 #[allow(dead_code)]
276 pub fn five_lemma(&self) -> String {
277 "Five lemma: if 4 maps are isomorphisms, the middle one is too".to_string()
278 }
279}
280#[allow(dead_code)]
282#[derive(Debug, Clone)]
283pub struct LieAlgebra {
284 pub name: String,
285 pub dimension: usize,
286 pub is_semisimple: bool,
287 pub is_nilpotent: bool,
288 pub is_solvable: bool,
289}
290impl LieAlgebra {
291 #[allow(dead_code)]
292 pub fn sl_n(n: usize) -> Self {
293 Self {
294 name: format!("sl({n})"),
295 dimension: n * n - 1,
296 is_semisimple: true,
297 is_nilpotent: false,
298 is_solvable: false,
299 }
300 }
301 #[allow(dead_code)]
302 pub fn heisenberg(n: usize) -> Self {
303 Self {
304 name: format!("h_{n} (Heisenberg)"),
305 dimension: 2 * n + 1,
306 is_semisimple: false,
307 is_nilpotent: true,
308 is_solvable: true,
309 }
310 }
311 #[allow(dead_code)]
312 pub fn abelian(n: usize) -> Self {
313 Self {
314 name: format!("k^{n} (abelian)"),
315 dimension: n,
316 is_semisimple: false,
317 is_nilpotent: true,
318 is_solvable: true,
319 }
320 }
321 #[allow(dead_code)]
322 pub fn engel_theorem(&self) -> String {
323 "Engel's theorem: g nilpotent iff all adj(x) are nilpotent endomorphisms".to_string()
324 }
325 #[allow(dead_code)]
326 pub fn lies_theorem(&self) -> String {
327 "Lie's theorem: solvable Lie algebra acts by upper triangular matrices (over alg. closed field)"
328 .to_string()
329 }
330 #[allow(dead_code)]
331 pub fn cartan_criterion(&self) -> String {
332 format!(
333 "{} is semisimple iff its Killing form is non-degenerate",
334 self.name
335 )
336 }
337}
338#[allow(dead_code)]
340#[derive(Debug, Clone)]
341pub struct ExtTorGroups {
342 pub ring: String,
343 pub module_m: String,
344 pub module_n: String,
345}
346impl ExtTorGroups {
347 #[allow(dead_code)]
348 pub fn new(ring: &str, m: &str, n: &str) -> Self {
349 Self {
350 ring: ring.to_string(),
351 module_m: m.to_string(),
352 module_n: n.to_string(),
353 }
354 }
355 #[allow(dead_code)]
356 pub fn ext_description(&self) -> String {
357 format!(
358 "Ext^n_{{{}}}({},{}) = derived functor of Hom, classifies n-fold extensions",
359 self.ring, self.module_m, self.module_n
360 )
361 }
362 #[allow(dead_code)]
363 pub fn tor_description(&self) -> String {
364 format!(
365 "Tor^n_{{{}}}({},{}) = derived functor of tensor, measures flatness failure",
366 self.ring, self.module_m, self.module_n
367 )
368 }
369 #[allow(dead_code)]
370 pub fn short_exact_sequence_long_ext(&self) -> String {
371 "0 -> Hom(M,N) -> ... -> Ext^1(M,N) -> ... long exact sequence".to_string()
372 }
373}
374#[allow(dead_code)]
376#[derive(Debug, Clone)]
377pub struct Localization {
378 pub ring: String,
379 pub multiplicative_set: String,
380 pub localized_ring: String,
381}
382impl Localization {
383 #[allow(dead_code)]
384 pub fn at_prime(ring: &str, prime: &str) -> Self {
385 Self {
386 ring: ring.to_string(),
387 multiplicative_set: format!("{ring} \\ {prime}"),
388 localized_ring: format!("{ring}_{prime}"),
389 }
390 }
391 #[allow(dead_code)]
392 pub fn away_from(ring: &str, element: &str) -> Self {
393 Self {
394 ring: ring.to_string(),
395 multiplicative_set: format!("powers of {element}"),
396 localized_ring: format!("{ring}[1/{element}]"),
397 }
398 }
399 #[allow(dead_code)]
400 pub fn universal_property(&self) -> String {
401 format!(
402 "S^-1 {}: maps to rings where S is invertible factor uniquely through {}",
403 self.ring, self.localized_ring
404 )
405 }
406}
407#[allow(dead_code)]
409#[derive(Debug, Clone)]
410pub struct TensorProduct {
411 pub module_a: String,
412 pub module_b: String,
413 pub ring: String,
414}
415impl TensorProduct {
416 #[allow(dead_code)]
417 pub fn new(a: &str, b: &str, ring: &str) -> Self {
418 Self {
419 module_a: a.to_string(),
420 module_b: b.to_string(),
421 ring: ring.to_string(),
422 }
423 }
424 #[allow(dead_code)]
425 pub fn right_exact_description(&self) -> String {
426 format!(
427 "- tensor_R {} is right exact (M' -> M -> M'' -> 0 stays exact) over {}",
428 self.module_b, self.ring
429 )
430 }
431 #[allow(dead_code)]
432 pub fn adjunction_hom_tensor(&self) -> String {
433 format!(
434 "Hom_R(A tensor_R B, C) = Hom_R(A, Hom_R(B, C)) for {},{},{} over {}",
435 self.module_a, self.module_b, "C", self.ring
436 )
437 }
438}