1use std::sync::Arc;
7
8use ext::{
9 chain_complex::{ChainComplex, ChainHomotopy, FreeChainComplex},
10 resolution_homomorphism::ResolutionHomomorphism,
11};
12use fp::matrix::{AugmentedMatrix, Matrix};
13use sseq::coordinates::{Bidegree, BidegreeElement, BidegreeGenerator};
14
15fn main() -> anyhow::Result<()> {
16 ext::utils::init_logging()?;
17
18 let resolution = Arc::new(ext::utils::query_module(None, true)?);
19 let p = resolution.prime();
20
21 let (is_unit, unit) = ext::utils::get_unit(Arc::clone(&resolution))?;
22
23 eprintln!("\nComputing Massey products <a, b, ->");
24 eprintln!("\nEnter a:");
25
26 let a = Bidegree::n_s(
27 query::raw("n of Ext class a", str::parse),
28 query::raw("s of Ext class a", str::parse::<std::num::NonZeroI32>).get(),
29 );
30
31 unit.compute_through_stem(a);
32
33 let a_class = query::vector("Input Ext class a", unit.number_of_gens_in_bidegree(a));
34
35 eprintln!("\nEnter b:");
36
37 let b = Bidegree::n_s(
38 query::raw("n of Ext class b", str::parse),
39 query::raw("s of Ext class b", str::parse::<std::num::NonZeroI32>).get(),
40 );
41
42 unit.compute_through_stem(b);
43
44 let b_class = query::vector("Input Ext class b", unit.number_of_gens_in_bidegree(b));
45
46 let shift = a + b - Bidegree::s_t(1, 0);
48
49 if !is_unit {
50 unit.compute_through_stem(shift);
51 }
52
53 if !resolution.has_computed_bidegree(shift + Bidegree::s_t(0, resolution.min_degree())) {
54 eprintln!("No computable bidegrees");
55 return Ok(());
56 }
57
58 let b_hom = Arc::new(ResolutionHomomorphism::from_class(
59 String::new(),
60 Arc::clone(&unit),
61 Arc::clone(&unit),
62 b,
63 &b_class,
64 ));
65
66 b_hom.extend_through_stem(shift);
67
68 let offset_a = unit.module(a.s()).generator_offset(a.t(), a.t(), 0);
69 for c in resolution.iter_nonzero_stem() {
70 if !resolution.has_computed_bidegree(c + shift) {
71 continue;
72 }
73
74 let tot = c + shift;
75
76 let num_gens = resolution.number_of_gens_in_bidegree(c);
77 let product_num_gens = resolution.number_of_gens_in_bidegree(b + c);
78 let target_num_gens = resolution.number_of_gens_in_bidegree(tot);
79 if target_num_gens == 0 {
80 continue;
81 }
82
83 let mut answers = vec![vec![0; target_num_gens]; num_gens];
84 let mut product = AugmentedMatrix::<2>::new(p, num_gens, [product_num_gens, num_gens]);
85 product.segment(1, 1).add_identity();
86
87 let mut matrix = Matrix::new(p, num_gens, 1);
88 for (idx, answer_row) in answers.iter_mut().enumerate() {
89 let hom = Arc::new(ResolutionHomomorphism::new(
90 String::new(),
91 Arc::clone(&resolution),
92 Arc::clone(&unit),
93 c,
94 ));
95
96 matrix.row_mut(idx).set_entry(0, 1);
97 hom.extend_step(c, Some(&matrix));
98 matrix.row_mut(idx).set_entry(0, 0);
99
100 hom.extend_through_stem(tot);
101
102 let homotopy = ChainHomotopy::new(Arc::clone(&hom), Arc::clone(&b_hom));
103
104 homotopy.extend(tot);
105
106 let last = homotopy.homotopy(tot.s());
107 for (i, answer) in answer_row.iter_mut().enumerate() {
108 let output = last.output(tot.t(), i);
109 for (k, &v) in a_class.iter().enumerate() {
110 if v != 0 {
111 *answer += v * output.entry(offset_a + k);
112 }
113 }
114 }
115
116 for (k, &v) in b_class.iter().enumerate() {
117 if v != 0 {
118 let g = BidegreeGenerator::new(b, k);
119 hom.act(product.row_mut(idx).slice_mut(0, product_num_gens), v, g);
120 }
121 }
122 }
123 product.row_reduce();
124 let kernel = product.compute_kernel();
125
126 for row in kernel.iter() {
127 let c_element = BidegreeElement::new(c, row.to_owned());
128 print!(
129 "<a, b, {c_string}> = [",
130 c_string = c_element.to_basis_string()
131 );
132
133 #[allow(clippy::needless_range_loop)]
134 for i in 0..target_num_gens {
135 let mut entry = 0;
136 for (j, v) in row.iter().enumerate() {
137 entry += v * answers[j][i];
138 }
139 if i != 0 {
140 print!(", ");
141 }
142 print!("{}", entry % p);
143 }
144 println!("]");
145 }
146 }
147
148 Ok(())
149}