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); 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 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}