ext/chain_complex/
finite_chain_complex.rs

1use std::sync::Arc;
2
3use algebra::module::{
4    Module, ZeroModule,
5    homomorphism::{FullModuleHomomorphism, ModuleHomomorphism, ZeroHomomorphism},
6};
7use sseq::coordinates::Bidegree;
8
9use crate::chain_complex::{AugmentedChainComplex, BoundedChainComplex, ChainComplex};
10
11pub struct FiniteChainComplex<M, F = FullModuleHomomorphism<M>>
12where
13    M: Module,
14    F: ModuleHomomorphism<Source = M, Target = M>,
15{
16    modules: Vec<Arc<M>>,
17    zero_module: Arc<M>,
18    differentials: Vec<Arc<F>>,
19}
20
21impl<M, F> FiniteChainComplex<M, F>
22where
23    M: Module + ZeroModule,
24    F: ModuleHomomorphism<Source = M, Target = M> + ZeroHomomorphism<M, M>,
25{
26    pub fn new(modules: Vec<Arc<M>>, differentials: Vec<Arc<F>>) -> Self {
27        let zero_module = Arc::new(M::zero_module(
28            modules[0].algebra(),
29            modules[0].min_degree(),
30        ));
31
32        let mut all_differentials = Vec::with_capacity(differentials.len() + 2);
33        all_differentials.push(Arc::new(F::zero_homomorphism(
34            Arc::clone(&modules[0]),
35            Arc::clone(&zero_module),
36            0,
37        )));
38        all_differentials.extend(differentials);
39        all_differentials.push(Arc::new(F::zero_homomorphism(
40            Arc::clone(&zero_module),
41            Arc::clone(&modules[modules.len() - 1]),
42            0,
43        )));
44
45        Self {
46            modules,
47            zero_module,
48            differentials: all_differentials,
49        }
50    }
51
52    pub fn ccdz(module: Arc<M>) -> Self {
53        Self::new(vec![module], vec![])
54    }
55}
56
57impl<M, F> FiniteChainComplex<M, F>
58where
59    M: Module,
60    F: ModuleHomomorphism<Source = M, Target = M> + ZeroHomomorphism<M, M>,
61{
62    pub fn pop(&mut self) {
63        if self.modules.is_empty() {
64            return;
65        }
66        self.modules.pop();
67        if self.modules.is_empty() {
68            self.differentials.clear();
69            self.differentials.push(Arc::new(F::zero_homomorphism(
70                self.zero_module(),
71                self.zero_module(),
72                0,
73            )));
74        } else {
75            self.differentials.pop();
76            self.differentials.pop();
77            self.differentials.push(Arc::new(F::zero_homomorphism(
78                self.zero_module(),
79                Arc::clone(&self.modules[self.modules.len() - 1]),
80                0,
81            )));
82        }
83    }
84}
85
86impl<M: Module> FiniteChainComplex<M, FullModuleHomomorphism<M>> {
87    pub fn map<N: Module<Algebra = M::Algebra>>(
88        &self,
89        mut f: impl FnMut(&M) -> N,
90    ) -> FiniteChainComplex<N, FullModuleHomomorphism<N>> {
91        let modules: Vec<Arc<N>> = self.modules.iter().map(|m| Arc::new(f(m))).collect();
92        let zero_module = Arc::new(f(&*self.zero_module));
93        let differentials: Vec<_> = self
94            .differentials
95            .iter()
96            .enumerate()
97            .map(|(s, d)| {
98                if s == 0 {
99                    Arc::new(
100                        (**d)
101                            .clone()
102                            .replace_source(Arc::clone(&modules[0]))
103                            .replace_target(Arc::clone(&zero_module)),
104                    )
105                } else {
106                    Arc::new(
107                        (**d)
108                            .clone()
109                            .replace_source(Arc::clone(modules.get(s).unwrap_or(&zero_module)))
110                            .replace_target(Arc::clone(modules.get(s - 1).unwrap_or(&zero_module))),
111                    )
112                }
113            })
114            .collect();
115        FiniteChainComplex {
116            modules,
117            zero_module,
118            differentials,
119        }
120    }
121}
122
123impl<M, F> ChainComplex for FiniteChainComplex<M, F>
124where
125    M: Module,
126    F: ModuleHomomorphism<Source = M, Target = M>,
127{
128    type Algebra = M::Algebra;
129    type Homomorphism = F;
130    type Module = M;
131
132    fn algebra(&self) -> Arc<Self::Algebra> {
133        self.zero_module.algebra()
134    }
135
136    fn min_degree(&self) -> i32 {
137        self.zero_module.min_degree()
138    }
139
140    fn zero_module(&self) -> Arc<Self::Module> {
141        Arc::clone(&self.zero_module)
142    }
143
144    fn module(&self, s: i32) -> Arc<Self::Module> {
145        let s = s as usize;
146        if s >= self.modules.len() {
147            self.zero_module()
148        } else {
149            Arc::clone(&self.modules[s])
150        }
151    }
152
153    fn differential(&self, s: i32) -> Arc<Self::Homomorphism> {
154        let s = s as usize;
155        let s = std::cmp::min(s, self.differentials.len() - 1); // The last entry is the zero homomorphism
156        Arc::clone(&self.differentials[s])
157    }
158
159    fn compute_through_bidegree(&self, b: Bidegree) {
160        for module in self.modules.iter().take(b.s() as usize + 1) {
161            module.compute_basis(b.t());
162        }
163    }
164
165    fn has_computed_bidegree(&self, b: Bidegree) -> bool {
166        b.s() > self.modules.len() as i32 || b.t() < self.module(b.s()).max_computed_degree()
167    }
168
169    fn next_homological_degree(&self) -> i32 {
170        i32::MAX
171    }
172}
173
174impl<M, F> BoundedChainComplex for FiniteChainComplex<M, F>
175where
176    M: Module,
177    F: ModuleHomomorphism<Source = M, Target = M>,
178{
179    fn max_s(&self) -> i32 {
180        self.modules.len() as i32
181    }
182}
183
184pub struct FiniteAugmentedChainComplex<M, F1, F2, CC>
185where
186    M: Module,
187    CC: ChainComplex<Algebra = M::Algebra>,
188    F1: ModuleHomomorphism<Source = M, Target = M>,
189    F2: ModuleHomomorphism<Source = M, Target = CC::Module>,
190{
191    cc: FiniteChainComplex<M, F1>,
192    target_cc: Arc<CC>,
193    chain_maps: Vec<Arc<F2>>,
194}
195
196impl<M, F1, F2, CC> ChainComplex for FiniteAugmentedChainComplex<M, F1, F2, CC>
197where
198    M: Module,
199    CC: ChainComplex<Algebra = M::Algebra>,
200    F1: ModuleHomomorphism<Source = M, Target = M>,
201    F2: ModuleHomomorphism<Source = M, Target = CC::Module>,
202{
203    type Algebra = M::Algebra;
204    type Homomorphism = F1;
205    type Module = M;
206
207    fn algebra(&self) -> Arc<M::Algebra> {
208        self.cc.algebra()
209    }
210
211    fn min_degree(&self) -> i32 {
212        self.cc.min_degree()
213    }
214
215    fn has_computed_bidegree(&self, b: Bidegree) -> bool {
216        self.cc.has_computed_bidegree(b)
217    }
218
219    fn zero_module(&self) -> Arc<Self::Module> {
220        self.cc.zero_module()
221    }
222
223    fn module(&self, s: i32) -> Arc<Self::Module> {
224        self.cc.module(s)
225    }
226
227    fn differential(&self, s: i32) -> Arc<Self::Homomorphism> {
228        self.cc.differential(s)
229    }
230
231    fn compute_through_bidegree(&self, b: Bidegree) {
232        self.cc.compute_through_bidegree(b)
233    }
234
235    fn next_homological_degree(&self) -> i32 {
236        self.cc.next_homological_degree()
237    }
238}
239
240impl<M, CC>
241    FiniteAugmentedChainComplex<
242        M,
243        FullModuleHomomorphism<M>,
244        FullModuleHomomorphism<M, CC::Module>,
245        CC,
246    >
247where
248    M: Module,
249    CC: ChainComplex<Algebra = M::Algebra>,
250{
251    pub fn map<N: Module<Algebra = M::Algebra>>(
252        &self,
253        f: impl FnMut(&M) -> N,
254    ) -> FiniteAugmentedChainComplex<
255        N,
256        FullModuleHomomorphism<N>,
257        FullModuleHomomorphism<N, CC::Module>,
258        CC,
259    > {
260        let cc = self.cc.map(f);
261        let chain_maps: Vec<_> = std::iter::zip(&self.chain_maps, &cc.modules)
262            .map(|(c, m)| Arc::new((**c).clone().replace_source(Arc::clone(m))))
263            .collect();
264        FiniteAugmentedChainComplex {
265            cc,
266            chain_maps,
267            target_cc: Arc::clone(&self.target_cc),
268        }
269    }
270}
271
272impl<M, F1, F2, CC> AugmentedChainComplex for FiniteAugmentedChainComplex<M, F1, F2, CC>
273where
274    M: Module,
275    CC: ChainComplex<Algebra = M::Algebra>,
276    F1: ModuleHomomorphism<Source = M, Target = M>,
277    F2: ModuleHomomorphism<Source = M, Target = CC::Module>,
278{
279    type ChainMap = F2;
280    type TargetComplex = CC;
281
282    fn target(&self) -> Arc<Self::TargetComplex> {
283        Arc::clone(&self.target_cc)
284    }
285
286    /// This currently crashes if `s` is greater than the s degree of the class this came from.
287    fn chain_map(&self, s: i32) -> Arc<Self::ChainMap> {
288        Arc::clone(&self.chain_maps[s as usize])
289    }
290}
291
292impl<M, F1, F2, CC> From<FiniteAugmentedChainComplex<M, F1, F2, CC>> for FiniteChainComplex<M, F1>
293where
294    M: Module,
295    CC: ChainComplex<Algebra = M::Algebra>,
296    F1: ModuleHomomorphism<Source = M, Target = M>,
297    F2: ModuleHomomorphism<Source = M, Target = CC::Module>,
298{
299    fn from(c: FiniteAugmentedChainComplex<M, F1, F2, CC>) -> Self {
300        c.cc
301    }
302}
303
304impl<M, F1, F2, CC> BoundedChainComplex for FiniteAugmentedChainComplex<M, F1, F2, CC>
305where
306    M: Module,
307    CC: ChainComplex<Algebra = M::Algebra>,
308    F1: ModuleHomomorphism<Source = M, Target = M>,
309    F2: ModuleHomomorphism<Source = M, Target = CC::Module>,
310{
311    fn max_s(&self) -> i32 {
312        self.cc.max_s()
313    }
314}
315
316impl<M, F1> FiniteChainComplex<M, F1>
317where
318    M: Module,
319    F1: ModuleHomomorphism<Source = M, Target = M>,
320{
321    pub fn augment<
322        CC: ChainComplex<Algebra = M::Algebra>,
323        F2: ModuleHomomorphism<Source = M, Target = CC::Module>,
324    >(
325        self,
326        target_cc: Arc<CC>,
327        chain_maps: Vec<Arc<F2>>,
328    ) -> FiniteAugmentedChainComplex<M, F1, F2, CC> {
329        FiniteAugmentedChainComplex {
330            cc: self,
331            target_cc,
332            chain_maps,
333        }
334    }
335}