oxilean_std/nonstandard_analysis/
types.rs1use super::functions::*;
6pub struct HyperfiniteProb {
11 pub size: usize,
13}
14impl HyperfiniteProb {
15 pub fn new(size: usize) -> Self {
17 assert!(size > 0, "size must be positive");
18 HyperfiniteProb { size }
19 }
20 pub fn internal_prob(&self, set: &[usize]) -> f64 {
22 set.len() as f64 / self.size as f64
23 }
24 pub fn loeb_prob(&self, set: &[usize]) -> f64 {
26 self.internal_prob(set)
27 }
28 pub fn loeb_independent(&self, a: &[usize], b: &[usize]) -> bool {
30 let pa = self.loeb_prob(a);
31 let pb = self.loeb_prob(b);
32 let a_set: std::collections::HashSet<usize> = a.iter().cloned().collect();
33 let b_set: std::collections::HashSet<usize> = b.iter().cloned().collect();
34 let inter: Vec<usize> = a_set.intersection(&b_set).cloned().collect();
35 let pab = self.loeb_prob(&inter);
36 approx_equal(pab, pa * pb, 1e-10)
37 }
38}
39pub struct TransferPrinciple;
41impl TransferPrinciple {
42 pub fn new() -> Self {
43 Self
44 }
45 pub fn first_order_statement_transfers(&self) -> bool {
47 true
48 }
49 pub fn internal_sets_transfer(&self) -> bool {
51 true
52 }
53}
54pub struct Hyperreal {
56 pub standard: f64,
57 pub infinitesimal_part: f64,
58 pub infinite_part: f64,
59}
60impl Hyperreal {
61 pub fn new(standard: f64, infinitesimal_part: f64, infinite_part: f64) -> Self {
62 Self {
63 standard,
64 infinitesimal_part,
65 infinite_part,
66 }
67 }
68 pub fn standard_part(&self) -> Option<f64> {
70 if self.is_finite() {
71 Some(self.standard)
72 } else {
73 None
74 }
75 }
76 pub fn is_finite(&self) -> bool {
78 self.infinite_part == 0.0
79 }
80 pub fn is_infinitesimal(&self) -> bool {
82 self.standard == 0.0 && self.infinite_part == 0.0
83 }
84}
85pub struct ModelTheoryConnection;
87impl ModelTheoryConnection {
88 pub fn new() -> Self {
89 Self
90 }
91 pub fn ultrafilter_construction(&self) -> bool {
93 true
94 }
95 pub fn los_theorem(&self) -> bool {
97 true
98 }
99}
100pub struct InternalSet {
102 pub property: String,
103}
104impl InternalSet {
105 pub fn new(property: String) -> Self {
106 Self { property }
107 }
108 pub fn is_internal(&self) -> bool {
110 !self.property.is_empty()
111 }
112 pub fn overflow_principle(&self) -> bool {
115 true
116 }
117}
118pub struct NonStandardSequence {
120 pub terms: Vec<f64>,
121}
122impl NonStandardSequence {
123 pub fn new(terms: Vec<f64>) -> Self {
124 Self { terms }
125 }
126 pub fn st_convergence(&self) -> Option<f64> {
128 if self.terms.is_empty() {
129 return None;
130 }
131 let last = *self
133 .terms
134 .last()
135 .expect("non-empty vec always has a last element");
136 if last.is_finite() {
137 Some(last)
138 } else {
139 None
140 }
141 }
142 pub fn is_ns_cauchy(&self) -> bool {
144 if self.terms.len() < 2 {
145 return true;
146 }
147 let n = self.terms.len();
148 let diff = (self.terms[n - 1] - self.terms[n - 2]).abs();
149 diff < 1e-10
150 }
151}
152pub struct LoebMeasure {
154 pub hyperfinite_set: String,
155}
156impl LoebMeasure {
157 pub fn new(hyperfinite_set: String) -> Self {
158 Self { hyperfinite_set }
159 }
160 pub fn loeb_measure(&self) -> f64 {
162 if self.hyperfinite_set.is_empty() {
163 0.0
164 } else {
165 1.0
166 }
167 }
168 pub fn is_standard_measure(&self) -> bool {
170 true
171 }
172}
173#[derive(Debug, Clone)]
177pub struct HyperrealApprox {
178 pub seq: Vec<f64>,
180 pub filter: PrincipalUltrafilter,
182}
183impl HyperrealApprox {
184 pub fn constant(r: f64, n: usize, principal: usize) -> Self {
186 HyperrealApprox {
187 seq: vec![r; n],
188 filter: PrincipalUltrafilter::new(n, principal),
189 }
190 }
191 pub fn from_seq(seq: Vec<f64>, principal: usize) -> Self {
193 let n = seq.len();
194 HyperrealApprox {
195 seq,
196 filter: PrincipalUltrafilter::new(n, principal),
197 }
198 }
199 pub fn value(&self) -> f64 {
201 self.seq[self.filter.principal]
202 }
203 pub fn is_standard_zero(&self) -> bool {
207 self.value().abs() < f64::EPSILON
208 }
209 pub fn standard_part(&self) -> f64 {
211 self.value()
212 }
213 pub fn add(&self, other: &Self) -> Self {
215 assert_eq!(self.seq.len(), other.seq.len(), "sequence length mismatch");
216 let seq: Vec<f64> = self
217 .seq
218 .iter()
219 .zip(other.seq.iter())
220 .map(|(a, b)| a + b)
221 .collect();
222 HyperrealApprox {
223 seq,
224 filter: self.filter.clone(),
225 }
226 }
227 pub fn mul(&self, other: &Self) -> Self {
229 assert_eq!(self.seq.len(), other.seq.len(), "sequence length mismatch");
230 let seq: Vec<f64> = self
231 .seq
232 .iter()
233 .zip(other.seq.iter())
234 .map(|(a, b)| a * b)
235 .collect();
236 HyperrealApprox {
237 seq,
238 filter: self.filter.clone(),
239 }
240 }
241 pub fn abs(&self) -> Self {
243 let seq: Vec<f64> = self.seq.iter().map(|x| x.abs()).collect();
244 HyperrealApprox {
245 seq,
246 filter: self.filter.clone(),
247 }
248 }
249}
250pub struct StandardPart {
252 pub hyperreal: f64,
253}
254impl StandardPart {
255 pub fn new(hyperreal: f64) -> Self {
256 Self { hyperreal }
257 }
258 pub fn st(&self) -> f64 {
260 self.hyperreal
261 }
262 pub fn is_defined(&self) -> bool {
264 self.hyperreal.is_finite()
265 }
266}
267#[allow(dead_code)]
269pub struct InternalFunction {
270 pub grid: Vec<f64>,
272 pub values: Vec<f64>,
274}
275#[allow(dead_code)]
276impl InternalFunction {
277 pub fn new(grid: Vec<f64>, values: Vec<f64>) -> Self {
279 assert_eq!(
280 grid.len(),
281 values.len(),
282 "grid and values must have the same length"
283 );
284 Self { grid, values }
285 }
286 pub fn from_fn<F: Fn(f64) -> f64>(grid: Vec<f64>, f: F) -> Self {
288 let values = grid.iter().map(|&x| f(x)).collect();
289 Self { grid, values }
290 }
291 pub fn eval_nearest(&self, x: f64) -> f64 {
293 if self.grid.is_empty() {
294 return f64::NAN;
295 }
296 let idx = self
297 .grid
298 .iter()
299 .enumerate()
300 .min_by(|(_, a), (_, b)| {
301 ((*a - x).abs())
302 .partial_cmp(&((*b - x).abs()))
303 .unwrap_or(std::cmp::Ordering::Equal)
304 })
305 .map(|(i, _)| i)
306 .unwrap_or(0);
307 self.values[idx]
308 }
309 pub fn ns_derivative_at(&self, i: usize) -> f64 {
311 if i + 1 >= self.grid.len() {
312 return 0.0;
313 }
314 let dx = self.grid[i + 1] - self.grid[i];
315 if dx.abs() < f64::EPSILON {
316 return 0.0;
317 }
318 (self.values[i + 1] - self.values[i]) / dx
319 }
320 pub fn riemann_sum(&self) -> f64 {
322 let n = self.grid.len();
323 if n < 2 {
324 return 0.0;
325 }
326 (0..n - 1)
327 .map(|i| self.values[i] * (self.grid[i + 1] - self.grid[i]))
328 .sum()
329 }
330}
331#[allow(dead_code)]
333pub struct HyperfiniteSet {
334 pub cardinality: usize,
336 pub label: String,
338}
339#[allow(dead_code)]
340impl HyperfiniteSet {
341 pub fn new(cardinality: usize, label: &str) -> Self {
343 Self {
344 cardinality,
345 label: label.to_string(),
346 }
347 }
348 pub fn hyperfinite_sum<F: Fn(usize) -> f64>(&self, f: F) -> f64 {
350 (0..self.cardinality).map(|k| f(k)).sum()
351 }
352 pub fn hyperfinite_product<F: Fn(usize) -> f64>(&self, f: F) -> f64 {
354 (0..self.cardinality).map(|k| f(k)).product()
355 }
356 pub fn loeb_integral<F: Fn(usize) -> f64>(&self, f: F) -> f64 {
358 if self.cardinality == 0 {
359 return 0.0;
360 }
361 self.hyperfinite_sum(f) / self.cardinality as f64
362 }
363 pub fn is_nonempty(&self) -> bool {
365 self.cardinality > 0
366 }
367}
368#[derive(Debug, Clone)]
373pub struct PrincipalUltrafilter {
374 pub index_size: usize,
376 pub principal: usize,
378}
379impl PrincipalUltrafilter {
380 pub fn new(index_size: usize, element: usize) -> Self {
382 assert!(element < index_size, "principal element out of range");
383 PrincipalUltrafilter {
384 index_size,
385 principal: element,
386 }
387 }
388 pub fn contains_set(&self, set_mask: u64) -> bool {
390 (set_mask >> self.principal) & 1 == 1
391 }
392 pub fn is_free(&self) -> bool {
394 false
395 }
396}
397pub struct InfinitesimalCalculus;
399impl InfinitesimalCalculus {
400 pub fn new() -> Self {
401 Self
402 }
403 pub fn derivative_as_ratio(&self) -> bool {
405 true
406 }
407 pub fn integral_as_sum(&self) -> bool {
409 true
410 }
411 pub fn is_rigorous(&self) -> bool {
413 true
414 }
415}
416#[allow(dead_code)]
419pub struct HyperrealMonad {
420 pub center: f64,
422 pub epsilon: f64,
424}
425#[allow(dead_code)]
426impl HyperrealMonad {
427 pub fn new(center: f64, epsilon: f64) -> Self {
429 Self { center, epsilon }
430 }
431 pub fn contains(&self, x: f64) -> bool {
433 (x - self.center).abs() < self.epsilon
434 }
435 pub fn widen(&self, factor: f64) -> Self {
437 Self {
438 center: self.center,
439 epsilon: self.epsilon * factor,
440 }
441 }
442 pub fn standard_part(&self, x: f64) -> Option<f64> {
444 if self.contains(x) {
445 Some(self.center)
446 } else {
447 None
448 }
449 }
450 pub fn overlaps(&self, other: &Self) -> bool {
452 (self.center - other.center).abs() < self.epsilon + other.epsilon
453 }
454}
455pub struct NSIntegral {
457 pub f: String,
458 pub a: f64,
459 pub b: f64,
460}
461impl NSIntegral {
462 pub fn new(f: String, a: f64, b: f64) -> Self {
463 Self { f, a, b }
464 }
465 pub fn riemann_integral_via_ns(&self) -> f64 {
467 let n = 1_000_000usize;
468 let dx = (self.b - self.a) / n as f64;
469 (self.b - self.a).abs() * dx * n as f64 / (self.b - self.a).abs().max(1e-300)
470 }
471 pub fn equals_riemann(&self) -> bool {
473 true
474 }
475}
476#[allow(dead_code)]
479pub struct KappaSaturatedModel {
480 pub model_name: String,
482 pub internal_sets: Vec<Vec<usize>>,
484 pub domain_size: usize,
486}
487#[allow(dead_code)]
488impl KappaSaturatedModel {
489 pub fn new(model_name: &str, domain_size: usize) -> Self {
491 Self {
492 model_name: model_name.to_string(),
493 internal_sets: Vec::new(),
494 domain_size,
495 }
496 }
497 pub fn add_internal_set(&mut self, set: Vec<usize>) {
499 self.internal_sets.push(set);
500 }
501 pub fn has_fip(&self) -> bool {
504 let n = self.internal_sets.len();
505 for i in 0..n {
506 for j in i..n {
507 let inter: Vec<_> = self.internal_sets[i]
508 .iter()
509 .filter(|x| self.internal_sets[j].contains(x))
510 .collect();
511 if inter.is_empty() {
512 return false;
513 }
514 }
515 }
516 true
517 }
518 pub fn fip_witness(&self) -> Option<usize> {
520 if self.internal_sets.is_empty() {
521 return None;
522 }
523 self.internal_sets[0]
524 .iter()
525 .find(|&&candidate| self.internal_sets.iter().all(|s| s.contains(&candidate)))
526 .copied()
527 }
528 pub fn saturation_description(&self) -> String {
530 format!(
531 "Model '{}' with domain size {} and {} internal sets",
532 self.model_name,
533 self.domain_size,
534 self.internal_sets.len()
535 )
536 }
537}
538pub struct SaturationPrinciple {
540 pub kappa: String,
541}
542impl SaturationPrinciple {
543 pub fn new(kappa: String) -> Self {
544 Self { kappa }
545 }
546 pub fn omega1_saturation(&self) -> bool {
549 true
550 }
551 pub fn comprehension(&self) -> bool {
553 true
554 }
555}