1use alloc::boxed::Box;
2use alloc::collections::BTreeSet;
3use crate::core::morphism::Morphism;
4use crate::topology::space::TopologicalSpace;
5
6pub struct ContinuousMap<X, Y>
7where
8 X: TopologicalSpace,
9 Y: TopologicalSpace,
10{
11 f: Box<dyn Fn(&X::Point) -> Y::Point + Send + Sync>,
12}
13
14impl<X, Y> ContinuousMap<X, Y>
15where
16 X: TopologicalSpace,
17 Y: TopologicalSpace,
18{
19 pub fn new<F>(f: F) -> Self
20 where
21 F: Fn(&X::Point) -> Y::Point + Send + Sync + 'static,
22 {
23 Self { f: Box::new(f) }
24 }
25
26 pub fn apply(&self, p: &X::Point) -> Y::Point {
27 (self.f)(p)
28 }
29
30 pub fn preimage(
31 &self,
32 domain_points: &BTreeSet<X::Point>,
33 open_set: &BTreeSet<Y::Point>,
34 ) -> BTreeSet<X::Point>
35 where
36 X::Point: Ord,
37 Y::Point: Ord,
38 {
39 domain_points
40 .iter()
41 .filter(|p| open_set.contains(&self.apply(p)))
42 .cloned()
43 .collect()
44 }
45
46 pub fn is_continuous_on(
47 &self,
48 domain: &X,
49 codomain: &Y,
50 domain_points: &BTreeSet<X::Point>,
51 ) -> bool
52 where
53 X::Point: Ord,
54 Y::Point: Ord,
55 Y: OpenSetsIter,
56 {
57 for open in codomain.open_sets_iter() {
58 let pre = self.preimage(domain_points, &open);
59 if !domain.is_open(&pre) {
60 return false;
61 }
62 }
63 true
64 }
65}
66
67impl<X, Y> Morphism for ContinuousMap<X, Y>
68where
69 X: TopologicalSpace,
70 Y: TopologicalSpace,
71 X::Point: Clone,
72 Y::Point: Clone,
73{
74 type Domain = X::Point;
75 type Codomain = Y::Point;
76
77 fn apply(&self, x: &X::Point) -> Y::Point {
78 (self.f)(x)
79 }
80}
81
82pub trait OpenSetsIter: TopologicalSpace {
83 fn open_sets_iter(&self) -> alloc::vec::IntoIter<BTreeSet<Self::Point>>;
84}
85
86use crate::topology::space::FiniteTopologicalSpace;
87
88impl<P: Clone + Eq + Ord> OpenSetsIter for FiniteTopologicalSpace<P> {
89 fn open_sets_iter(&self) -> alloc::vec::IntoIter<BTreeSet<P>> {
90 self.open_sets().iter().cloned().collect::<alloc::vec::Vec<_>>().into_iter()
91 }
92}