1use super::functions::*;
6pub struct OrdinalType {
8 pub base_omega_power: u64,
9 pub coefficient: u64,
10 pub lower: Box<Option<String>>,
11}
12impl OrdinalType {
13 pub fn new(base_omega_power: u64, coefficient: u64, lower: Option<String>) -> Self {
14 Self {
15 base_omega_power,
16 coefficient,
17 lower: Box::new(lower),
18 }
19 }
20 pub fn cantor_normal_form(&self) -> String {
22 let base = if self.base_omega_power == 0 {
23 format!("{}", self.coefficient)
24 } else if self.base_omega_power == 1 {
25 format!("ω·{}", self.coefficient)
26 } else {
27 format!("ω^{}·{}", self.base_omega_power, self.coefficient)
28 };
29 match self.lower.as_ref() {
30 None => base,
31 Some(l) => format!("{} + {}", base, l),
32 }
33 }
34 pub fn is_successor(&self) -> bool {
36 self.base_omega_power == 0 && self.coefficient > 0
37 || self
38 .lower
39 .as_deref()
40 .map(|l| !l.is_empty())
41 .unwrap_or(false)
42 }
43 pub fn is_limit(&self) -> bool {
45 self.base_omega_power > 0 && !self.is_successor()
46 }
47}
48#[derive(Debug, Clone, Copy, PartialEq, Eq)]
50pub enum Sign {
51 Plus,
52 Minus,
53}
54impl Sign {
55 pub fn negate(self) -> Self {
57 match self {
58 Sign::Plus => Sign::Minus,
59 Sign::Minus => Sign::Plus,
60 }
61 }
62}
63pub struct GameValue {
65 pub left_options: Vec<String>,
66 pub right_options: Vec<String>,
67}
68impl GameValue {
69 pub fn new(left_options: Vec<String>, right_options: Vec<String>) -> Self {
70 Self {
71 left_options,
72 right_options,
73 }
74 }
75 pub fn temperature(&self) -> f64 {
77 (self.left_options.len() + self.right_options.len()) as f64 / 2.0
78 }
79 pub fn mean(&self) -> f64 {
81 let l = self.left_options.len() as f64;
82 let r = self.right_options.len() as f64;
83 (l - r) / 2.0
84 }
85 pub fn is_number(&self) -> bool {
87 self.left_options.is_empty()
88 || self.right_options.is_empty()
89 || !self
90 .left_options
91 .iter()
92 .any(|l| self.right_options.contains(l))
93 }
94}
95#[derive(Debug, Clone)]
102pub struct SignExpansionEncoder {
103 pub(super) signs: Vec<bool>,
105}
106impl SignExpansionEncoder {
107 pub fn new(signs: Vec<bool>) -> Self {
109 Self { signs }
110 }
111 pub fn from_fin_surreal(x: &FinSurreal) -> Self {
113 let raw = x.sign_expansion();
114 Self {
115 signs: raw.iter().map(|s| *s == Sign::Plus).collect(),
116 }
117 }
118 pub fn decode(&self) -> FinSurreal {
120 let mut lo = f64::NEG_INFINITY;
121 let mut hi = f64::INFINITY;
122 let mut current = 0.0_f64;
123 for &plus in &self.signs {
124 if plus {
125 lo = current;
126 current = if hi.is_infinite() {
127 lo + 1.0
128 } else {
129 (lo + hi) / 2.0
130 };
131 } else {
132 hi = current;
133 current = if lo.is_infinite() {
134 hi - 1.0
135 } else {
136 (lo + hi) / 2.0
137 };
138 }
139 }
140 let exp = self.signs.len() as u32;
141 let denom = if exp < 63 { 1i64 << exp } else { i64::MAX };
142 let numer = (current * denom as f64).round() as i64;
143 FinSurreal::new(numer, exp)
144 }
145 pub fn len(&self) -> usize {
147 self.signs.len()
148 }
149 pub fn is_empty(&self) -> bool {
151 self.signs.is_empty()
152 }
153 pub fn le(&self, other: &Self) -> bool {
158 for (i, (&s1, &s2)) in self.signs.iter().zip(other.signs.iter()).enumerate() {
159 let _ = i;
160 match (s1, s2) {
161 (true, false) => return false,
162 (false, true) => return true,
163 _ => {}
164 }
165 }
166 self.signs.len() <= other.signs.len()
167 }
168 pub fn to_signs(&self) -> Vec<Sign> {
170 self.signs
171 .iter()
172 .map(|&b| if b { Sign::Plus } else { Sign::Minus })
173 .collect()
174 }
175}
176pub struct InfinitesimalSurreal {
178 pub epsilon_power: i32,
179}
180impl InfinitesimalSurreal {
181 pub fn new(epsilon_power: i32) -> Self {
182 Self { epsilon_power }
183 }
184 pub fn is_infinitesimal(&self) -> bool {
186 self.epsilon_power > 0
187 }
188 pub fn standard_part(&self) -> f64 {
190 if self.is_infinitesimal() {
191 0.0
192 } else {
193 f64::INFINITY
194 }
195 }
196 pub fn infinite_part(&self) -> f64 {
198 if self.epsilon_power < 0 {
199 f64::INFINITY
200 } else {
201 0.0
202 }
203 }
204}
205pub struct CombinatorialGame {
207 pub position: String,
208}
209impl CombinatorialGame {
210 pub fn new(position: String) -> Self {
211 Self { position }
212 }
213 pub fn grundy_value(&self) -> u64 {
215 let mut h: u64 = 0xcbf29ce484222325;
216 for b in self.position.bytes() {
217 h ^= b as u64;
218 h = h.wrapping_mul(0x100000001b3);
219 }
220 h % 64
221 }
222 pub fn is_hot(&self) -> bool {
224 self.position.contains("hot") || self.grundy_value() > 8
225 }
226 pub fn canonical_form(&self) -> String {
228 format!("CanonicalGame({})", self.position)
229 }
230}
231#[derive(Debug, Clone, PartialEq, Eq)]
236pub struct FinSurreal {
237 pub numerator: i64,
239 pub exp: u32,
241}
242impl FinSurreal {
243 pub fn zero() -> Self {
245 FinSurreal {
246 numerator: 0,
247 exp: 0,
248 }
249 }
250 pub fn one() -> Self {
252 FinSurreal {
253 numerator: 1,
254 exp: 0,
255 }
256 }
257 pub fn neg_one() -> Self {
259 FinSurreal {
260 numerator: -1,
261 exp: 0,
262 }
263 }
264 pub fn half() -> Self {
266 FinSurreal {
267 numerator: 1,
268 exp: 1,
269 }
270 }
271 pub fn new(numerator: i64, exp: u32) -> Self {
273 let mut s = FinSurreal { numerator, exp };
274 s.reduce();
275 s
276 }
277 fn reduce(&mut self) {
279 while self.exp > 0 && self.numerator % 2 == 0 {
280 self.numerator /= 2;
281 self.exp -= 1;
282 }
283 }
284 pub fn to_f64(&self) -> f64 {
286 self.numerator as f64 / (1u64 << self.exp) as f64
287 }
288 pub fn birthday(&self) -> u32 {
292 if self.exp == 0 {
293 self.numerator.unsigned_abs().count_ones()
294 + self.numerator.unsigned_abs().leading_zeros()
295 - (u64::BITS - 1 - self.numerator.unsigned_abs().leading_zeros())
296 } else {
297 self.exp + (self.numerator.unsigned_abs() >> self.exp).count_ones()
298 }
299 }
300 pub fn negate(&self) -> Self {
302 FinSurreal::new(-self.numerator, self.exp)
303 }
304 pub fn add(&self, other: &Self) -> Self {
306 let max_exp = self.exp.max(other.exp);
307 let a = self.numerator * (1i64 << (max_exp - self.exp));
308 let b = other.numerator * (1i64 << (max_exp - other.exp));
309 FinSurreal::new(a + b, max_exp)
310 }
311 pub fn mul(&self, other: &Self) -> Self {
313 FinSurreal::new(self.numerator * other.numerator, self.exp + other.exp)
314 }
315 pub fn le(&self, other: &Self) -> bool {
317 let max_exp = self.exp.max(other.exp);
318 let a = self.numerator * (1i64 << (max_exp - self.exp));
319 let b = other.numerator * (1i64 << (max_exp - other.exp));
320 a <= b
321 }
322 pub fn lt(&self, other: &Self) -> bool {
324 self.le(other) && self != other
325 }
326 pub fn sign_expansion(&self) -> Vec<Sign> {
331 let v = self.to_f64();
332 let mut signs = Vec::new();
333 let mut lo = f64::NEG_INFINITY;
334 let mut hi = f64::INFINITY;
335 let mut current = 0.0_f64;
336 for _ in 0..64 {
337 if (current - v).abs() < 1e-12 {
338 break;
339 }
340 if v > current {
341 signs.push(Sign::Plus);
342 lo = current;
343 current = if hi.is_infinite() {
344 lo + 1.0
345 } else {
346 (lo + hi) / 2.0
347 };
348 } else {
349 signs.push(Sign::Minus);
350 hi = current;
351 current = if lo.is_infinite() {
352 hi - 1.0
353 } else {
354 (lo + hi) / 2.0
355 };
356 }
357 }
358 signs
359 }
360 pub fn integer_part(&self) -> i64 {
362 if self.exp == 0 {
363 self.numerator
364 } else {
365 let d = 1i64 << self.exp;
366 if self.numerator >= 0 {
367 self.numerator / d
368 } else {
369 (self.numerator - d + 1) / d
370 }
371 }
372 }
373}
374pub struct NimberType {
376 pub n: u64,
377}
378impl NimberType {
379 pub fn new(n: u64) -> Self {
380 Self { n }
381 }
382 pub fn nim_addition(&self, other: &Self) -> Self {
384 Self {
385 n: self.n ^ other.n,
386 }
387 }
388 pub fn nim_multiplication(&self, other: &Self) -> Self {
390 let result = nim_mul_internal(self.n, other.n);
391 Self { n: result }
392 }
393 pub fn grundy_value(&self) -> u64 {
395 self.n
396 }
397}
398pub struct SurrealOrd {
400 pub lhs: String,
401 pub rhs: String,
402}
403impl SurrealOrd {
404 pub fn new(lhs: String, rhs: String) -> Self {
405 Self { lhs, rhs }
406 }
407 pub fn le(&self) -> bool {
408 self.lhs <= self.rhs
409 }
410 pub fn lt(&self) -> bool {
411 self.lhs < self.rhs
412 }
413 pub fn eq_surreal(&self) -> bool {
414 self.lhs == self.rhs
415 }
416 pub fn compare(&self) -> std::cmp::Ordering {
417 self.lhs.cmp(&self.rhs)
418 }
419}
420#[derive(Debug, Clone)]
426pub struct HahnSeriesRepr {
427 pub terms: Vec<(f64, f64)>,
429}
430impl HahnSeriesRepr {
431 pub fn zero() -> Self {
433 Self { terms: vec![] }
434 }
435 pub fn constant(c: f64) -> Self {
437 if c == 0.0 {
438 Self::zero()
439 } else {
440 Self {
441 terms: vec![(0.0, c)],
442 }
443 }
444 }
445 pub fn monomial(e: f64, c: f64) -> Self {
447 if c == 0.0 {
448 Self::zero()
449 } else {
450 Self {
451 terms: vec![(e, c)],
452 }
453 }
454 }
455 pub fn add(&self, other: &Self) -> Self {
457 let mut result = self.terms.clone();
458 for (e, c) in &other.terms {
459 if let Some(pos) = result.iter().position(|(re, _)| (re - e).abs() < 1e-14) {
460 result[pos].1 += c;
461 if result[pos].1.abs() < 1e-14 {
462 result.remove(pos);
463 }
464 } else {
465 result.push((*e, *c));
466 }
467 }
468 result.sort_by(|a, b| b.0.partial_cmp(&a.0).unwrap_or(std::cmp::Ordering::Equal));
469 Self { terms: result }
470 }
471 pub fn mul(&self, other: &Self) -> Self {
473 let mut result = Self::zero();
474 for (e1, c1) in &self.terms {
475 for (e2, c2) in &other.terms {
476 let term = Self::monomial(e1 + e2, c1 * c2);
477 result = result.add(&term);
478 }
479 }
480 result
481 }
482 pub fn leading_exponent(&self) -> Option<f64> {
484 self.terms.first().map(|(e, _)| *e)
485 }
486 pub fn leading_coefficient(&self) -> f64 {
488 self.terms.first().map(|(_, c)| *c).unwrap_or(0.0)
489 }
490 pub fn has_well_ordered_support(&self) -> bool {
492 true
493 }
494 pub fn eval_at_one(&self) -> f64 {
496 self.terms.iter().map(|(_, c)| c).sum()
497 }
498}
499pub struct SurrealNumber {
501 pub left_set: Vec<String>,
502 pub right_set: Vec<String>,
503 pub birthday: u32,
504}
505impl SurrealNumber {
506 pub fn new(left_set: Vec<String>, right_set: Vec<String>, birthday: u32) -> Self {
507 Self {
508 left_set,
509 right_set,
510 birthday,
511 }
512 }
513 pub fn is_valid(&self) -> bool {
515 let right_set: std::collections::HashSet<_> = self.right_set.iter().collect();
516 !self.left_set.iter().any(|l| right_set.contains(l))
517 }
518 pub fn simplest_form(&self) -> String {
520 format!("{{ {:?} | {:?} }}", self.left_set, self.right_set)
521 }
522}
523pub struct SurrealArithmetic {
525 pub a: String,
526 pub b: String,
527}
528impl SurrealArithmetic {
529 pub fn new(a: String, b: String) -> Self {
530 Self { a, b }
531 }
532 pub fn add(&self) -> String {
533 format!("({} + {})", self.a, self.b)
534 }
535 pub fn multiply(&self) -> String {
536 format!("({} * {})", self.a, self.b)
537 }
538 pub fn negate(&self) -> String {
539 format!("(-{})", self.a)
540 }
541 pub fn reciprocal(&self) -> Option<String> {
542 if self.a == "0" {
543 None
544 } else {
545 Some(format!("(1/{})", self.a))
546 }
547 }
548}
549pub struct SurrealFieldAxioms;
551impl SurrealFieldAxioms {
552 pub fn new() -> Self {
553 Self
554 }
555 pub fn verify_field_axioms(&self) -> bool {
557 true
558 }
559 pub fn is_ordered_field(&self) -> bool {
561 true
562 }
563}
564#[derive(Debug, Clone)]
570pub struct SurrealGame {
571 pub left_options: Vec<FinSurreal>,
573 pub right_options: Vec<FinSurreal>,
575}
576impl SurrealGame {
577 pub fn new(left_options: Vec<FinSurreal>, right_options: Vec<FinSurreal>) -> Self {
579 Self {
580 left_options,
581 right_options,
582 }
583 }
584 pub fn zero_game() -> Self {
586 Self {
587 left_options: vec![],
588 right_options: vec![],
589 }
590 }
591 pub fn star_game() -> Self {
593 Self {
594 left_options: vec![FinSurreal::zero()],
595 right_options: vec![FinSurreal::zero()],
596 }
597 }
598 pub fn surreal_value(&self) -> Option<FinSurreal> {
601 let max_left = self.left_options.iter().max_by(|a, b| {
602 if a.le(b) {
603 std::cmp::Ordering::Less
604 } else {
605 std::cmp::Ordering::Greater
606 }
607 });
608 let min_right = self.right_options.iter().min_by(|a, b| {
609 if a.le(b) {
610 std::cmp::Ordering::Less
611 } else {
612 std::cmp::Ordering::Greater
613 }
614 });
615 match (max_left, min_right) {
616 (None, None) => Some(FinSurreal::zero()),
617 (Some(l), None) => Some(FinSurreal::new(l.numerator + (1i64 << l.exp), l.exp)),
618 (None, Some(r)) => Some(FinSurreal::new(r.numerator - (1i64 << r.exp), r.exp)),
619 (Some(l), Some(r)) => {
620 if !l.lt(r) {
621 None
622 } else {
623 let lo = l.to_f64();
624 let hi = r.to_f64();
625 simplest_in_interval(lo, hi).map(|v| {
626 let exp = 53u32;
627 let denom = (1u64 << exp) as f64;
628 let numer = (v * denom).round() as i64;
629 FinSurreal::new(numer, exp)
630 })
631 }
632 }
633 }
634 }
635 pub fn outcome_class(&self) -> &'static str {
641 match self.surreal_value() {
642 None => "Fuzzy",
643 Some(v) => {
644 let zero = FinSurreal::zero();
645 if v == zero {
646 "P"
647 } else if zero.lt(&v) {
648 "L"
649 } else {
650 "R"
651 }
652 }
653 }
654 }
655 pub fn is_number(&self) -> bool {
657 for l in &self.left_options {
658 for r in &self.right_options {
659 if !l.lt(r) {
660 return false;
661 }
662 }
663 }
664 true
665 }
666 pub fn negate(&self) -> Self {
668 Self {
669 left_options: self.right_options.iter().map(|x| x.negate()).collect(),
670 right_options: self.left_options.iter().map(|x| x.negate()).collect(),
671 }
672 }
673}
674#[derive(Debug, Clone)]
680pub struct SurrealModelChecker {
681 pub kappa: u64,
683}
684impl SurrealModelChecker {
685 pub fn new(kappa: u64) -> Self {
687 Self { kappa }
688 }
689 pub fn is_kappa_saturated(&self) -> bool {
692 self.kappa > 0
693 }
694 pub fn is_ordered_field(&self) -> bool {
696 true
697 }
698 pub fn is_real_closed(&self) -> bool {
700 true
701 }
702 pub fn is_o_minimal(&self) -> bool {
704 true
705 }
706 pub fn embeds_all_ordered_fields_of_size(&self, field_size: u64) -> bool {
708 field_size < self.kappa
709 }
710 pub fn satisfied_properties(&self) -> Vec<&'static str> {
712 let mut props = vec!["ordered_field", "real_closed", "o_minimal"];
713 if self.is_kappa_saturated() {
714 props.push("kappa_saturated");
715 }
716 if self.kappa > u64::MAX / 2 {
717 props.push("universal_ordered_field");
718 }
719 props
720 }
721}
722#[derive(Debug, Clone, PartialEq)]
728pub struct CantorNormalForm {
729 pub terms: Vec<(u64, u64)>,
731}
732impl CantorNormalForm {
733 pub fn zero() -> Self {
735 Self { terms: vec![] }
736 }
737 pub fn finite(n: u64) -> Self {
739 if n == 0 {
740 Self::zero()
741 } else {
742 Self {
743 terms: vec![(0, n)],
744 }
745 }
746 }
747 pub fn omega() -> Self {
749 Self {
750 terms: vec![(1, 1)],
751 }
752 }
753 pub fn omega_pow(k: u64) -> Self {
755 Self {
756 terms: vec![(k, 1)],
757 }
758 }
759 pub fn epsilon0_approx() -> Self {
762 Self {
763 terms: vec![(256, 1)],
764 }
765 }
766 pub fn add(&self, other: &Self) -> Self {
768 if other.terms.is_empty() {
769 return self.clone();
770 }
771 if self.terms.is_empty() {
772 return other.clone();
773 }
774 let top_other_power = other.terms[0].0;
775 let self_kept: Vec<(u64, u64)> = self
776 .terms
777 .iter()
778 .filter(|(p, _)| *p >= top_other_power)
779 .cloned()
780 .collect();
781 let mut result = self_kept;
782 if let (Some(last), Some(first_other)) = (result.last_mut(), other.terms.first()) {
783 if last.0 == first_other.0 {
784 last.1 += first_other.1;
785 for term in other.terms.iter().skip(1) {
786 result.push(*term);
787 }
788 return Self { terms: result };
789 }
790 }
791 result.extend_from_slice(&other.terms);
792 Self { terms: result }
793 }
794 pub fn mul(&self, other: &Self) -> Self {
796 if self.terms.is_empty() || other.terms.is_empty() {
797 return Self::zero();
798 }
799 let (b0, c0) = other.terms[0];
800 if b0 == 0 {
801 let terms = self.terms.iter().map(|(p, c)| (*p, c * c0)).collect();
802 return Self { terms };
803 }
804 let top_power_alpha = self.terms[0].0;
805 Self {
806 terms: vec![(top_power_alpha + b0, c0)],
807 }
808 }
809 pub fn is_successor(&self) -> bool {
811 self.terms.last().map(|(p, _)| *p == 0).unwrap_or(false)
812 }
813 pub fn is_limit(&self) -> bool {
815 !self.terms.is_empty() && !self.is_successor()
816 }
817 pub fn to_string_cnf(&self) -> String {
819 if self.terms.is_empty() {
820 return "0".to_string();
821 }
822 let parts: Vec<String> = self
823 .terms
824 .iter()
825 .map(|(p, c)| match p {
826 0 => format!("{}", c),
827 1 => {
828 if *c == 1 {
829 "ω".to_string()
830 } else {
831 format!("ω·{}", c)
832 }
833 }
834 _ => {
835 if *c == 1 {
836 format!("ω^{}", p)
837 } else {
838 format!("ω^{}·{}", p, c)
839 }
840 }
841 })
842 .collect();
843 parts.join(" + ")
844 }
845}