secondary_product/
secondary_product.rs1use std::sync::Arc;
24
25use algebra::module::Module;
26use ext::{
27 chain_complex::{ChainComplex, FreeChainComplex},
28 resolution_homomorphism::ResolutionHomomorphism,
29 secondary::*,
30 utils::query_module,
31};
32use fp::{matrix::Matrix, prime::Prime, vector::FpVector};
33use itertools::Itertools;
34use sseq::coordinates::{Bidegree, BidegreeElement, BidegreeGenerator};
35
36fn main() -> anyhow::Result<()> {
37 ext::utils::init_logging()?;
38
39 let resolution = Arc::new(query_module(Some(algebra::AlgebraType::Milnor), true)?);
40
41 let (is_unit, unit) = ext::utils::get_unit(Arc::clone(&resolution))?;
42
43 let p = resolution.prime();
44
45 let name: String = query::raw("Name of product", str::parse);
46
47 let shift = Bidegree::n_s(
48 query::raw(&format!("n of Ext class {name}"), str::parse),
49 query::raw(&format!("s of Ext class {name}"), str::parse),
50 );
51
52 let hom = ResolutionHomomorphism::new(name, Arc::clone(&resolution), Arc::clone(&unit), shift);
53
54 let mut matrix = Matrix::new(p, hom.source.number_of_gens_in_bidegree(shift), 1);
55
56 if matrix.rows() == 0 || matrix.columns() == 0 {
57 panic!("No classes in this bidegree");
58 }
59 let v: Vec<u32> = query::vector("Input ext class", matrix.rows());
60 for (i, &x) in v.iter().enumerate() {
61 matrix.row_mut(i).set_entry(0, x);
62 }
63
64 if !is_unit {
65 let res_max = Bidegree::n_s(
66 resolution.module(0).max_computed_degree(),
67 resolution.next_homological_degree() - 1,
68 );
69 unit.compute_through_stem(res_max - shift);
70 }
71
72 hom.extend_step(shift, Some(&matrix));
73 hom.extend_all();
74
75 let res_lift = SecondaryResolution::new(Arc::clone(&resolution));
76 res_lift.extend_all();
77
78 {
80 let m = res_lift.homotopy(shift.s() + 2).homotopies.hom_k(shift.t());
81 assert_eq!(m.len(), v.len());
82 let mut sum = vec![0; m[0].len()];
83 for (x, d2) in v.iter().zip_eq(&m) {
84 sum.iter_mut().zip_eq(d2).for_each(|(a, b)| *a += x * b);
85 }
86 assert!(
87 sum.iter().all(|x| x.is_multiple_of(p.as_u32())),
88 "Class supports a non-zero d2"
89 );
90 }
91 let res_lift = Arc::new(res_lift);
92
93 let unit_lift = if is_unit {
94 Arc::clone(&res_lift)
95 } else {
96 let lift = SecondaryResolution::new(Arc::clone(&unit));
97 lift.extend_all();
98 Arc::new(lift)
99 };
100
101 let hom = Arc::new(hom);
102 let hom_lift = SecondaryResolutionHomomorphism::new(
103 Arc::clone(&res_lift),
104 Arc::clone(&unit_lift),
105 Arc::clone(&hom),
106 );
107
108 if let Some(s) = ext::utils::secondary_job() {
109 hom_lift.compute_partial(s);
110 return Ok(());
111 }
112
113 hom_lift.extend_all();
114
115 let res_sseq = Arc::new(res_lift.e3_page());
117 let unit_sseq = if is_unit {
118 Arc::clone(&res_sseq)
119 } else {
120 Arc::new(unit_lift.e3_page())
121 };
122
123 fn get_page_data(sseq: &sseq::Sseq<2, sseq::Adams>, b: Bidegree) -> &fp::matrix::Subquotient {
124 let d = sseq.page_data(b);
125 &d[std::cmp::min(3, d.len() - 1)]
126 }
127
128 let name = hom_lift.name();
129 for b in unit.iter_nonzero_stem() {
131 if !resolution.has_computed_bidegree(b + shift + LAMBDA_BIDEGREE) {
134 continue;
135 }
136 if !resolution.has_computed_bidegree(b + shift - Bidegree::s_t(1, 0)) {
137 continue;
138 }
139
140 let page_data = get_page_data(unit_sseq.as_ref(), b);
141
142 let target_num_gens = resolution.number_of_gens_in_bidegree(b + shift);
143 let lambda_num_gens = resolution.number_of_gens_in_bidegree(b + shift + LAMBDA_BIDEGREE);
144
145 if target_num_gens == 0 && lambda_num_gens == 0 {
146 continue;
147 }
148
149 if target_num_gens > 0 {
151 let hom_k = hom.get_map((b + shift).s()).hom_k(b.t());
152 for i in page_data.complement_pivots() {
153 let g = BidegreeGenerator::new(b, i);
154 println!("{name} λ x_{g} = λ {:?}", &hom_k[i]);
155 }
156 }
157
158 if page_data.subspace_dimension() == 0 {
160 continue;
161 }
162
163 let mut outputs = vec![
164 FpVector::new(p, target_num_gens + lambda_num_gens);
165 page_data.subspace_dimension()
166 ];
167
168 hom_lift.hom_k(
169 Some(&res_sseq),
170 b,
171 page_data.subspace_gens(),
172 outputs.iter_mut().map(FpVector::as_slice_mut),
173 );
174 for (g, output) in page_data.subspace_gens().zip_eq(outputs) {
175 println!(
176 "{name} [{basis_string}] = {} + λ {}",
177 output.slice(0, target_num_gens),
178 output.slice(target_num_gens, target_num_gens + lambda_num_gens),
179 basis_string = BidegreeElement::new(b, g.to_owned()).to_basis_string(),
180 );
181 }
182 }
183 Ok(())
184}