diff --git a/.github/workflows/ext.yaml b/.github/workflows/ext.yaml index 569743feeb..8c7edc5039 100644 --- a/.github/workflows/ext.yaml +++ b/.github/workflows/ext.yaml @@ -45,9 +45,6 @@ jobs: - name: Run ext examples run: make -C ext benchmarks - - name: Run ext examples (nassau) - run: make -C ext benchmarks-nassau - - name: Run ext examples (concurrent) run: make -C ext benchmarks-concurrent diff --git a/ext/Cargo.toml b/ext/Cargo.toml index 8b3919aba8..109175d413 100644 --- a/ext/Cargo.toml +++ b/ext/Cargo.toml @@ -58,7 +58,6 @@ concurrent = [ ] odd-primes = ["fp/odd-primes", "algebra/odd-primes", "sseq/odd-primes"] logging = [] -nassau = [] [workspace] members = [ diff --git a/ext/Makefile b/ext/Makefile index 963bc530a6..0af9af111a 100644 --- a/ext/Makefile +++ b/ext/Makefile @@ -25,13 +25,11 @@ docs: echo "window.ALL_CRATES = [$$(ls crates/ | sed "s/.*/'&',/; s/-/_/g")'ext'];" > target/doc/crates.js -BENCHMARKS = $(filter-out examples/benchmarks/%-nassau, $(wildcard examples/benchmarks/*)) +BENCHMARKS = $(wildcard examples/benchmarks/*) benchmarks: $(BENCHMARKS) -benchmarks-nassau: $(wildcard examples/benchmarks/*-nassau) fix-benchmarks: $(patsubst examples/benchmarks/%, examples/benchmarks/%-fixed, BENCHMARKS) -fix-benchmarks-nassau: $(patsubst examples/benchmarks/%, examples/benchmarks/%-fixed, $(wildcard examples/benchmarks/*-nassau)) benchmarks-concurrent: $(patsubst examples/benchmarks/%, examples/benchmarks/%-concurrent, $(BENCHMARKS)) @@ -43,21 +41,10 @@ examples/benchmarks/%-fixed: dummy else \ mv $@ $(FILE); \ fi -examples/benchmarks/%-nassau-fixed: dummy - (head -n 1 $(FILE)-nassau && bash -c "echo '' | cargo run --features nassau --example $$(head -n 1 $(FILE)-nassau)") > $@ - if diff --color $(FILE)-nassau $@; then \ - rm $@; \ - else \ - mv $@ $(FILE)-nassau; \ - fi - examples/benchmarks/%: dummy (head -n 1 $@ && bash -c "echo '' | cargo run --example $$(head -n 1 $@)") | diff --color $@ - -examples/benchmarks/%-nassau: dummy - (head -n 1 $@ && bash -c "echo '' | cargo run --features nassau --example $$(head -n 1 $@)") | diff --color $@ - - examples/benchmarks/%-concurrent: FILE = examples/benchmarks/$* examples/benchmarks/%-concurrent: dummy @{ \ diff --git a/ext/crates/algebra/src/module/homomorphism/mod.rs b/ext/crates/algebra/src/module/homomorphism/mod.rs index 540b34ac4b..e83ffa5aad 100644 --- a/ext/crates/algebra/src/module/homomorphism/mod.rs +++ b/ext/crates/algebra/src/module/homomorphism/mod.rs @@ -39,7 +39,7 @@ pub use quotient_homomorphism::{QuotientHomomorphism, QuotientHomomorphismSource /// /// Note that an instance of a `ModuleHomomorphism` need not have the data available, even after /// `compute_auxiliary_data_through_degree` is invoked. -pub trait ModuleHomomorphism: Send + Sync { +pub trait ModuleHomomorphism: Send + Sync + 'static { type Source: Module; type Target: Module::Algebra>; diff --git a/ext/crates/fp/src/matrix/matrix_inner.rs b/ext/crates/fp/src/matrix/matrix_inner.rs index 392625cb6b..8c6dd93b38 100644 --- a/ext/crates/fp/src/matrix/matrix_inner.rs +++ b/ext/crates/fp/src/matrix/matrix_inner.rs @@ -1081,6 +1081,10 @@ impl Matrix { } pub fn trim(&mut self, row_start: usize, row_end: usize, col_start: usize, keep_pivots: bool) { + assert!( + !keep_pivots || col_start == 0, + "trim cannot keep pivots when col_start != 0: column indices would shift" + ); let mut new = Self::new(self.prime(), row_end - row_start, self.columns - col_start); for (i, mut row) in new.iter_mut().enumerate() { row.assign(self.row(row_start + i).restrict(col_start, self.columns)); diff --git a/ext/examples/benchmarks/differentials-S_2-nassau b/ext/examples/benchmarks/differentials-S_2-nassau deleted file mode 100644 index a25c426760..0000000000 --- a/ext/examples/benchmarks/differentials-S_2-nassau +++ /dev/null @@ -1,22 +0,0 @@ -differentials -- S_2 "" 10 5 -d x_(0,0,0) = 0 -d x_(0,1,0) = P(1) x_(0,0,0) -d x_(0,2,0) = P(1) x_(0,1,0) -d x_(0,3,0) = P(1) x_(0,2,0) -d x_(0,4,0) = P(1) x_(0,3,0) -d x_(0,5,0) = P(1) x_(0,4,0) -d x_(1,1,0) = P(2) x_(0,0,0) -d x_(2,2,0) = P(3) x_(0,1,0) + P(2) x_(1,1,0) -d x_(3,1,0) = P(4) x_(0,0,0) -d x_(3,2,0) = P(4) x_(0,1,0) + P(0, 1) x_(1,1,0) + P(1) x_(3,1,0) -d x_(3,3,0) = P(4) x_(0,2,0) + P(2) x_(2,2,0) + P(1) x_(3,2,0) -d x_(6,2,0) = P(1, 2) x_(0,1,0) + P(0, 2) x_(1,1,0) + P(4) x_(3,1,0) -d x_(7,1,0) = P(8) x_(0,0,0) -d x_(7,2,0) = P(8) x_(0,1,0) + P(2, 1) x_(3,1,0) + P(1) x_(7,1,0) -d x_(7,3,0) = P(8) x_(0,2,0) + P(2, 1) x_(3,2,0) + P(1) x_(7,2,0) -d x_(7,4,0) = P(8) x_(0,3,0) + P(2, 1) x_(3,3,0) + P(1) x_(7,3,0) -d x_(8,2,0) = P(8) x_(1,1,0) + P(1, 0, 1) x_(1,1,0) + P(0, 2) x_(3,1,0) + P(2) x_(7,1,0) -d x_(8,3,0) = P(4, 1) x_(2,2,0) + P(1, 2) x_(2,2,0) + P(0, 0, 1) x_(2,2,0) + P(6) x_(3,2,0) + P(3) x_(6,2,0) + P(0, 1) x_(6,2,0) -d x_(9,3,0) = P(3, 0, 1) x_(0,2,0) + P(8) x_(2,2,0) + P(1, 0, 1) x_(2,2,0) + P(4) x_(6,2,0) + P(3) x_(7,2,0) + P(2) x_(8,2,0) -d x_(9,4,0) = P(4, 2) x_(0,3,0) + P(4, 1) x_(3,3,0) + P(1, 2) x_(3,3,0) + P(0, 0, 1) x_(3,3,0) + P(2) x_(8,3,0) -d x_(9,5,0) = P(10) x_(0,4,0) + P(3) x_(7,4,0) + P(0, 1) x_(7,4,0) diff --git a/ext/examples/benchmarks/filtration_one-S_2-nassau b/ext/examples/benchmarks/filtration_one-S_2-nassau deleted file mode 100644 index 20d8843a4d..0000000000 --- a/ext/examples/benchmarks/filtration_one-S_2-nassau +++ /dev/null @@ -1,33 +0,0 @@ -filtration_one -- S_2 "" 10 5 -h_0 x_(0, 0, 0) = [1] -h_1 x_(0, 0, 0) = [1] -h_2 x_(0, 0, 0) = [1] -h_3 x_(0, 0, 0) = [1] -h_0 x_(0, 1, 0) = [1] -h_2 x_(0, 1, 0) = [1] -h_3 x_(0, 1, 0) = [1] -h_0 x_(0, 2, 0) = [1] -h_2 x_(0, 2, 0) = [1] -h_3 x_(0, 2, 0) = [1] -h_0 x_(0, 3, 0) = [1] -h_3 x_(0, 3, 0) = [1] -h_0 x_(0, 4, 0) = [1] -h_1 x_(1, 1, 0) = [1] -h_3 x_(1, 1, 0) = [1] -h_1 x_(2, 2, 0) = [1] -h_3 x_(2, 2, 0) = [1] -h_0 x_(3, 1, 0) = [1] -h_2 x_(3, 1, 0) = [1] -h_0 x_(3, 2, 0) = [1] -h_1 x_(6, 2, 0) = [0] -h_2 x_(6, 2, 0) = [1] -h_0 x_(7, 1, 0) = [1] -h_1 x_(7, 1, 0) = [1] -h_0 x_(7, 2, 0) = [1] -h_1 x_(7, 2, 0) = [0] -h_0 x_(7, 3, 0) = [1] -h_0 x_(8, 2, 0) = [0] -h_1 x_(8, 2, 0) = [1] -h_1 x_(8, 3, 0) = [1] -h_0 x_(9, 3, 0) = [0] -h_0 x_(9, 4, 0) = [0] diff --git a/ext/examples/benchmarks/lift_hom-g-S_2-nassau b/ext/examples/benchmarks/lift_hom-g-S_2-nassau deleted file mode 100644 index 3176d0cee7..0000000000 --- a/ext/examples/benchmarks/lift_hom-g-S_2-nassau +++ /dev/null @@ -1,12 +0,0 @@ -lift_hom -- S_2 /tmp/test_nassau_s_2 25 9 S_2 g 20 4 [1] -g x_(0, 0, 0) = [1] -g x_(0, 1, 0) = [1] -g x_(0, 2, 0) = [1] -g x_(0, 3, 0) = [] -g x_(0, 4, 0) = [] -g x_(0, 5, 0) = [] -g x_(1, 1, 0) = [1] -g x_(2, 2, 0) = [] -g x_(3, 1, 0) = [1] -g x_(3, 2, 0) = [1] -g x_(3, 3, 0) = [0] diff --git a/ext/examples/benchmarks/resolve-S_2-nassau b/ext/examples/benchmarks/resolve-S_2-nassau deleted file mode 100644 index 0898911373..0000000000 --- a/ext/examples/benchmarks/resolve-S_2-nassau +++ /dev/null @@ -1,14 +0,0 @@ -resolve -- S_2 "" 30 11 "" -· · -· · · -· · · -· · · · -· · · · · · -· · · · · · · · · -· · · · : · · · · · · -· · · · · · : · · · -· · · · · · · · · · · -· · · · · · · · · · -· · · · · -· - diff --git a/ext/examples/benchmarks/resolve_through_stem-S_2-nassau b/ext/examples/benchmarks/resolve_through_stem-S_2-nassau deleted file mode 100644 index 9f84a24d24..0000000000 --- a/ext/examples/benchmarks/resolve_through_stem-S_2-nassau +++ /dev/null @@ -1,14 +0,0 @@ -resolve_through_stem -- S_2 "" 30 11 "" -· · · · · · -· · · · · · · · · -· · · · : · · · · · -· · · · · · · · · · -· · · · · · · · · -· · · · · · · · · · · -· · · · : · · · · · · · -· · · · · · : · · · · -· · · · · · · · · · · · -· · · · · · · · · · · -· · · · · -· - diff --git a/ext/examples/benchmarks/secondary-C2-nassau b/ext/examples/benchmarks/secondary-C2-nassau deleted file mode 100644 index 0dc2bb66f5..0000000000 --- a/ext/examples/benchmarks/secondary-C2-nassau +++ /dev/null @@ -1,12 +0,0 @@ -secondary -- C2 /tmp/test_nassau_c2 30 7 "" -d_2 x_(9, 2, 0) = [0] -d_2 x_(10, 3, 0) = [0] -d_2 x_(17, 3, 0) = [0] -d_2 x_(17, 4, 0) = [1] -d_2 x_(18, 2, 0) = [0] -d_2 x_(18, 4, 0) = [0] -d_2 x_(19, 5, 0) = [1] -d_2 x_(20, 3, 0) = [0] -d_2 x_(22, 3, 0) = [0] -d_2 x_(22, 4, 0) = [0] -d_2 x_(24, 5, 0) = [0] diff --git a/ext/examples/benchmarks/secondary_product-h_0-S_2-nassau b/ext/examples/benchmarks/secondary_product-h_0-S_2-nassau deleted file mode 100644 index 75dbb090de..0000000000 --- a/ext/examples/benchmarks/secondary_product-h_0-S_2-nassau +++ /dev/null @@ -1,38 +0,0 @@ -secondary_product -- S_2 /tmp/test_nassau_s_2 30 7 h_0 0 1 [1] -[h_0] [x_(0, 0, 0)] = [1] + λ [0] -[h_0] [x_(0, 1, 0)] = [1] + λ [1] -[h_0] [x_(0, 2, 0)] = [1] + λ [0] -[h_0] [x_(0, 3, 0)] = [1] + λ [1] -[h_0] [x_(0, 4, 0)] = [1] + λ [0] -[h_0] [x_(0, 5, 0)] = [1] + λ [1] -[h_0] [x_(3, 1, 0)] = [1] + λ [1] -[h_0] [x_(3, 2, 0)] = [1] + λ [] -[h_0] [x_(7, 1, 0)] = [1] + λ [0] -[h_0] [x_(7, 2, 0)] = [1] + λ [1] -[h_0] [x_(7, 3, 0)] = [1] + λ [] -[h_0] [x_(8, 2, 0)] = [0] + λ [] -[h_0] [x_(9, 3, 0)] = [0] + λ [0] -[h_0] [x_(9, 4, 0)] = [0] + λ [] -[h_0] [x_(11, 5, 0)] = [1] + λ [1] -[h_0] [x_(14, 2, 0)] = [1] + λ [0] -[h_0] [x_(14, 3, 0)] = [0] + λ [1] -[h_0] [x_(14, 4, 0)] = [1] + λ [0] -[h_0] [x_(14, 5, 0)] = [1] + λ [] -[h_0] λ x_(15, 1, 0) = λ [1] -[h_0] [x_(15, 2, 0)] = [1] + λ [1] -[h_0] [x_(15, 3, 0)] = [1] + λ [0, 0] -[h_0] [x_(15, 4, 0)] = [1, 0] + λ [1] -[h_0] [x_(15, 5, 0)] = [1] + λ [0] -[h_0] [x_(15, 5, 1)] = [0] + λ [0] -[h_0] [x_(17, 3, 0)] = [0] + λ [0] -[h_0] λ x_(17, 4, 0) = λ [1] -[h_0] [x_(17, 5, 0)] = [1] + λ [0] -[h_0] [x_(18, 2, 0)] = [1] + λ [1, 0] -[h_0] [x_(18, 3, 0)] = [1, 0] + λ [0] -[h_0] λ x_(18, 4, 1) = λ [1] -[h_0] [x_(18, 4, 0)] = [0] + λ [] -[h_0] [x_(20, 4, 0)] = [1] + λ [1] -[h_0] [x_(20, 5, 0)] = [1] + λ [] -[h_0] [x_(21, 3, 0)] = [] + λ [0] -[h_0] [x_(23, 4, 0)] = [0] + λ [0] -[h_0] [x_(23, 5, 0)] = [1] + λ [0] diff --git a/ext/examples/benchmarks/steenrod-c_0-S_2-nassau b/ext/examples/benchmarks/steenrod-c_0-S_2-nassau deleted file mode 100644 index d0512568b5..0000000000 --- a/ext/examples/benchmarks/steenrod-c_0-S_2-nassau +++ /dev/null @@ -1,6 +0,0 @@ -steenrod -- S_2 /tmp/save_nassau_s_2 8 3 [1] -Dimensions of Yoneda representative: 1 5 7 4 1 -Sq^3 x_(8, 3, 0) = [1] -Sq^2 x_(8, 3, 0) = [1] -Sq^1 x_(8, 3, 0) = [0, 1] -Sq^0 x_(8, 3, 0) = [1] diff --git a/ext/examples/benchmarks/yoneda-g-S_2-nassau b/ext/examples/benchmarks/yoneda-g-S_2-nassau deleted file mode 100644 index f25dafd924..0000000000 --- a/ext/examples/benchmarks/yoneda-g-S_2-nassau +++ /dev/null @@ -1,6 +0,0 @@ -yoneda -- S_2 "" 20 4 [1] -Dimension of 0th module is 15 -Dimension of 1th module is 41 -Dimension of 2th module is 32 -Dimension of 3th module is 6 -Dimension of 4th module is 1 diff --git a/ext/examples/bruner.rs b/ext/examples/bruner.rs index 71c5c0e22a..eb353d9ded 100644 --- a/ext/examples/bruner.rs +++ b/ext/examples/bruner.rs @@ -36,9 +36,6 @@ use ext::{ use fp::{matrix::Matrix, prime::TWO, vector::FpVector}; use sseq::coordinates::{Bidegree, BidegreeGenerator}; -#[cfg(feature = "nassau")] -type FreeModule = FM; -#[cfg(not(feature = "nassau"))] type FreeModule = FM; type FreeModuleHomomorphism = FMH; @@ -134,10 +131,6 @@ fn get_element( /// Create a new `FiniteChainComplex` with `num_s` many non-zero modules. fn create_chain_complex(num_s: usize) -> FiniteChainComplex { - #[cfg(feature = "nassau")] - let algebra: Arc = Arc::new(MilnorAlgebra::new(TWO, false)); - - #[cfg(not(feature = "nassau"))] let algebra: Arc = Arc::new(algebra::SteenrodAlgebra::MilnorAlgebra( MilnorAlgebra::new(TWO, false), )); @@ -235,12 +228,6 @@ fn main() -> anyhow::Result<()> { core::result::Result::::Ok(PathBuf::from(x)) }); - #[cfg(feature = "nassau")] - assert!( - save_dir.is_some(), - "A save directory is required for comparison between Bruner and Nassau resolutions." - ); - let resolution = ext::utils::construct("S_2@milnor", save_dir).unwrap(); resolution.compute_through_stem(max); diff --git a/ext/examples/ext_m_n.rs b/ext/examples/ext_m_n.rs index 0796354f3d..05895e3054 100644 --- a/ext/examples/ext_m_n.rs +++ b/ext/examples/ext_m_n.rs @@ -11,12 +11,8 @@ fn main() -> anyhow::Result<()> { eprintln!("This script computes Ext(M, N)"); let res = ext::utils::query_module_only("Module M", None, false)?; let module_spec = query::raw("Module N", ext::utils::parse_module_name); - #[cfg(not(feature = "nassau"))] let module = algebra::module::steenrod_module::from_json(res.algebra(), &module_spec)?; - #[cfg(feature = "nassau")] - let module = algebra::module::FDModule::from_json(res.algebra(), &module_spec)?; - let max = Bidegree::n_s( query::raw("Max n", str::parse), query::raw("Max s", str::parse), diff --git a/ext/examples/lift_hom.rs b/ext/examples/lift_hom.rs index 3958a6069c..9e13ad39a1 100644 --- a/ext/examples/lift_hom.rs +++ b/ext/examples/lift_hom.rs @@ -42,7 +42,7 @@ use std::{path::PathBuf, sync::Arc}; use algebra::module::Module; -use anyhow::{Context, anyhow}; +use anyhow::Context; use ext::{ chain_complex::{AugmentedChainComplex, ChainComplex, FreeChainComplex}, resolution_homomorphism::ResolutionHomomorphism, @@ -61,30 +61,25 @@ fn main() -> anyhow::Result<()> { ); let source_name = source.name(); - let target = query::with_default("Target module", source_name, |s| { - if s == source_name { - Ok(Arc::clone(&source)) - } else if cfg!(feature = "nassau") { - Err(anyhow!("Can only resolve S_2 with nassau")) - } else { - let config: utils::Config = s.try_into()?; - let save_dir = query::optional("Target save directory", |x| { - Result::::Ok(PathBuf::from(x)) - }); - - let mut target = utils::construct(config, save_dir) - .context("Failed to load module from save file") - .unwrap(); - - target.set_name(s.to_owned()); - - #[cfg(feature = "nassau")] - unreachable!(); - - #[cfg(not(feature = "nassau"))] - Ok(Arc::new(target)) - } - }); + let target: Arc = + query::with_default("Target module", source_name, |s| -> anyhow::Result<_> { + if s == source_name { + Ok(Arc::clone(&source)) + } else { + let config: utils::Config = s.try_into()?; + let save_dir = query::optional("Target save directory", |x| { + Result::::Ok(PathBuf::from(x)) + }); + + let mut target = utils::construct(config, save_dir) + .context("Failed to load module from save file") + .unwrap(); + + target.set_name(s.to_owned()); + + Ok(Arc::new(target)) + } + }); assert_eq!(source.prime(), target.prime()); let p = source.prime(); diff --git a/ext/examples/mahowald_invariant.rs b/ext/examples/mahowald_invariant.rs index 0afe97f056..40ae448045 100644 --- a/ext/examples/mahowald_invariant.rs +++ b/ext/examples/mahowald_invariant.rs @@ -109,7 +109,7 @@ struct MahowaldInvariant { } fn resolve_s_2(s_2_path: Option, k_max: i32) -> Result> { - let s_2_resolution = Arc::new(utils::construct_standard("S_2", s_2_path)?); + let s_2_resolution = Arc::new(utils::construct("S_2", s_2_path)?); // Here are some bounds on the bidegrees in which we have should have resolutions available. // // A class in stem n won't be detected before RP_-{n+1}_inf, so we can only detect Mahowald @@ -142,7 +142,7 @@ impl PKData { if let Some(p) = p_k_path.as_mut() { p.push(PathBuf::from(&format!("RP_{minus_k}_inf", minus_k = -k))); }; - let resolution = Arc::new(utils::construct_standard( + let resolution = Arc::new(utils::construct( (p_k_config, AlgebraType::Milnor), p_k_path, )?); diff --git a/ext/flake.nix b/ext/flake.nix index cfc98ca094..36ff098e83 100644 --- a/ext/flake.nix +++ b/ext/flake.nix @@ -47,7 +47,6 @@ make lint make test make benchmarks - make benchmarks-nassau make benchmarks-concurrent make miri ''); diff --git a/ext/src/chain_complex/mod.rs b/ext/src/chain_complex/mod.rs index dd19d9a70f..07a2686d89 100644 --- a/ext/src/chain_complex/mod.rs +++ b/ext/src/chain_complex/mod.rs @@ -160,7 +160,7 @@ where /// A chain complex is defined to start in degree 0. The min_degree is the min_degree of the /// modules in the chain complex, all of which must be the same. -pub trait ChainComplex: Send + Sync { +pub trait ChainComplex: Send + Sync + 'static { type Algebra: Algebra; type Module: Module; type Homomorphism: ModuleHomomorphism; diff --git a/ext/src/lib.rs b/ext/src/lib.rs index ad5a6afb26..61886dcf60 100644 --- a/ext/src/lib.rs +++ b/ext/src/lib.rs @@ -160,9 +160,6 @@ //! $\mathrm{tmf}$ modules. //! - `logging`: Print timing information of the computations to stderr. Note that this has no //! effect unless the `RUST_LOG` environment variable is set appropriately. -//! - `nassau`: Use Nassau's algorithm to compute the minimal resolution instead of the usual -//! minimal resolution algorithm. When this feature is enabled, only finite dimensional modules -//! at the prime 2 can be resolved. #![allow(clippy::upper_case_acronyms)] #![deny(clippy::use_self, unsafe_op_in_unsafe_fn)] @@ -179,7 +176,6 @@ use algebra::module::SteenrodModule; use crate::chain_complex::FiniteChainComplex; pub type CCC = FiniteChainComplex; -pub mod nassau; pub mod secondary; pub mod utils; diff --git a/ext/src/resolution.rs b/ext/src/resolution/classical.rs similarity index 93% rename from ext/src/resolution.rs rename to ext/src/resolution/classical.rs index 1d138cafd4..d42b1de64d 100644 --- a/ext/src/resolution.rs +++ b/ext/src/resolution/classical.rs @@ -1,5 +1,3 @@ -//! This module exports the [`Resolution`] object, which is a chain complex resolving a module. In -//! particular, this contains the core logic that compute minimal resolutions. use std::sync::{Arc, Mutex, mpsc}; use algebra::{ @@ -26,7 +24,7 @@ use crate::{ utils::parallel::ParallelGuard, }; -/// In [`MuResolution::compute_through_stem`] and [`MuResolution::compute_through_bidegree`], we pass +/// In [`MuClassicalResolution::compute_through_stem`] and [`MuClassicalResolution::compute_through_bidegree`], we pass /// this struct around to inform the supervisor what bidegrees have been computed. We use an /// explicit struct instead of a tuple to avoid an infinite type problem. struct SenderData { @@ -72,12 +70,9 @@ impl SenderData { /// number if needs be, but up to the 140th stem we only see at most 8 new generators. const MAX_NEW_GENS: usize = 10; -pub type Resolution = MuResolution; -pub type UnstableResolution = MuResolution; - -/// A minimal resolution of a chain complex. The functions [`MuResolution::compute_through_stem`] and -/// [`MuResolution::compute_through_bidegree`] extends the minimal resolution to the given bidegree. -pub struct MuResolution +/// A minimal resolution of a chain complex. The functions [`MuClassicalResolution::compute_through_stem`] and +/// [`MuClassicalResolution::compute_through_bidegree`] extends the minimal resolution to the given bidegree. +pub struct MuClassicalResolution where CC::Algebra: MuAlgebra, { @@ -112,15 +107,10 @@ where pub load_quasi_inverse: bool, } -impl MuResolution +impl MuClassicalResolution where CC::Algebra: MuAlgebra, { - pub fn new(complex: Arc) -> Self { - // It doesn't error if the save file is None - Self::new_with_save(complex, None).unwrap() - } - pub fn new_with_save( complex: Arc, save_dir: impl Into, @@ -892,7 +882,7 @@ where } } -impl ChainComplex for MuResolution +impl ChainComplex for MuClassicalResolution where CC::Algebra: MuAlgebra, { @@ -962,7 +952,7 @@ where } } -impl AugmentedChainComplex for MuResolution +impl AugmentedChainComplex for MuClassicalResolution where CC::Algebra: MuAlgebra, { @@ -980,48 +970,50 @@ where #[cfg(test)] mod tests { - use expect_test::expect; + // use expect_test::expect; - use super::*; - use crate::{chain_complex::FreeChainComplex, utils::construct_standard}; + // use super::*; + // use crate::{chain_complex::FreeChainComplex, utils::construct_standard}; #[test] fn test_restart_stem() { - let res = construct_standard::("S_2", None).unwrap(); - res.compute_through_stem(Bidegree::n_s(14, 8)); - res.compute_through_bidegree(Bidegree::s_t(5, 19)); - - expect![[r#" - · - · · - · · · · - · · · · - · · · · · - · · · · · · · - · · · · · · · · · - · · · · · - · - "#]] - .assert_eq(&res.graded_dimension_string()); + todo!() + // let res = construct_standard::("S_2", None).unwrap(); + // res.compute_through_stem(Bidegree::n_s(14, 8)); + // res.compute_through_bidegree(Bidegree::s_t(5, 19)); + + // expect![[r#" + // · + // · · + // · · · · + // · · · · + // · · · · · + // · · · · · · · + // · · · · · · · · · + // · · · · · + // · + // "#]] + // .assert_eq(&res.graded_dimension_string()); } #[test] fn test_apply_quasi_inverse() { - let tempdir = tempfile::TempDir::new().unwrap(); + todo!() + // let tempdir = tempfile::TempDir::new().unwrap(); - let mut res = - construct_standard::("S_2", Some(tempdir.path().into())).unwrap(); - res.load_quasi_inverse = false; + // let mut res = + // construct_standard::("S_2", Some(tempdir.path().into())).unwrap(); + // res.load_quasi_inverse = false; - let b = Bidegree::s_t(8, 8); - res.compute_through_bidegree(b); + // let b = Bidegree::s_t(8, 8); + // res.compute_through_bidegree(b); - assert!(res.differential(8).quasi_inverse(8).is_none()); + // assert!(res.differential(8).quasi_inverse(8).is_none()); - let v = FpVector::new(res.prime(), res.module(7).dimension(8)); - let mut w = FpVector::new(res.prime(), res.module(8).dimension(8)); + // let v = FpVector::new(res.prime(), res.module(7).dimension(8)); + // let mut w = FpVector::new(res.prime(), res.module(8).dimension(8)); - assert!(res.apply_quasi_inverse(&mut [w.as_slice_mut()], b, &[v.as_slice()])); - assert!(w.is_zero()); + // assert!(res.apply_quasi_inverse(&mut [w.as_slice_mut()], b, &[v.as_slice()])); + // assert!(w.is_zero()); } } diff --git a/ext/src/resolution/mod.rs b/ext/src/resolution/mod.rs new file mode 100644 index 0000000000..d6aea6cb3d --- /dev/null +++ b/ext/src/resolution/mod.rs @@ -0,0 +1,150 @@ +//! This module exports the [`Resolution`] object, which is a chain complex resolving a module. In +//! particular, this contains the core logic that compute minimal resolutions. + +use std::sync::Arc; + +use algebra::{ + MilnorAlgebra, MuAlgebra, SteenrodAlgebra, + module::{FDModule, MuFreeModule, homomorphism::MuFreeModuleHomomorphism}, +}; +use sseq::coordinates::Bidegree; + +use crate::{ + chain_complex::{AugmentedChainComplex, ChainComplex}, + save::SaveDirectory, +}; + +mod classical; +mod nassau; + +use classical::MuClassicalResolution; +use nassau::NassauResolution; + +pub type Resolution = MuResolution; +pub type UnstableResolution = MuResolution; + +pub enum MuResolution +where + CC::Algebra: MuAlgebra, +{ + Classical(MuClassicalResolution), + Nassau(NassauResolution), +} + +impl MuResolution +where + CC::Algebra: MuAlgebra, +{ + pub fn new(complex: Arc) -> Self { + // It doesn't error if the save file is None + Self::new_with_save(complex, None).unwrap() + } + + pub fn new_with_save( + complex: Arc, + save_dir: impl Into, + ) -> anyhow::Result { + Ok(match Self::try_into_nassau(complex) { + Ok(module) => Self::Nassau(NassauResolution::new_with_save(module, save_dir)?), + Err(complex) => { + Self::Classical(MuClassicalResolution::new_with_save(complex, save_dir)?) + } + }) + } + + fn try_into_nassau(complex: Arc) -> Result>, Arc> { + todo!() + } + + pub fn name(&self) -> &str { + match self { + Self::Classical(classical) => classical.name(), + Self::Nassau(nassau) => nassau.name(), + } + } + + pub fn compute_through_stem(&self, max: Bidegree) { + match self { + Self::Classical(classical) => classical.compute_through_stem(max), + Self::Nassau(nassau) => nassau.compute_through_stem(max), + } + } + + pub fn set_load_quasi_inverse(&mut self, load_quasi_inverse: bool) { + match self { + Self::Classical(classical) => classical.load_quasi_inverse = load_quasi_inverse, + Self::Nassau(nassau) => assert!( + !load_quasi_inverse || nassau.save_dir().is_some(), + "Quasi inverse loading not supported with Nassau. Please use a save directory \ + instead" + ), + } + } + + pub fn set_name(&mut self, name: String) { + match self { + Self::Classical(classical) => classical.set_name(name), + Self::Nassau(nassau) => nassau.set_name(name), + } + } +} + +impl ChainComplex for MuResolution +where + CC::Algebra: MuAlgebra, +{ + type Algebra = CC::Algebra; + type Homomorphism = MuFreeModuleHomomorphism>; + type Module = MuFreeModule; + + fn algebra(&self) -> Arc { + match self { + Self::Classical(classical) => classical.algebra(), + Self::Nassau(nassau) => todo!(), + } + } + + fn min_degree(&self) -> i32 { + todo!() + } + + fn zero_module(&self) -> Arc { + todo!() + } + + fn module(&self, homological_degree: i32) -> Arc { + todo!() + } + + fn differential(&self, s: i32) -> Arc { + todo!() + } + + fn has_computed_bidegree(&self, b: sseq::coordinates::Bidegree) -> bool { + todo!() + } + + fn compute_through_bidegree(&self, b: sseq::coordinates::Bidegree) { + todo!() + } + + fn next_homological_degree(&self) -> i32 { + todo!() + } +} + +impl AugmentedChainComplex for MuResolution +where + CC::Algebra: MuAlgebra, +{ + type ChainMap = as AugmentedChainComplex>::ChainMap; + type TargetComplex = as AugmentedChainComplex>::TargetComplex; + + fn target(&self) -> Arc { + todo!() + } + + fn chain_map(&self, s: i32) -> Arc { + todo!() + } +} diff --git a/ext/src/nassau.rs b/ext/src/resolution/nassau.rs similarity index 94% rename from ext/src/nassau.rs rename to ext/src/resolution/nassau.rs index 8d1919136a..a9b8d8064c 100644 --- a/ext/src/nassau.rs +++ b/ext/src/resolution/nassau.rs @@ -1,16 +1,10 @@ //! This module implements [Nassau's algorithm](https://arxiv.org/abs/1910.04063). //! -//! The main export is the [`Resolution`] object, which is a resolution of the sphere at the prime 2 -//! using Nassau's algorithm. It aims to provide an API similar to +//! The main export is the [`Resolution`] object, which is a resolution at the prime 2 using +//! Nassau's algorithm. It aims to provide an API similar to //! [`resolution::Resolution`](crate::resolution::Resolution). From an API point of view, the main //! difference between the two is that our `Resolution` is a chain complex over [`MilnorAlgebra`] //! over [`SteenrodAlgebra`](algebra::SteenrodAlgebra). -//! -//! To make use of this resolution in the example scripts, enable the `nassau` feature. This will -//! cause [`utils::query_module`](crate::utils::query_module) to return the `Resolution` from this -//! module instead of [`resolution`](crate::resolution). There is no formal polymorphism involved; -//! the feature changes the return type of the function. While this is an incorrect use of features, -//! we find that this the easiest way to make all scripts support both types of resolutions. use std::{ fmt::Display, @@ -22,11 +16,10 @@ use algebra::{ Algebra, combinatorics, milnor_algebra::{MilnorAlgebra, PPartEntry}, module::{ - FreeModule, GeneratorData, Module, ZeroModule, + FDModule, FreeModule, GeneratorData, Module, homomorphism::{FreeModuleHomomorphism, FullModuleHomomorphism, ModuleHomomorphism}, }, }; -use anyhow::anyhow; use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt}; use fp::{ matrix::{AugmentedMatrix, Matrix}, @@ -62,7 +55,6 @@ impl SenderData { } pub(crate) fn send_retry(b: Bidegree, sender: mpsc::Sender) { - tracing::info!(%b, "retrying"); sender .send(Self { b, @@ -388,25 +380,22 @@ enum Magic { Fix = -3, } -/// A resolution of `S_2` using Nassau's algorithm. -/// -/// This aims to have an API similar to that of -/// [`resolution::Resolution`](crate::resolution::Resolution). From an API point of view, the main -/// difference between the two is that this is a chain complex over [`MilnorAlgebra`] over -/// [`SteenrodAlgebra`](algebra::SteenrodAlgebra). -pub struct Resolution> { +type FDMM = FDModule; + +/// A resolution of a finite-dimensional module using Nassau's algorithm +pub struct NassauResolution { lock: Mutex<()>, name: String, max_degree: i32, modules: OnceBiVec>>, zero_module: Arc>, differentials: OnceBiVec>>>, - target: Arc>, - chain_maps: OnceBiVec>>, + target: Arc>, + chain_maps: OnceBiVec>>, save_dir: SaveDirectory, } -impl> Resolution { +impl NassauResolution { pub fn name(&self) -> &str { &self.name } @@ -415,18 +404,16 @@ impl> Resolution { self.name = name; } - pub fn new(module: Arc) -> Self { + pub fn new(module: Arc) -> Self { Self::new_with_save(module, None).unwrap() } pub fn new_with_save( - module: Arc, + module: Arc, save_dir: impl Into, ) -> anyhow::Result { let save_dir = save_dir.into(); - let max_degree = module - .max_degree() - .ok_or_else(|| anyhow!("Nassau's algorithm requires bounded module"))?; + let max_degree = module.max_degree().unwrap(); let target = Arc::new(FiniteChainComplex::ccdz(module)); if let Some(p) = save_dir.write() { @@ -495,7 +482,7 @@ impl> Resolution { }); } - #[tracing::instrument(skip_all, fields(throughput))] + #[tracing::instrument(skip_all, fields(signature = ?signature, throughput))] fn write_qi( f: &mut Option, scratch: &mut FpVector, @@ -993,7 +980,7 @@ impl> Resolution { } } -impl> ChainComplex for Resolution { +impl ChainComplex for NassauResolution { type Algebra = MilnorAlgebra; type Homomorphism = FreeModuleHomomorphism>; type Module = FreeModule; @@ -1224,9 +1211,9 @@ impl> ChainComplex for Resolution { } } -impl> AugmentedChainComplex for Resolution { - type ChainMap = FreeModuleHomomorphism; - type TargetComplex = FiniteChainComplex>; +impl AugmentedChainComplex for NassauResolution { + type ChainMap = FreeModuleHomomorphism; + type TargetComplex = FiniteChainComplex>; fn target(&self) -> Arc { Arc::clone(&self.target) @@ -1239,28 +1226,29 @@ impl> AugmentedChainComplex for Resolutio #[cfg(test)] mod tests { - use expect_test::expect; + // use expect_test::expect; use super::*; #[test] fn test_restart_stem() { - let res = crate::utils::construct_nassau("S_2", None).unwrap(); - res.compute_through_stem(Bidegree::n_s(14, 8)); - res.compute_through_bidegree(Bidegree::s_t(5, 19)); - - expect![[r#" - · - · · - · · · · - · · · · - · · · · · - · · · · · · · - · · · · · · · · · - · · · · · - · - "#]] - .assert_eq(&res.graded_dimension_string()); + todo!() + // let res = crate::utils::construct_standard("S_2", None).unwrap(); + // res.compute_through_stem(Bidegree::n_s(14, 8)); + // res.compute_through_bidegree(Bidegree::s_t(5, 19)); + + // expect![[r#" + // · + // · · + // · · · · + // · · · · + // · · · · · + // · · · · · · · + // · · · · · · · · · + // · · · · · + // · + // "#]] + // .assert_eq(&res.graded_dimension_string()); } #[test] diff --git a/ext/src/utils.rs b/ext/src/utils.rs index acfb352a49..25d6b5148a 100644 --- a/ext/src/utils.rs +++ b/ext/src/utils.rs @@ -16,17 +16,9 @@ use crate::{ save::SaveDirectory, }; -// We build docs with --all-features so the docs are at the feature = "nassau" version -#[cfg(not(feature = "nassau"))] +/// The resolution type returned by [`query_module`] and [`construct`]. pub type QueryModuleResolution = Resolution; -/// The type returned by [`query_module`]. The value of this type depends on whether -/// [`nassau`](crate::nassau) is enabled. In any case, it is an augmented free chain complex over -/// either [`SteenrodAlgebra`] or [`MilnorAlgebra`] and supports the `compute_through_stem` -/// function. -#[cfg(feature = "nassau")] -pub type QueryModuleResolution = crate::nassau::Resolution>; - const STATIC_MODULES_PATH: &str = concat!(env!("CARGO_MANIFEST_DIR"), "/../ext/steenrod_modules"); /// A config object is an object that specifies how a Steenrod module should be constructed. @@ -133,69 +125,8 @@ impl> TryFrom<(Value, T)> for Config { /// - `save_file`: The save file for the module. If it points to an invalid save file, an error is /// returned. /// -/// This dispatches to either [`construct_nassau`] or [`construct_standard`] depending on whether -/// the `nassau` feature is enabled. -pub fn construct( - module_spec: T, - save_dir: impl Into, -) -> anyhow::Result -where - anyhow::Error: From, - T: TryInto, -{ - #[cfg(feature = "nassau")] - { - construct_nassau(module_spec, save_dir) - } - - #[cfg(not(feature = "nassau"))] - { - construct_standard(module_spec, save_dir) - } -} - -/// See [`construct`] -pub fn construct_nassau( - module_spec: T, - save_dir: impl Into, -) -> anyhow::Result>> -where - anyhow::Error: From, - T: TryInto, -{ - let Config { - module: json, - algebra, - } = module_spec.try_into()?; - - if algebra == AlgebraType::Adem { - return Err(anyhow!("Nassau's algorithm requires Milnor's basis")); - } - if !json["profile"].is_null() { - return Err(anyhow!( - "Nassau's algorithm does not support non-trivial profile" - )); - } - if json["p"].as_i64() != Some(2) { - return Err(anyhow!("Nassau's algorithm does not support odd primes")); - } - if json["type"].as_str() != Some("finite dimensional module") { - return Err(anyhow!( - "Nassau's algorithm only supports finite dimensional modules" - )); - } - - let algebra = Arc::new(MilnorAlgebra::new(fp::prime::TWO, false)); - let module = Arc::new(FDModule::from_json(Arc::clone(&algebra), &json)?); - - if !json["cofiber"].is_null() { - return Err(anyhow!("Nassau's algorithm does not support cofiber")); - } - crate::nassau::Resolution::new_with_save(module, save_dir) -} - -/// See [`construct`] -pub fn construct_standard( +/// See [`construct_standard`] for what this accepts. +pub fn construct( module_spec: T, save_dir: impl Into, ) -> anyhow::Result> @@ -268,6 +199,63 @@ where crate::resolution::MuResolution::new_with_save(chain_complex, save_dir) } +// pub fn construct( +// module_spec: T, +// save_dir: impl Into, +// ) -> anyhow::Result +// where +// anyhow::Error: From, +// T: TryInto, +// { +// #[cfg(feature = "nassau")] +// { +// construct_nassau(module_spec, save_dir) +// } + +// #[cfg(not(feature = "nassau"))] +// { +// construct_standard(module_spec, save_dir) +// } +// } + +// pub fn construct_nassau( +// module_spec: T, +// save_dir: impl Into, +// ) -> anyhow::Result>> +// where +// anyhow::Error: From, +// T: TryInto, +// { +// let Config { +// module: json, +// algebra, +// } = module_spec.try_into()?; + +// if algebra == AlgebraType::Adem { +// return Err(anyhow!("Nassau's algorithm requires Milnor's basis")); +// } +// if !json["profile"].is_null() { +// return Err(anyhow!( +// "Nassau's algorithm does not support non-trivial profile" +// )); +// } +// if json["p"].as_i64() != Some(2) { +// return Err(anyhow!("Nassau's algorithm does not support odd primes")); +// } +// if json["type"].as_str() != Some("finite dimensional module") { +// return Err(anyhow!( +// "Nassau's algorithm only supports finite dimensional modules" +// )); +// } + +// let algebra = Arc::new(MilnorAlgebra::new(fp::prime::TWO, false)); +// let module = Arc::new(FDModule::from_json(Arc::clone(&algebra), &json)?); + +// if !json["cofiber"].is_null() { +// return Err(anyhow!("Nassau's algorithm does not support cofiber")); +// } +// crate::nassau::Resolution::new_with_save(module, save_dir) +// } /// Load a module specification from a JSON file. /// @@ -354,16 +342,7 @@ pub fn query_module_only( let load_quasi_inverse = load_quasi_inverse && resolution.save_dir().is_none(); - #[cfg(not(feature = "nassau"))] - { - resolution.load_quasi_inverse = load_quasi_inverse; - } - - #[cfg(feature = "nassau")] - assert!( - !load_quasi_inverse, - "Quasi inverse loading not support with Nassau. Please use a save directory instead" - ); + resolution.set_load_quasi_inverse(load_quasi_inverse); resolution.set_name(name); @@ -419,7 +398,7 @@ pub fn query_unstable_module(load_quasi_inverse: bool) -> anyhow::Result::Ok(PathBuf::from(x)) @@ -447,19 +426,8 @@ pub fn get_unit( bivec::BiVec::from_vec(0, vec![1]), ); - #[cfg(feature = "nassau")] - { - Arc::new(crate::nassau::Resolution::new_with_save( - Arc::new(module), - save_dir, - )?) - } - - #[cfg(not(feature = "nassau"))] - { - let cc = FiniteChainComplex::ccdz(Arc::new(steenrod_module::erase(module))); - Arc::new(Resolution::new_with_save(Arc::new(cc), save_dir)?) - } + let cc = FiniteChainComplex::ccdz(Arc::new(steenrod_module::erase(module))); + Arc::new(Resolution::new_with_save(Arc::new(cc), save_dir)?) }; Ok((is_unit, unit)) diff --git a/ext/tests/milnor_vs_adem.rs b/ext/tests/milnor_vs_adem.rs index af0b24a5f6..2ef9381ecd 100644 --- a/ext/tests/milnor_vs_adem.rs +++ b/ext/tests/milnor_vs_adem.rs @@ -1,6 +1,6 @@ use ext::{ chain_complex::{ChainComplex, FreeChainComplex}, - utils::{construct, construct_standard}, + utils::construct, }; use rstest::rstest; use sseq::coordinates::Bidegree; @@ -21,8 +21,8 @@ use sseq::coordinates::Bidegree; #[case("ksp", 30)] fn compare(#[case] module_name: &str, #[case] max_degree: i32) { let max = Bidegree::s_t(max_degree, max_degree); - let a = construct((module_name, "adem"), None).unwrap(); - let b = construct((module_name, "milnor"), None).unwrap(); + let a = construct::((module_name, "adem"), None).unwrap(); + let b = construct::((module_name, "milnor"), None).unwrap(); a.compute_through_bidegree(max); b.compute_through_bidegree(max); @@ -41,8 +41,8 @@ fn compare(#[case] module_name: &str, #[case] max_degree: i32) { #[case("Calpha[15]", 50)] fn compare_unstable(#[case] module_name: &str, #[case] max_degree: i32) { let max = Bidegree::s_t(max_degree, max_degree); - let a = construct_standard::((module_name, "adem"), None).unwrap(); - let b = construct_standard::((module_name, "milnor"), None).unwrap(); + let a = construct::((module_name, "adem"), None).unwrap(); + let b = construct::((module_name, "milnor"), None).unwrap(); a.compute_through_bidegree(max); b.compute_through_bidegree(max); diff --git a/ext/tests/milnor_vs_nassau.rs b/ext/tests/milnor_vs_nassau.rs index 2e6e18b81c..024e8e1415 100644 --- a/ext/tests/milnor_vs_nassau.rs +++ b/ext/tests/milnor_vs_nassau.rs @@ -1,10 +1,14 @@ use ext::{ chain_complex::{ChainComplex, FreeChainComplex}, - utils::{construct_nassau, construct_standard}, + utils::construct, }; use rstest::rstest; use sseq::coordinates::Bidegree; +/// Compare a resolution with Nassau (via save directory) against one without. +/// +/// When a save directory is provided and the module is eligible, Nassau's algorithm +/// is used automatically at runtime. #[rstest] #[trace] #[case("S_2", 30)] @@ -13,11 +17,19 @@ use sseq::coordinates::Bidegree; #[case("Csigma", 30)] fn compare(#[case] module_name: &str, #[case] max_degree: i32) { let max = Bidegree::s_t(max_degree, max_degree); - let a = construct_standard::(module_name, None).unwrap(); - let b = construct_nassau(module_name, None).unwrap(); - a.compute_through_bidegree(max); - b.compute_through_bidegree(max); + // Without save dir: classical algorithm + let classical = construct::(module_name, None).unwrap(); - assert_eq!(a.graded_dimension_string(), b.graded_dimension_string()); + // With save dir: Nassau's algorithm will be used if eligible + let save_dir = tempfile::tempdir().unwrap(); + let nassau = construct::(module_name, Some(save_dir.path().to_owned())).unwrap(); + + classical.compute_through_bidegree(max); + nassau.compute_through_bidegree(max); + + assert_eq!( + classical.graded_dimension_string(), + nassau.graded_dimension_string() + ); } diff --git a/ext/tests/module_construct_error.rs b/ext/tests/module_construct_error.rs index b6fa6e1948..2b3d26e8f5 100644 --- a/ext/tests/module_construct_error.rs +++ b/ext/tests/module_construct_error.rs @@ -19,6 +19,6 @@ fn module_construct_error() { } fn test(json: Value) { - assert!(construct((json.clone(), "adem"), None).is_err()); - assert!(construct((json, "milnor"), None).is_err()); + assert!(construct::((json.clone(), "adem"), None).is_err()); + assert!(construct::((json, "milnor"), None).is_err()); } diff --git a/ext/tests/save_load_resolution.rs b/ext/tests/save_load_resolution.rs index 556161514f..acf461e9fe 100644 --- a/ext/tests/save_load_resolution.rs +++ b/ext/tests/save_load_resolution.rs @@ -20,9 +20,11 @@ fn set_readonly(p: &Path, readonly: bool) { fn lock_tempdir(dir: &Path) { let mut dir: PathBuf = dir.into(); - for kind in SaveKind::resolution_data() { + for kind in SaveKind::resolution_data().chain(SaveKind::nassau_data()) { dir.push(format!("{}s", kind.name())); - set_readonly(&dir, true); + if dir.exists() { + set_readonly(&dir, true); + } dir.pop(); } set_readonly(&dir, true); @@ -33,9 +35,11 @@ fn unlock_tempdir(dir: &Path) { set_readonly(dir, false); let mut dir: PathBuf = dir.into(); - for kind in SaveKind::resolution_data() { + for kind in SaveKind::resolution_data().chain(SaveKind::nassau_data()) { dir.push(format!("{}s", kind.name())); - set_readonly(&dir, false); + if dir.exists() { + set_readonly(&dir, false); + } dir.pop(); } } @@ -100,15 +104,17 @@ fn test_save_load() { } #[test] -#[should_panic(expected = "Invalid header: algebra was 0x20000 but expected 0x28000")] +#[should_panic(expected = "Invalid header: algebra was 0x30000 but expected 0x38000")] fn wrong_algebra() { let tempdir = tempfile::TempDir::new().unwrap(); + + // We use p = 3 to disable Nassau's algorithm let resolution1 = - construct_standard::("S_2@adem", Some(tempdir.path().into())).unwrap(); + construct_standard::("S_3@adem", Some(tempdir.path().into())).unwrap(); resolution1.compute_through_bidegree(Bidegree::s_t(2, 2)); let resolution2 = - construct_standard::("S_2@milnor", Some(tempdir.path().into())).unwrap(); + construct_standard::("S_3@milnor", Some(tempdir.path().into())).unwrap(); resolution2.compute_through_bidegree(Bidegree::s_t(2, 2)); } @@ -289,7 +295,7 @@ fn test_checksum() { .compute_through_bidegree(Bidegree::s_t(2, 2)); let mut path = tempdir.path().to_owned(); - path.push("differentials/2_2_differential"); + path.push("nassau_differentials/2_2_nassau_differential"); let mut file = OpenOptions::new() .read(true)