1use std::{path::PathBuf, sync::Arc};
43
44use algebra::module::Module;
45use anyhow::{Context, anyhow};
46use ext::{
47 chain_complex::{AugmentedChainComplex, ChainComplex, FreeChainComplex},
48 resolution_homomorphism::ResolutionHomomorphism,
49 utils,
50};
51use fp::matrix::Matrix;
52use sseq::coordinates::{Bidegree, BidegreeGenerator};
53
54fn main() -> anyhow::Result<()> {
55 ext::utils::init_logging()?;
56
57 let source = Arc::new(utils::query_module_only("Source module", None, true)?);
58 let b = Bidegree::n_s(
59 query::with_default("Max source n", "30", str::parse),
60 query::with_default("Max source s", "7", str::parse),
61 );
62
63 let source_name = source.name();
64 let target = query::with_default("Target module", source_name, |s| {
65 if s == source_name {
66 Ok(Arc::clone(&source))
67 } else if cfg!(feature = "nassau") {
68 Err(anyhow!("Can only resolve S_2 with nassau"))
69 } else {
70 let config: utils::Config = s.try_into()?;
71 let save_dir = query::optional("Target save directory", |x| {
72 Result::<PathBuf, std::convert::Infallible>::Ok(PathBuf::from(x))
73 });
74
75 let mut target = utils::construct(config, save_dir)
76 .context("Failed to load module from save file")
77 .unwrap();
78
79 target.set_name(s.to_owned());
80
81 #[cfg(feature = "nassau")]
82 unreachable!();
83
84 #[cfg(not(feature = "nassau"))]
85 Ok(Arc::new(target))
86 }
87 });
88
89 assert_eq!(source.prime(), target.prime());
90 let p = source.prime();
91
92 let name: String = query::raw("Name of product", str::parse);
93
94 let shift = Bidegree::n_s(
95 query::with_default("n of product", "0", str::parse),
96 query::with_default("s of product", "0", str::parse),
97 );
98
99 source.compute_through_stem(b);
100 target.compute_through_stem(b - shift);
101
102 let target_module = target.target().module(0);
103 let hom = ResolutionHomomorphism::new(name.clone(), source, target, shift);
104
105 eprintln!("\nInput Ext class to lift:");
106 for output_t in 0..=target_module
107 .max_degree()
108 .expect("lift_hom requires target to be bounded")
109 {
110 let output = Bidegree::s_t(0, output_t);
111 let input = output + shift;
112 let mut matrix = Matrix::new(
113 p,
114 hom.source.number_of_gens_in_bidegree(input),
115 target_module.dimension(output.t()),
116 );
117
118 if matrix.rows() == 0 || matrix.columns() == 0 {
119 hom.extend_step(input, None);
120 } else {
121 for (idx, mut row) in matrix.iter_mut().enumerate() {
122 let g = BidegreeGenerator::new(input, idx);
123 let v: Vec<u32> = query::vector(&format!("f(x_{g}"), row.as_slice().len());
124 for (i, &x) in v.iter().enumerate() {
125 row.set_entry(i, x);
126 }
127 }
128 hom.extend_step(input, Some(&matrix));
129 }
130 }
131
132 hom.extend_all();
133
134 for b2 in hom.target.iter_stem() {
135 let shifted_b2 = b2 + shift;
136 if shifted_b2.s() >= hom.source.next_homological_degree()
137 || shifted_b2.t() > hom.source.module(shifted_b2.s()).max_computed_degree()
138 {
139 continue;
140 }
141 let matrix = hom.get_map(shifted_b2.s()).hom_k(b2.t());
142 for (i, r) in matrix.iter().enumerate() {
143 let g = BidegreeGenerator::new(b2, i);
144 println!("{name} x_{g} = {r:?}");
145 }
146 }
147 Ok(())
148}