diff --git a/benches/entry.rs b/benches/entry.rs index aa5551f3d90..2e4a0109705 100644 --- a/benches/entry.rs +++ b/benches/entry.rs @@ -3,15 +3,25 @@ use criterion::criterion_main; mod group; mod perm; -use group::bruteforce_elements::bruteforce; -use group::orbit; -use group::orbit::{ - factored_transversal::factored_transversal_impl, orbit_impl, transversal::transversal_impl, +use group::{ + bruteforce_elements::bruteforce, + orbit::{ + self, + factored_transversal::factored_transversal_impl, + orbit_impl, + transversal::transversal_impl, + }, }; -use group::stabilizer_chain::{selector::selector, stabchain}; +use group::stabilizer_chain::{ + selector::selector, + stabchain, +}; -use perm::{comparison::cmp, permutation}; +use perm::{ + comparison::cmp, + permutation, +}; criterion_main!( permutation, diff --git a/benches/group/bruteforce_elements.rs b/benches/group/bruteforce_elements.rs index 15986aed0b0..1446ef38a5b 100644 --- a/benches/group/bruteforce_elements.rs +++ b/benches/group/bruteforce_elements.rs @@ -1,4 +1,8 @@ -use criterion::{criterion_group, BenchmarkId, Criterion}; +use criterion::{ + criterion_group, + BenchmarkId, + Criterion, +}; const RANGE_OF_VALUES: [usize; 4] = [8, 16, 32, 64]; #[allow(deprecated)] use stabchain::group::brute_force::group_elements; @@ -36,8 +40,4 @@ fn brute_force_vs_orbit_cyclic(c: &mut Criterion) { group.finish(); } -criterion_group!( - bruteforce, - brute_force_vs_orbit_cyclic, - brute_force_vs_orbit_symmetric -); +criterion_group!(bruteforce, brute_force_vs_orbit_cyclic, brute_force_vs_orbit_symmetric); diff --git a/benches/group/mod.rs b/benches/group/mod.rs index 75111776733..cd7a5ba3572 100644 --- a/benches/group/mod.rs +++ b/benches/group/mod.rs @@ -2,10 +2,16 @@ pub mod bruteforce_elements; pub mod orbit; pub mod stabilizer_chain; -use criterion::{criterion_group, BenchmarkId, Criterion}; +use criterion::{ + criterion_group, + BenchmarkId, + Criterion, +}; const RANGE_OF_VALUES: [usize; 4] = [8, 16, 32, 64]; -use stabchain::group::orbit::transversal::Transversal; -use stabchain::group::Group; +use stabchain::group::{ + orbit::transversal::Transversal, + Group, +}; // Comparing different methods of obtaining an orbit --------------------------- diff --git a/benches/group/orbit/factored_transversal.rs b/benches/group/orbit/factored_transversal.rs index 1a1024a68e6..102f8609078 100644 --- a/benches/group/orbit/factored_transversal.rs +++ b/benches/group/orbit/factored_transversal.rs @@ -1,18 +1,26 @@ -use criterion::{criterion_group, BenchmarkId, Criterion}; +use criterion::{ + criterion_group, + BenchmarkId, + Criterion, +}; const RANGE_OF_VALUES: [usize; 4] = [8, 16, 32, 64]; -use stabchain::group::orbit::transversal::factored_transversal::{ - factored_transversal, factored_transversal_complete_opt, +use stabchain::{ + group::{ + orbit::transversal::factored_transversal::{ + factored_transversal, + factored_transversal_complete_opt, + }, + Group, + }, + perm::actions::SimpleApplication, }; -use stabchain::group::Group; -use stabchain::perm::actions::SimpleApplication; // Comparing orbit optimizations fn transversal_vs_optmized_transversal_complete(c: &mut Criterion) { - let mut group = - c.benchmark_group("group__orbit__f_transversal_vs_optmized_f_transversal_complete"); + let mut group = c.benchmark_group("group__orbit__f_transversal_vs_optmized_f_transversal_complete"); for i in RANGE_OF_VALUES.iter() { group.bench_with_input(BenchmarkId::new("transversal", i), i, |b, i| { let g = Group::symmetric(*i); @@ -27,9 +35,7 @@ fn transversal_vs_optmized_transversal_complete(c: &mut Criterion) { } fn transversal_vs_optmized_transversal_complete_many_generators(c: &mut Criterion) { - let mut group = c.benchmark_group( - "group__orbit__f_transversal_vs_optmized_f_transversal_complete_many_gens", - ); + let mut group = c.benchmark_group("group__orbit__f_transversal_vs_optmized_f_transversal_complete_many_gens"); for i in RANGE_OF_VALUES.iter() { group.bench_with_input(BenchmarkId::new("transversal", i), i, |b, i| { let g = Group::alternating(*i); @@ -46,8 +52,7 @@ fn transversal_vs_optmized_transversal_complete_many_generators(c: &mut Criterio fn transversal_vs_optmized_transversal_uncomplete(c: &mut Criterion) { use stabchain::group::utils::copies_of_cyclic; - let mut group = - c.benchmark_group("group__orbit__f_transversal_vs_optmized_f_transversal_uncomplete"); + let mut group = c.benchmark_group("group__orbit__f_transversal_vs_optmized_f_transversal_uncomplete"); for i in RANGE_OF_VALUES.iter() { group.bench_with_input(BenchmarkId::new("transversal", i), i, |b, i| { let g = copies_of_cyclic(&[*i, 20, 20]); diff --git a/benches/group/orbit/mod.rs b/benches/group/orbit/mod.rs index 352e16eb33c..39d955d35a8 100644 --- a/benches/group/orbit/mod.rs +++ b/benches/group/orbit/mod.rs @@ -1,13 +1,24 @@ pub mod factored_transversal; pub mod transversal; -use criterion::{criterion_group, BenchmarkId, Criterion}; +use criterion::{ + criterion_group, + BenchmarkId, + Criterion, +}; const RANGE_OF_VALUES: [usize; 4] = [8, 16, 32, 64]; -use stabchain::group::orbit::{orbit, orbit_complete_opt}; -use stabchain::group::Group; -use stabchain::perm::actions::SimpleApplication; +use stabchain::{ + group::{ + orbit::{ + orbit, + orbit_complete_opt, + }, + Group, + }, + perm::actions::SimpleApplication, +}; // Comparing orbit optimizations diff --git a/benches/group/orbit/transversal.rs b/benches/group/orbit/transversal.rs index 1e9e9274ffa..b145b442e39 100644 --- a/benches/group/orbit/transversal.rs +++ b/benches/group/orbit/transversal.rs @@ -1,12 +1,21 @@ -use criterion::{criterion_group, BenchmarkId, Criterion}; +use criterion::{ + criterion_group, + BenchmarkId, + Criterion, +}; const RANGE_OF_VALUES: [usize; 4] = [8, 16, 32, 64]; -use stabchain::group::orbit::transversal::simple_transversal::{ - transversal, transversal_complete_opt, +use stabchain::{ + group::{ + orbit::transversal::simple_transversal::{ + transversal, + transversal_complete_opt, + }, + Group, + }, + perm::actions::SimpleApplication, }; -use stabchain::group::Group; -use stabchain::perm::actions::SimpleApplication; // Comparing orbit optimizations @@ -26,8 +35,7 @@ fn transversal_vs_optmized_transversal_complete(c: &mut Criterion) { } fn transversal_vs_optmized_transversal_complete_many_generators(c: &mut Criterion) { - let mut group = - c.benchmark_group("group__orbit__transversal_vs_optmized_transversal_complete_many_gens"); + let mut group = c.benchmark_group("group__orbit__transversal_vs_optmized_transversal_complete_many_gens"); for i in RANGE_OF_VALUES.iter() { group.bench_with_input(BenchmarkId::new("transversal", i), i, |b, i| { let g = Group::alternating(*i); @@ -44,8 +52,7 @@ fn transversal_vs_optmized_transversal_complete_many_generators(c: &mut Criterio fn transversal_vs_optmized_transversal_uncomplete(c: &mut Criterion) { use stabchain::group::utils::copies_of_cyclic; - let mut group = - c.benchmark_group("group__orbit__transversal_vs_optmized_transversal_uncomplete"); + let mut group = c.benchmark_group("group__orbit__transversal_vs_optmized_transversal_uncomplete"); for i in RANGE_OF_VALUES.iter() { group.bench_with_input(BenchmarkId::new("transversal", i), i, |b, i| { let g = copies_of_cyclic(&[*i, 20, 20]); diff --git a/benches/group/stabilizer_chain/mod.rs b/benches/group/stabilizer_chain/mod.rs index 13f80e0fc1d..6e5cda45288 100644 --- a/benches/group/stabilizer_chain/mod.rs +++ b/benches/group/stabilizer_chain/mod.rs @@ -1,13 +1,30 @@ pub mod selector; -use criterion::{criterion_group, BenchmarkId, Criterion}; +use criterion::{ + criterion_group, + BenchmarkId, + Criterion, +}; const RANGE_OF_VALUES: [usize; 5] = [8, 10, 16, 20, 32]; -use rand::{Rng, SeedableRng}; -use stabchain::group::stabchain::base::selectors::DefaultSelector; -use stabchain::group::stabchain::builder::random::parameters::RandomAlgoParameters; -use stabchain::group::stabchain::builder::*; -use stabchain::group::Group; -use stabchain::perm::actions::SimpleApplication; +use { + rand::{ + Rng, + SeedableRng, + }, + stabchain::{ + group::{ + stabchain::{ + base::selectors::DefaultSelector, + builder::{ + random::parameters::RandomAlgoParameters, + *, + }, + }, + Group, + }, + perm::actions::SimpleApplication, + }, +}; use num::BigUint; @@ -47,18 +64,13 @@ fn stabchain_cyclic(c: &mut Criterion) { bench_stabchain_impl!(group, "ift", i, (|i: &usize| Group::cyclic(*i)), || { IftBuilderStrategy::new(SimpleApplication::default(), DefaultSelector::default()) }); - bench_stabchain_impl!( - group, - "random_shallow", - i, - (|i: &usize| Group::cyclic(*i)), - || RandomBuilderStrategyShallow::new_with_params( + bench_stabchain_impl!(group, "random_shallow", i, (|i: &usize| Group::cyclic(*i)), || { + RandomBuilderStrategyShallow::new_with_params( SimpleApplication::default(), DefaultSelector::default(), - RandomAlgoParameters::default() - .rng(rand_xorshift::XorShiftRng::from_seed(rng.gen())) + RandomAlgoParameters::default().rng(rand_xorshift::XorShiftRng::from_seed(rng.gen())), ) - ); + }); bench_stabchain_impl_with_order!( group, "random_shallow_known_order", @@ -112,28 +124,19 @@ fn stabchain_symmetric(c: &mut Criterion) { let g = Group::symmetric(*i); b.iter(|| g.stabchain()) }); - bench_stabchain_impl!( - group, - "naive", - i, - (|i: &usize| Group::symmetric(*i)), - || NaiveBuilderStrategy::new(SimpleApplication::default(), DefaultSelector::default()) - ); + bench_stabchain_impl!(group, "naive", i, (|i: &usize| Group::symmetric(*i)), || { + NaiveBuilderStrategy::new(SimpleApplication::default(), DefaultSelector::default()) + }); bench_stabchain_impl!(group, "ift", i, (|i: &usize| Group::symmetric(*i)), || { IftBuilderStrategy::new(SimpleApplication::default(), DefaultSelector::default()) }); - bench_stabchain_impl!( - group, - "random_shallow", - i, - (|i: &usize| Group::symmetric(*i)), - || RandomBuilderStrategyShallow::new_with_params( + bench_stabchain_impl!(group, "random_shallow", i, (|i: &usize| Group::symmetric(*i)), || { + RandomBuilderStrategyShallow::new_with_params( SimpleApplication::default(), DefaultSelector::default(), - RandomAlgoParameters::default() - .rng(rand_xorshift::XorShiftRng::from_seed(rng.gen())), + RandomAlgoParameters::default().rng(rand_xorshift::XorShiftRng::from_seed(rng.gen())), ) - ); + }); bench_stabchain_impl!( group, "random_shallow_quick_test", @@ -210,8 +213,7 @@ fn stabchain_direct_product_symm(c: &mut Criterion) { || RandomBuilderStrategyShallow::new_with_params( SimpleApplication::default(), DefaultSelector::default(), - RandomAlgoParameters::default() - .rng(rand_xorshift::XorShiftRng::from_seed(rng.gen())), + RandomAlgoParameters::default().rng(rand_xorshift::XorShiftRng::from_seed(rng.gen())), ) ); bench_stabchain_impl!( @@ -291,8 +293,7 @@ fn stabchain_copies_of_cyclic(c: &mut Criterion) { || RandomBuilderStrategyShallow::new_with_params( SimpleApplication::default(), DefaultSelector::default(), - RandomAlgoParameters::default() - .rng(rand_xorshift::XorShiftRng::from_seed(rng.gen())), + RandomAlgoParameters::default().rng(rand_xorshift::XorShiftRng::from_seed(rng.gen())), ) ); bench_stabchain_impl!( diff --git a/benches/group/stabilizer_chain/selector.rs b/benches/group/stabilizer_chain/selector.rs index bfa903889e1..5967cde20b9 100644 --- a/benches/group/stabilizer_chain/selector.rs +++ b/benches/group/stabilizer_chain/selector.rs @@ -1,8 +1,19 @@ -use criterion::{criterion_group, BenchmarkId, Criterion}; +use criterion::{ + criterion_group, + BenchmarkId, + Criterion, +}; const RANGE_OF_VALUES: [usize; 5] = [8, 10, 16, 20, 32]; -use stabchain::group::stabchain::base::selectors::{FixedBaseSelector, LmpSelector}; -use stabchain::group::Group; -use std::iter::FromIterator; +use { + stabchain::group::{ + stabchain::base::selectors::{ + FixedBaseSelector, + LmpSelector, + }, + Group, + }, + std::iter::FromIterator, +}; fn selector_comparison_cyclic(c: &mut Criterion) { let mut group = c.benchmark_group("group__stabchain__ss__selector_comparison__cyclic"); @@ -45,8 +56,7 @@ fn selector_comparison_symmetric(c: &mut Criterion) { } fn selector_comparison_direct_product(c: &mut Criterion) { - let mut group = - c.benchmark_group("group__stabchain__ss__selector_comparison__product_symmetric"); + let mut group = c.benchmark_group("group__stabchain__ss__selector_comparison__product_symmetric"); for i in RANGE_OF_VALUES.iter() { group.bench_with_input(BenchmarkId::new("default", i), i, |b, i| { let g = Group::product(&Group::symmetric(*i), &Group::symmetric(*i)); diff --git a/benches/perm/comparison.rs b/benches/perm/comparison.rs index d48cb02098b..305e2665c9d 100644 --- a/benches/perm/comparison.rs +++ b/benches/perm/comparison.rs @@ -1,11 +1,20 @@ -use criterion::{criterion_group, BenchmarkId, Criterion}; -use stabchain::perm::utils::random_permutation; +use { + criterion::{ + criterion_group, + BenchmarkId, + Criterion, + }, + stabchain::perm::utils::random_permutation, +}; use stabchain::perm::Permutation; use stabchain::perm::impls::{ - based::BasedPermutation, map::MapPermutation, standard::StandardPermutation, - sync::SyncPermutation, word::WordPermutation, + based::BasedPermutation, + map::MapPermutation, + standard::StandardPermutation, + sync::SyncPermutation, + word::WordPermutation, }; const RANGE_OF_VALUES: [usize; 7] = [8, 16, 32, 64, 128, 256, 512]; diff --git a/benches/perm/mod.rs b/benches/perm/mod.rs index 7cdf6b978f5..4708d0ba597 100644 --- a/benches/perm/mod.rs +++ b/benches/perm/mod.rs @@ -1,13 +1,20 @@ pub mod comparison; -use criterion::{black_box, criterion_group, BenchmarkId, Criterion}; +use criterion::{ + black_box, + criterion_group, + BenchmarkId, + Criterion, +}; use std::iter::FromIterator; -use stabchain::perm::builder::PermBuilder; -use stabchain::perm::impls::standard::StandardPermutation; -use stabchain::perm::utils::random_permutation; -use stabchain::perm::*; +use stabchain::perm::{ + builder::PermBuilder, + impls::standard::StandardPermutation, + utils::random_permutation, + *, +}; const RANGE_OF_VALUES: [usize; 7] = [8, 16, 32, 64, 128, 256, 512]; @@ -59,7 +66,7 @@ fn exponentiation(c: &mut Criterion) { group.bench_with_input(BenchmarkId::new("multijoin", i), &i, |b, i| { use stabchain::perm::builder::join::MultiJoin; let perm = random_permutation::(*i); - let join = MultiJoin::from_iter(std::iter::repeat(perm).take(i / 2)); + let join = MultiJoin::from_iter(std::iter::repeat_n(perm, i / 2)); b.iter(|| join.collapse()) }); } @@ -76,7 +83,7 @@ fn exponentiation_small_exponent(c: &mut Criterion) { group.bench_with_input(BenchmarkId::new("multijoin", i), &i, |b, i| { use stabchain::perm::builder::join::MultiJoin; let perm = random_permutation::(1024); - let join = MultiJoin::from_iter(std::iter::repeat(perm).take(*i)); + let join = MultiJoin::from_iter(std::iter::repeat_n(perm, *i)); b.iter(|| join.collapse()) }); } @@ -101,11 +108,13 @@ fn order_efficiency(c: &mut Criterion) { b.iter(|| order_cycle(&perm)) }); group.bench_with_input(BenchmarkId::new("parallel", i), i, |b, i| { - use rayon::prelude::*; - use stabchain::perm::impls::sync::SyncPermutation; + use { + rayon::prelude::*, + stabchain::perm::impls::sync::SyncPermutation, + }; let perm = random_permutation::(*i); b.iter(|| match perm.lmp() { - Some(n) => (0..n as usize) + Some(n) => (0..n) .into_par_iter() .map(|i| (i, perm.pow(i as isize))) .filter(|t| t.1.is_id()) diff --git a/examples/benchmark.rs b/examples/benchmark.rs index 8eaa359f300..37885c1110a 100644 --- a/examples/benchmark.rs +++ b/examples/benchmark.rs @@ -1,14 +1,26 @@ -use std::fs::File; -use std::io::BufReader; -use std::str::FromStr; -use structopt::StructOpt; - -use stabchain::group::group_library::DecoratedGroup; -use stabchain::group::stabchain::base::selectors::LmpSelector; -use stabchain::group::stabchain::builder::*; -use stabchain::perm::actions::SimpleApplication; -use stabchain::perm::export::ExportablePermutation; -use stabchain::perm::*; +use { + std::{ + fs::File, + io::BufReader, + str::FromStr, + }, + structopt::StructOpt, +}; + +use stabchain::{ + group::{ + group_library::DecoratedGroup, + stabchain::{ + base::selectors::LmpSelector, + builder::*, + }, + }, + perm::{ + actions::SimpleApplication, + export::ExportablePermutation, + *, + }, +}; use std::time::Instant; @@ -29,25 +41,24 @@ impl FromStr for BenchMode { fn from_str(s: &str) -> Result { Ok(match s { - "deterministic" => BenchMode::Deterministic, - "ift" => BenchMode::DeterministicIFT, - "random" => BenchMode::Random, - "shallow" => BenchMode::RandomShallow, + "deterministic" => Self::Deterministic, + "ift" => Self::DeterministicIFT, + "random" => Self::Random, + "shallow" => Self::RandomShallow, _ => return Err("Could not parse".to_string()), }) } } fn load_libraries(paths: &[&str]) -> Vec> { - paths.iter().map(|p| group_library(p)).flatten().collect() + paths.iter().flat_map(|p| group_library(p)).collect() } fn group_library(path: &str) -> impl IntoIterator> { let input = File::open(path).unwrap(); let input = BufReader::new(input); - let groups: Vec> = - serde_json::from_reader(input).unwrap(); + let groups: Vec> = serde_json::from_reader(input).unwrap(); groups.into_iter().map(|g| g.map(DefaultPermutation::from)) } @@ -99,19 +110,19 @@ fn main() { match args.mode { BenchMode::Deterministic => bench( group_library, - DefaultStrategy::new(SimpleApplication::default(), LmpSelector::default()), + DefaultStrategy::new(SimpleApplication::default(), LmpSelector), ), BenchMode::DeterministicIFT => bench( group_library, - IftBuilderStrategy::new(SimpleApplication::default(), LmpSelector::default()), + IftBuilderStrategy::new(SimpleApplication::default(), LmpSelector), ), BenchMode::Random => bench( group_library, - RandomBuilderStrategyNaive::new(SimpleApplication::default(), LmpSelector::default()), + RandomBuilderStrategyNaive::new(SimpleApplication::default(), LmpSelector), ), BenchMode::RandomShallow => bench( group_library, - RandomBuilderStrategyShallow::new(SimpleApplication::default(), LmpSelector::default()), + RandomBuilderStrategyShallow::new(SimpleApplication::default(), LmpSelector), ), } } diff --git a/examples/group_import.rs b/examples/group_import.rs index c478ae0a0c4..05f6725c6b1 100644 --- a/examples/group_import.rs +++ b/examples/group_import.rs @@ -1,15 +1,32 @@ -use std::fs::{metadata, File}; -use std::io::{BufReader, BufWriter}; -use std::path::PathBuf; +use std::{ + fs::{ + metadata, + File, + }, + io::{ + BufReader, + BufWriter, + }, + path::PathBuf, +}; -use num::BigUint; -use serde::Deserialize; -use structopt::StructOpt; -use walkdir::WalkDir; +use { + num::BigUint, + serde::Deserialize, + structopt::StructOpt, + walkdir::WalkDir, +}; -use stabchain::group::group_library::DecoratedGroup; -use stabchain::group::Group; -use stabchain::perm::export::{ClassicalPermutation, ExportablePermutation}; +use stabchain::{ + group::{ + group_library::DecoratedGroup, + Group, + }, + perm::export::{ + ClassicalPermutation, + ExportablePermutation, + }, +}; #[derive(Deserialize)] struct GAPGroup { diff --git a/examples/permutation_converter.rs b/examples/permutation_converter.rs index 83d51b02a13..f6e37e296e6 100644 --- a/examples/permutation_converter.rs +++ b/examples/permutation_converter.rs @@ -1,15 +1,18 @@ -use stabchain::perm::{DefaultPermutation, Permutation}; -use std::io; -use std::io::prelude::*; +use { + stabchain::perm::{ + DefaultPermutation, + Permutation, + }, + std::{ + io, + io::prelude::*, + }, +}; fn main() { for line in io::stdin().lock().lines() { let arg = line.expect("Invalid line read"); - let images: Vec<_> = arg - .trim() - .split(' ') - .map(|s| s.parse::().unwrap()) - .collect(); + let images: Vec<_> = arg.trim().split(' ').map(|s| s.parse::().unwrap()).collect(); let perm = DefaultPermutation::from_images(&images[..]); println!("{}", perm); diff --git a/rustfmt.toml b/rustfmt.toml new file mode 100644 index 00000000000..9cd24c6c2c6 --- /dev/null +++ b/rustfmt.toml @@ -0,0 +1,4 @@ +max_width = 120 +reorder_modules = true +imports_layout = "Vertical" +imports_granularity = "One" diff --git a/src/group/brute_force.rs b/src/group/brute_force.rs index 1b73b08cd35..dc73d6dea26 100644 --- a/src/group/brute_force.rs +++ b/src/group/brute_force.rs @@ -1,8 +1,12 @@ //! Mod which contains a deprecated utility for bruteforcing group elements -use super::Group; -use crate::perm::Permutation; -use crate::DetHashSet; +use { + super::Group, + crate::{ + perm::Permutation, + DetHashSet, + }, +}; use std::collections::VecDeque; @@ -16,10 +20,9 @@ pub fn group_elements(g: &Group

) -> Vec

{ let gens = g.generators(); let mut res = DetHashSet::with_capacity_and_hasher(gens.len(), Default::default()); // Get everything that is not the identity - let mut to_check: VecDeque<_> = gens.iter().cloned().filter(|p| !p.is_id()).collect(); - while !to_check.is_empty() { + let mut to_check: VecDeque<_> = gens.iter().filter(|&p| !p.is_id()).cloned().collect(); + while let Some(element) = to_check.pop_back() { // Add it to the group (as well as its inverse) - let element = to_check.pop_back().unwrap(); res.insert(element.inv()); res.insert(element.clone()); let element = element.clone(); diff --git a/src/group/group_library.rs b/src/group/group_library.rs index 4830fdb3718..e54ae2fbe26 100644 --- a/src/group/group_library.rs +++ b/src/group/group_library.rs @@ -1,8 +1,18 @@ -use num::BigUint; -use serde::{Deserialize, Serialize}; +use { + num::BigUint, + serde::{ + Deserialize, + Serialize, + }, +}; -use super::Group; -use crate::perm::{DefaultPermutation, Permutation}; +use { + super::Group, + crate::perm::{ + DefaultPermutation, + Permutation, + }, +}; /// A simple struct that keeps track of additional information of a group, such /// as the order. This is very useful for testing stabilizer chains @@ -46,6 +56,6 @@ where { fn from(g: Group

) -> Self { let order = g.stabchain().order(); - DecoratedGroup::new(g, order) + Self::new(g, order) } } diff --git a/src/group/mod.rs b/src/group/mod.rs index fe73e73cdf0..0cce621e775 100644 --- a/src/group/mod.rs +++ b/src/group/mod.rs @@ -7,19 +7,37 @@ pub mod random_perm; pub mod stabchain; pub mod utils; -use self::stabchain::base::selectors::adaptors::PartialFixedBaseSelector; -use self::stabchain::base::selectors::DefaultSelector; -use self::stabchain::base::selectors::FixedBaseSelector; -use self::stabchain::builder::DefaultStrategy; -use crate::group::orbit::abstraction::TransversalResolver; -use crate::group::stabchain::base::selectors::BaseSelector; -use crate::group::stabchain::builder::BuilderStrategy; -use crate::perm::actions::SimpleApplication; -use crate::perm::export::CyclePermutation; -use crate::perm::utils::order_n_permutation; -use crate::perm::*; - -use serde::{Deserialize, Serialize}; +use { + self::stabchain::{ + base::selectors::{ + adaptors::PartialFixedBaseSelector, + DefaultSelector, + FixedBaseSelector, + }, + builder::DefaultStrategy, + Stabchain, + }, + crate::{ + group::{ + orbit::abstraction::TransversalResolver, + stabchain::{ + base::selectors::BaseSelector, + builder::BuilderStrategy, + }, + }, + perm::{ + actions::SimpleApplication, + export::CyclePermutation, + utils::order_n_permutation, + *, + }, + }, +}; + +use serde::{ + Deserialize, + Serialize, +}; use std::iter::FromIterator; @@ -32,12 +50,12 @@ pub struct Group

{ impl Group { /// Generates the trivial group, which only contains the identity pub fn trivial() -> Self { - Group::new(&[]) + Self::new(&[]) } /// Creates the Klein 4 group pub fn klein_4() -> Self { - Group::new(&[ + Self::new(&[ CyclePermutation::single_cycle(&[1, 2]).into_perm(), CyclePermutation::single_cycle(&[3, 4]).into_perm(), ]) @@ -48,10 +66,10 @@ impl Group { //https://math.stackexchange.com/questions/3614294/choice-of-generator-in-dihedral-group assert!(n > 0); if n == 1 { - return Group::cyclic(2); + return Self::cyclic(2); } if n == 2 { - return Group::klein_4(); + return Self::klein_4(); } let reflection_perm = if n % 2 == 0 { @@ -65,14 +83,14 @@ impl Group { } .into_perm(); - Group::new(&[reflection_perm, order_n_permutation(1, n)]) + Self::new(&[reflection_perm, order_n_permutation(1, n)]) } /// Generate the cyclical group on n elements (more accurately, generates the cyclical group from a cycle on 1..=n) pub fn cyclic(n: usize) -> Self { assert!(n > 0); - Group::new(&[order_n_permutation(1, n)]) + Self::new(&[order_n_permutation(1, n)]) } /// Generate the alternating group on n points @@ -96,7 +114,7 @@ impl Group { return Self::trivial(); } - Group::new(&[ + Self::new(&[ CyclePermutation::single_cycle(&[1, 2]).into_perm(), order_n_permutation(1, n), ]) @@ -105,8 +123,8 @@ impl Group { impl

Group

{ /// To be used when the element is not a permutation. Note this does not check id - pub fn from_list>(iter: T) -> Group

{ - Group { + pub fn from_list>(iter: T) -> Self { + Self { generators: iter.into_iter().collect(), } } @@ -140,7 +158,7 @@ where pub fn deduplicate(&self) -> Self { use crate::DetHashSet; let set: DetHashSet<_> = self.generators.iter().cloned().collect(); - Group::from_list(set.into_iter()) + Self::from_list(set) } /// Create a random generator for elements of the group @@ -172,19 +190,12 @@ where /// Computes the transversal from the group generators (use factored transversal instead for memory efficience) #[tracing::instrument] - pub fn transversal( - &self, - base: usize, - ) -> impl orbit::transversal::Transversal> { + pub fn transversal(&self, base: usize) -> impl orbit::transversal::Transversal> { orbit::transversal::SimpleTransversal::new(self, base) } /// Compute the transversal w.r.t. to a given action - pub fn transversal_of_action( - &self, - base: A::OrbitT, - strat: A, - ) -> impl orbit::transversal::Transversal + pub fn transversal_of_action(&self, base: A::OrbitT, strat: A) -> impl orbit::transversal::Transversal where A: Action

, { @@ -193,10 +204,7 @@ where /// Computes the factored transversal from the group generators #[tracing::instrument] - pub fn factored_transversal( - &self, - base: usize, - ) -> impl orbit::transversal::Transversal> { + pub fn factored_transversal(&self, base: usize) -> impl orbit::transversal::Transversal> { orbit::transversal::FactoredTransversal::new(self, base) } @@ -214,8 +222,8 @@ where /// Computes a stabilizer chain for this group #[tracing::instrument] - pub fn stabchain(&self) -> stabchain::Stabchain> { - stabchain::Stabchain::new_with_strategy( + pub fn stabchain(&self) -> Stabchain> { + Stabchain::new_with_strategy( self, DefaultStrategy::new(SimpleApplication::default(), DefaultSelector::default()), ) @@ -223,21 +231,15 @@ where /// Computes a stabilizer chain for this group with a base #[tracing::instrument] - pub fn stabchain_base( - &self, - base: &[usize], - ) -> stabchain::Stabchain> { - stabchain::Stabchain::new_with_strategy( + pub fn stabchain_base(&self, base: &[usize]) -> Stabchain> { + Stabchain::new_with_strategy( self, DefaultStrategy::new(SimpleApplication::default(), FixedBaseSelector::new(base)), ) } /// Computes a stabilizer chain for this group with a partial base, using the default strategy for further points. - pub fn stabchain_partial_base( - &self, - partial_base: &[usize], - ) -> stabchain::Stabchain> { - stabchain::Stabchain::new_with_strategy( + pub fn stabchain_partial_base(&self, partial_base: &[usize]) -> Stabchain> { + Stabchain::new_with_strategy( self, DefaultStrategy::new( SimpleApplication::default(), @@ -247,22 +249,13 @@ where } /// Computes a stabilizer chain for this group with a strategy - pub fn stabchain_with_strategy>( - &self, - strat: S, - ) -> stabchain::Stabchain { - stabchain::Stabchain::new_with_strategy(self, strat) + pub fn stabchain_with_strategy>(&self, strat: S) -> Stabchain { + Stabchain::new_with_strategy(self, strat) } /// Computes a stabilizer chain for this group with a chosen selector - pub fn stabchain_with_selector( - &self, - selector: impl BaseSelector

, - ) -> stabchain::Stabchain> { - stabchain::Stabchain::new_with_strategy( - self, - DefaultStrategy::new(SimpleApplication::default(), selector), - ) + pub fn stabchain_with_selector(&self, selector: impl BaseSelector

) -> Stabchain> { + Stabchain::new_with_strategy(self, DefaultStrategy::new(SimpleApplication::default(), selector)) } /// Check G.subgroup_of(H) <=> G <= H @@ -276,13 +269,10 @@ where /// Unless time is a very cheap commodity, do not do on large groups #[tracing::instrument] pub fn bruteforce_elements(&self) -> Vec

{ - self.orbit_of_action( - P::id(), - &crate::perm::actions::MultiplicationAction::default(), - ) - .iter() - .cloned() - .collect() + self.orbit_of_action(P::id(), &crate::perm::actions::MultiplicationAction::default()) + .iter() + .cloned() + .collect() } /// Regenerate the groups using a new set of generators @@ -320,12 +310,7 @@ where /// Computes the smallest n s.t. G <= S_n pub fn symmetric_super_order(&self) -> usize { - self.generators - .iter() - .flat_map(|g| g.lmp()) - .max() - .unwrap_or(0) - + 1 + self.generators.iter().flat_map(|g| g.lmp()).max().unwrap_or(0) + 1 } /// Conjugate the generators by this permutation @@ -362,9 +347,9 @@ impl

FromIterator

for Group

where P: Permutation, { - fn from_iter>(iter: T) -> Group

{ + fn from_iter>(iter: T) -> Self { let v = iter.into_iter().filter(|p| !p.is_id()).collect(); - Group { generators: v } + Self { generators: v } } } @@ -442,9 +427,13 @@ mod tests { #[test] fn test_product() { - use crate::perm::export::CyclePermutation; - use crate::perm::DefaultPermutation; - use crate::DetHashSet; + use crate::{ + perm::{ + export::CyclePermutation, + DefaultPermutation, + }, + DetHashSet, + }; let perm: DefaultPermutation = CyclePermutation::single_cycle(&[1, 2, 3]).into(); @@ -483,7 +472,7 @@ mod tests { let reg = g.random_n_generators(30); // We subtract the identity - assert!(reg.generators().len() <= 24 - 1); + assert!(reg.generators().len() < 24); } #[test] diff --git a/src/group/orbit/abstraction.rs b/src/group/orbit/abstraction.rs index 0eb6c07adac..86f4f28383a 100644 --- a/src/group/orbit/abstraction.rs +++ b/src/group/orbit/abstraction.rs @@ -1,10 +1,15 @@ //! Some useful abstractions to abstract over the two different kind of transversals. //! In particular useful for stabchain as it allows to build factored transversal quite transparently -use crate::perm::actions::SimpleApplication; -use crate::perm::impls::word::WordPermutation; -use crate::perm::{Action, Permutation}; -use crate::DetHashMap; +use crate::{ + perm::{ + actions::SimpleApplication, + impls::word::WordPermutation, + Action, + Permutation, + }, + DetHashMap, +}; use std::fmt::Debug; @@ -17,12 +22,7 @@ where type AssociatedTransversal: super::transversal::Transversal; /// Compute the representative - fn representative( - &self, - map: &DetHashMap, - base: A::OrbitT, - point: A::OrbitT, - ) -> Option

; + fn representative(&self, map: &DetHashMap, base: A::OrbitT, point: A::OrbitT) -> Option

; /// Compute representative as word fn representative_as_word( @@ -39,11 +39,7 @@ where } /// Convert into a full blown transversal - fn to_transversal( - &self, - map: DetHashMap, - base: A::OrbitT, - ) -> Self::AssociatedTransversal; + fn to_transversal(&self, map: DetHashMap, base: A::OrbitT) -> Self::AssociatedTransversal; } /// A dispatcher which does simple lookups @@ -57,21 +53,12 @@ where { type AssociatedTransversal = super::transversal::SimpleTransversal; - fn representative( - &self, - map: &DetHashMap, - _: A::OrbitT, - point: A::OrbitT, - ) -> Option

{ + fn representative(&self, map: &DetHashMap, _: A::OrbitT, point: A::OrbitT) -> Option

{ map.get(&point).cloned() } - fn to_transversal( - &self, - map: DetHashMap, - base: A::OrbitT, - ) -> Self::AssociatedTransversal { - super::transversal::SimpleTransversal::from_raw(base, map, SimpleTransversalResolver) + fn to_transversal(&self, map: DetHashMap, base: A::OrbitT) -> Self::AssociatedTransversal { + super::transversal::SimpleTransversal::from_raw(base, map, Self) } } @@ -86,12 +73,7 @@ where { type AssociatedTransversal = super::transversal::FactoredTransversal; - fn representative( - &self, - map: &DetHashMap, - base: A::OrbitT, - point: A::OrbitT, - ) -> Option

{ + fn representative(&self, map: &DetHashMap, base: A::OrbitT, point: A::OrbitT) -> Option

{ super::transversal::factored_transversal::representative_raw(map, base, point, &self.0) } @@ -104,25 +86,11 @@ where where P: Permutation, { - super::transversal::shallow_transversal::representative_raw_as_word( - map, - base, - point, - &self.0, - map.len(), - ) + super::transversal::shallow_transversal::representative_raw_as_word(map, base, point, &self.0, map.len()) } // Note that no validation is actually done here - fn to_transversal( - &self, - map: DetHashMap, - base: A::OrbitT, - ) -> Self::AssociatedTransversal { - super::transversal::FactoredTransversal::from_raw( - base, - map, - FactoredTransversalResolver(self.0.clone()), - ) + fn to_transversal(&self, map: DetHashMap, base: A::OrbitT) -> Self::AssociatedTransversal { + super::transversal::FactoredTransversal::from_raw(base, map, Self(self.0.clone())) } } diff --git a/src/group/orbit/mod.rs b/src/group/orbit/mod.rs index 459b1bd2741..739088e94ba 100644 --- a/src/group/orbit/mod.rs +++ b/src/group/orbit/mod.rs @@ -3,12 +3,21 @@ pub mod abstraction; pub mod transversal; -use crate::group::Group; -use crate::perm::actions::SimpleApplication; -use crate::perm::{Action, Permutation}; -use crate::DetHashSet; -use std::collections::VecDeque; -use std::fmt::Debug; +use { + crate::{ + group::Group, + perm::{ + actions::SimpleApplication, + Action, + Permutation, + }, + DetHashSet, + }, + std::{ + collections::VecDeque, + fmt::Debug, + }, +}; /// w^G = { w^g | g \in G } #[derive(Debug)] @@ -53,7 +62,7 @@ where OrbitT: std::hash::Hash + Eq, { pub(crate) fn from_raw(base: OrbitT, orbit: DetHashSet) -> Self { - Orbit { base, orbit } + Self { base, orbit } } /// Is this a complete orbit? @@ -113,8 +122,7 @@ where to_traverse.push_back(w); // Get unused - while !to_traverse.is_empty() { - let delta = to_traverse.pop_front().unwrap(); + while let Some(delta) = to_traverse.pop_front() { for g in gens { // Apply generator and insert let gamma = strat.apply(g, delta.clone()); @@ -148,8 +156,7 @@ where to_traverse.push_back(w); // Get unused - while !to_traverse.is_empty() { - let delta = to_traverse.pop_front().unwrap(); + while let Some(delta) = to_traverse.pop_front() { for g in gens { // Apply generator and insert let gamma = strat.apply(g, delta.clone()); diff --git a/src/group/orbit/transversal/factored_transversal.rs b/src/group/orbit/transversal/factored_transversal.rs index abe72896f46..723a2776452 100644 --- a/src/group/orbit/transversal/factored_transversal.rs +++ b/src/group/orbit/transversal/factored_transversal.rs @@ -1,13 +1,28 @@ //! Transversal using a Schrier Vector approach to save memory over standard -use super::skeleton::TransversalSkeleton; -use crate::group::orbit::transversal::Transversal; -use crate::group::Group; -use crate::perm::actions::SimpleApplication; -use crate::perm::{Action, DefaultPermutation, Permutation}; +use { + super::skeleton::TransversalSkeleton, + crate::{ + group::{ + orbit::transversal::Transversal, + Group, + }, + perm::{ + actions::SimpleApplication, + Action, + DefaultPermutation, + Permutation, + }, + }, +}; -use crate::DetHashMap; -use std::collections::{HashMap, VecDeque}; +use { + crate::DetHashMap, + std::collections::{ + HashMap, + VecDeque, + }, +}; use crate::group::orbit::abstraction::FactoredTransversalResolver; @@ -44,6 +59,18 @@ where debug_assert!(strat.apply(&rep.inv(), base) == point); Some(rep.inv()) } + let mut orbit_point = point.clone(); + let mut rep = P::id(); + // Move along the orbit till we reach a representative that the base moves to the point. + while orbit_point != base { + let g_inv = transversal.get(&orbit_point).unwrap(); + rep = rep.multiply(g_inv); + orbit_point = strat.apply(g_inv, orbit_point); + } + // Invert at the end, as the inverses are used. + // If we want fgh, then we can instead do (h^-1, g^-1, f^-1)^-1. + debug_assert!(strat.apply(&rep.inv(), base) == point); + Some(rep.inv()) } #[deprecated(since = "0.1.1")] @@ -97,7 +124,7 @@ where /// let fc = FactoredTransversal::from_generators(1, &[DefaultPermutation::from_images(&[1, 0])]); ///``` pub fn from_generators(base: usize, gens: &[P]) -> Self { - FactoredTransversal::new(&Group::new(gens), base) + Self::new(&Group::new(gens), base) } } @@ -108,7 +135,7 @@ where { /// Build a factored transversal using a predefined action pub fn new_with_action(g: &Group

, base: A::OrbitT, strat: &A) -> Self { - FactoredTransversal::from_raw( + Self::from_raw( base.clone(), factored_transversal(g, base, strat), FactoredTransversalResolver(strat.clone()), @@ -122,11 +149,7 @@ where P: fmt::Display + Permutation, { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!( - f, - "[FactoredTransversal: base := {}, elements := {{", - self.base() + 1, - )?; + write!(f, "[FactoredTransversal: base := {}, elements := {{", self.base() + 1,)?; for (orbit, repr) in self.raw_elements() { write!(f, "({}, {}) ", orbit + 1, repr)? @@ -137,11 +160,7 @@ where } /// Computes the factored transversal for a Group -pub fn factored_transversal( - g: &Group

, - base: A::OrbitT, - strat: &A, -) -> DetHashMap +pub fn factored_transversal(g: &Group

, base: A::OrbitT, strat: &A) -> DetHashMap where P: Permutation, A: Action

, @@ -154,9 +173,8 @@ where let mut to_traverse = VecDeque::new(); to_traverse.push_back(base); // While there are still elements of the orbit unused. - while !to_traverse.is_empty() { - //Take an unused element. - let delta = to_traverse.pop_front().unwrap(); + //Take an unused element. + while let Some(delta) = to_traverse.pop_front() { for g in gens { let point = strat.apply(g, delta.clone()); @@ -172,11 +190,7 @@ where } /// Computes the factored transversal for a Group. Use optmization on complete orbits -pub fn factored_transversal_complete_opt( - g: &Group

, - base: A::OrbitT, - strat: &A, -) -> DetHashMap +pub fn factored_transversal_complete_opt(g: &Group

, base: A::OrbitT, strat: &A) -> DetHashMap where P: Permutation, A: Action

, @@ -190,9 +204,8 @@ where let mut to_traverse = VecDeque::new(); to_traverse.push_back(base); // While there are still elements of the orbit unused. - while !to_traverse.is_empty() { + while let Some(delta) = to_traverse.pop_front() { //Take an unused element. - let delta = to_traverse.pop_front().unwrap(); for g in gens { let point = strat.apply(g, delta.clone()); @@ -213,8 +226,16 @@ where #[cfg(test)] mod tests { - use super::{FactoredTransversal, Transversal}; - use crate::perm::{DefaultPermutation, Permutation}; + use { + super::{ + FactoredTransversal, + Transversal, + }, + crate::perm::{ + DefaultPermutation, + Permutation, + }, + }; /// Test the factored transversal calculation for a generating set with multiple generators. #[test] diff --git a/src/group/orbit/transversal/mod.rs b/src/group/orbit/transversal/mod.rs index 2b85e010111..68787b70923 100644 --- a/src/group/orbit/transversal/mod.rs +++ b/src/group/orbit/transversal/mod.rs @@ -5,11 +5,15 @@ pub mod shallow_transversal; pub mod simple_transversal; pub mod skeleton; -pub use factored_transversal::FactoredTransversal; -pub use simple_transversal::SimpleTransversal; +pub use { + factored_transversal::FactoredTransversal, + simple_transversal::SimpleTransversal, +}; -use crate::perm::actions::SimpleApplication; -use crate::perm::Action; +use crate::perm::{ + actions::SimpleApplication, + Action, +}; use std::fmt::Debug; @@ -61,9 +65,7 @@ pub enum TransversalError { } /// Validate a transversal -pub fn valid_transversal( - transv: &impl Transversal, -) -> Result<(), TransversalError> +pub fn valid_transversal(transv: &impl Transversal) -> Result<(), TransversalError> where A: Action

, { @@ -100,10 +102,16 @@ where macro_rules! transversal_tests { ($name:ty, $short:ident) => { mod $short { - use crate::group::orbit::transversal::valid_transversal; - use crate::group::orbit::transversal::Transversal; - use crate::group::Group; - use crate::perm::*; + use crate::{ + group::{ + orbit::transversal::{ + valid_transversal, + Transversal, + }, + Group, + }, + perm::*, + }; #[test] fn id_transveral() { @@ -163,8 +171,5 @@ macro_rules! transversal_tests { #[cfg(test)] mod tests { transversal_tests!(crate::group::orbit::transversal::SimpleTransversal, simple); - transversal_tests!( - crate::group::orbit::transversal::FactoredTransversal, - factored - ); + transversal_tests!(crate::group::orbit::transversal::FactoredTransversal, factored); } diff --git a/src/group/orbit/transversal/shallow_transversal/cube.rs b/src/group/orbit/transversal/shallow_transversal/cube.rs index 77ebb0f0e1d..c0b0ca04466 100644 --- a/src/group/orbit/transversal/shallow_transversal/cube.rs +++ b/src/group/orbit/transversal/shallow_transversal/cube.rs @@ -1,5 +1,11 @@ -use crate::perm::{Action, Permutation}; -use crate::{DetHashMap, DetHashSet}; +use crate::{ + perm::{ + Action, + Permutation, + }, + DetHashMap, + DetHashSet, +}; /// Struct to represent the cube like structure from the remark after Lemma 4.4.1 from Seress pub(super) struct Cube @@ -53,7 +59,7 @@ where break; } } - Cube { + Self { orbit, cube: cubes.pop().unwrap(), depth, @@ -63,16 +69,24 @@ where #[cfg(test)] mod tests { - use super::*; - use crate::group::orbit::transversal::factored_transversal::representative_raw; - use crate::group::Group; - use crate::perm::actions::SimpleApplication; - use crate::perm::export::CyclePermutation; - use crate::perm::{DefaultPermutation, Permutation}; + use { + super::*, + crate::{ + group::{ + orbit::transversal::factored_transversal::representative_raw, + Group, + }, + perm::{ + actions::SimpleApplication, + export::CyclePermutation, + DefaultPermutation, + Permutation, + }, + }, + }; #[test] fn test_single_generator() { - let gens: Vec = - vec![CyclePermutation::single_cycle(&[1_usize, 2, 3]).into()]; + let gens: Vec = vec![CyclePermutation::single_cycle(&[1_usize, 2, 3]).into()]; let g = Group::from_list(gens); let strat = SimpleApplication::default(); let cube = Cube::new(1, g.generators(), &strat, None); @@ -82,12 +96,7 @@ mod tests { assert!(cube.orbit.contains_key(&2)); dbg!(cube.depth); for &i in cube.orbit.keys() { - assert_eq!( - i, - representative_raw(&cube.orbit, 1, i, &strat) - .unwrap() - .apply(1) - ); + assert_eq!(i, representative_raw(&cube.orbit, 1, i, &strat).unwrap().apply(1)); } } } diff --git a/src/group/orbit/transversal/shallow_transversal/mod.rs b/src/group/orbit/transversal/shallow_transversal/mod.rs index bdcc10dc476..d2811840fc6 100644 --- a/src/group/orbit/transversal/shallow_transversal/mod.rs +++ b/src/group/orbit/transversal/shallow_transversal/mod.rs @@ -1,14 +1,25 @@ //! Collection of functions that will compute shallow(er) transversals. -use crate::group::orbit::orbit_complete_opt; -use crate::group::random_perm::RandPerm; -use crate::group::{Action, Group}; -use crate::perm::impls::word::WordPermutation; -use crate::perm::Permutation; -use crate::DetHashMap; -use rand::seq::SliceRandom; -use rand::Rng; -use std::collections::VecDeque; +use { + crate::{ + group::{ + orbit::orbit_complete_opt, + random_perm::RandPerm, + Action, + Group, + }, + perm::{ + impls::word::WordPermutation, + Permutation, + }, + DetHashMap, + }, + rand::{ + seq::SliceRandom, + Rng, + }, + std::collections::VecDeque, +}; mod cube; @@ -37,9 +48,8 @@ where let mut to_traverse = VecDeque::new(); to_traverse.push_back(base.clone()); // While there are still elements of the orbit unused. - 'element_checking: while !to_traverse.is_empty() { - //Take an unused element. - let delta = to_traverse.pop_front().unwrap(); + //Take an unused element. + 'element_checking: while let Some(delta) = to_traverse.pop_front() { for g in gens { let point = strat.apply(g, delta.clone()); @@ -143,11 +153,18 @@ where #[cfg(test)] mod tests { - use super::*; - use crate::group::orbit::transversal::factored_transversal::representative_raw; - use crate::perm::actions::SimpleApplication; - use crate::perm::export::CyclePermutation; - use crate::perm::{DefaultPermutation, Permutation}; + use { + super::*, + crate::{ + group::orbit::transversal::factored_transversal::representative_raw, + perm::{ + actions::SimpleApplication, + export::CyclePermutation, + DefaultPermutation, + Permutation, + }, + }, + }; /// Test the factored transversal calculation for a generating set with multiple generators. #[test] @@ -163,17 +180,11 @@ mod tests { let strat = SimpleApplication::default(); //All points should be in the orbit (according to GAP) for i in 0_usize..6 { - let (transversal, max_depth) = - random_transversal_naive(&mut g.clone(), i, &strat, &mut rng, set_depth); + let (transversal, max_depth) = random_transversal_naive(&mut g.clone(), i, &strat, &mut rng, set_depth); assert!(max_depth < set_depth + 1); for j in 0_usize..6 { assert!(transversal.contains_key(&j)); - assert_eq!( - j, - representative_raw(&transversal, i, j, &strat) - .unwrap() - .apply(i) - ); + assert_eq!(j, representative_raw(&transversal, i, j, &strat).unwrap().apply(i)); } } } @@ -195,12 +206,7 @@ mod tests { dbg!(max_depth); for j in 0_usize..6 { assert!(transversal.contains_key(&j)); - assert_eq!( - j, - representative_raw(&transversal, i, j, &strat) - .unwrap() - .apply(i) - ); + assert_eq!(j, representative_raw(&transversal, i, j, &strat).unwrap().apply(i)); } } } @@ -219,25 +225,19 @@ mod tests { let mut rng = rand::thread_rng(); let set_depth = 2; let strat = SimpleApplication::default(); - let (fc1, max_depth) = - random_transversal_naive(&mut g.clone(), 5, &strat, &mut rng, set_depth); + let (fc1, max_depth) = random_transversal_naive(&mut g.clone(), 5, &strat, &mut rng, set_depth); assert_eq!(3, fc1.len()); assert!(max_depth < set_depth + 1); - let (fc2, max_depth) = - random_transversal_naive(&mut g.clone(), 4, &strat, &mut rng, set_depth); + let (fc2, max_depth) = random_transversal_naive(&mut g.clone(), 4, &strat, &mut rng, set_depth); assert_eq!(3, fc2.len()); assert!(max_depth < set_depth + 1); - let (fc3, max_depth) = - random_transversal_naive(&mut g.clone(), 3, &strat, &mut rng, set_depth); + let (fc3, max_depth) = random_transversal_naive(&mut g.clone(), 3, &strat, &mut rng, set_depth); assert_eq!(1, fc3.len()); assert!(max_depth < set_depth + 1); for i in [0, 1, 5].iter() { // Tests for fc1 assert!(fc1.contains_key(i)); - assert_eq!( - *i, - representative_raw(&fc1, 5, *i, &strat).unwrap().apply(5) - ); + assert_eq!(*i, representative_raw(&fc1, 5, *i, &strat).unwrap().apply(5)); // Tests for fc2 assert!(!fc2.contains_key(i)); assert_eq!(None, representative_raw(&fc2, 4, *i, &strat)); @@ -251,10 +251,7 @@ mod tests { assert_eq!(None, representative_raw(&fc1, 5, *i, &strat)); // Tests for fc2 assert!(fc2.contains_key(i)); - assert_eq!( - *i, - representative_raw(&fc2, 4, *i, &strat).unwrap().apply(4) - ); + assert_eq!(*i, representative_raw(&fc2, 4, *i, &strat).unwrap().apply(4)); // Tests for fc3 assert!(!fc3.contains_key(i)); assert_eq!(None, representative_raw(&fc3, 3, *i, &strat)); @@ -293,10 +290,7 @@ mod tests { for i in [0, 1, 5].iter() { // Tests for fc1 assert!(fc1.contains_key(i)); - assert_eq!( - *i, - representative_raw(&fc1, 5, *i, &strat).unwrap().apply(5) - ); + assert_eq!(*i, representative_raw(&fc1, 5, *i, &strat).unwrap().apply(5)); // Tests for fc2 assert!(!fc2.contains_key(i)); assert_eq!(None, representative_raw(&fc2, 4, *i, &strat)); @@ -310,10 +304,7 @@ mod tests { assert_eq!(None, representative_raw(&fc1, 5, *i, &strat)); // Tests for fc2 assert!(fc2.contains_key(i)); - assert_eq!( - *i, - representative_raw(&fc2, 4, *i, &strat).unwrap().apply(4) - ); + assert_eq!(*i, representative_raw(&fc2, 4, *i, &strat).unwrap().apply(4)); // Tests for fc3 assert!(!fc3.contains_key(i)); assert_eq!(None, representative_raw(&fc3, 3, *i, &strat)); diff --git a/src/group/orbit/transversal/simple_transversal.rs b/src/group/orbit/transversal/simple_transversal.rs index dacfb722096..2eef512004e 100644 --- a/src/group/orbit/transversal/simple_transversal.rs +++ b/src/group/orbit/transversal/simple_transversal.rs @@ -1,15 +1,25 @@ //! A transversal which naively stores the first representative it finds -use crate::group::Group; -use crate::perm::actions::SimpleApplication; -use crate::perm::*; - -use super::skeleton::TransversalSkeleton; -use super::Transversal; -use crate::group::orbit::abstraction::SimpleTransversalResolver; - -use crate::DetHashMap; -use std::collections::VecDeque; +use crate::{ + group::Group, + perm::{ + actions::SimpleApplication, + *, + }, +}; + +use { + super::{ + skeleton::TransversalSkeleton, + Transversal, + }, + crate::group::orbit::abstraction::SimpleTransversalResolver, +}; + +use { + crate::DetHashMap, + std::collections::VecDeque, +}; /// Transversal using the naive algorithm /// Should be quicker computation wise but possibly much more @@ -40,11 +50,7 @@ where { /// Create from the group pub fn new_with_action(g: &Group

, base: A::OrbitT, strategy: &A) -> Self { - Self::from_raw( - base.clone(), - transversal(g, base, strategy), - SimpleTransversalResolver, - ) + Self::from_raw(base.clone(), transversal(g, base, strategy), SimpleTransversalResolver) } } @@ -56,11 +62,7 @@ where P: fmt::Display + Permutation, { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!( - f, - "[Transversal: base := {}, elements := {{", - self.base() + 1, - )?; + write!(f, "[Transversal: base := {}, elements := {{", self.base() + 1,)?; for (orbit, repr) in self.raw_elements() { write!(f, "({}, {}) ", orbit + 1, repr)? @@ -92,8 +94,7 @@ where to_traverse.push_back(base); // While we have stuff to do - while !to_traverse.is_empty() { - let delta = to_traverse.pop_front().unwrap(); + while let Some(delta) = to_traverse.pop_front() { for g in gens { let gamma = strat.apply(g, delta.clone()); @@ -111,11 +112,7 @@ where /// Optimized version of transversal which does less work on complete groups // Needed since entry requires &mut #[allow(clippy::map_entry)] -pub fn transversal_complete_opt( - g: &Group

, - base: A::OrbitT, - strat: &A, -) -> DetHashMap +pub fn transversal_complete_opt(g: &Group

, base: A::OrbitT, strat: &A) -> DetHashMap where P: Permutation, A: Action

, @@ -133,8 +130,7 @@ where to_traverse.push_back(base); // While we have stuff to do - while !to_traverse.is_empty() { - let delta = to_traverse.pop_front().unwrap(); + while let Some(delta) = to_traverse.pop_front() { for g in gens { let gamma = strat.apply(g, delta.clone()); diff --git a/src/group/orbit/transversal/skeleton.rs b/src/group/orbit/transversal/skeleton.rs index 4ea15ccc987..563425423ca 100644 --- a/src/group/orbit/transversal/skeleton.rs +++ b/src/group/orbit/transversal/skeleton.rs @@ -1,8 +1,12 @@ //! Utility to avoid code duplication in the context of transversals -use super::Transversal; -use crate::group::orbit::abstraction::TransversalResolver; -use crate::perm::Action; +use { + super::Transversal, + crate::{ + group::orbit::abstraction::TransversalResolver, + perm::Action, + }, +}; use crate::DetHashMap; @@ -24,12 +28,8 @@ impl TransversalSkeleton where A: Action

, { - pub(crate) fn from_raw( - base: A::OrbitT, - transversal: DetHashMap, - resolver: R, - ) -> Self { - TransversalSkeleton { + pub(crate) fn from_raw(base: A::OrbitT, transversal: DetHashMap, resolver: R) -> Self { + Self { base, transversal, resolver, @@ -55,10 +55,7 @@ where /// Get the orbit from the transversal fn orbit(&self) -> crate::group::orbit::Orbit { - crate::group::orbit::Orbit::from_raw( - self.base.clone(), - self.transversal.keys().cloned().collect(), - ) + crate::group::orbit::Orbit::from_raw(self.base.clone(), self.transversal.keys().cloned().collect()) } /// Get the computed representative diff --git a/src/group/random_perm.rs b/src/group/random_perm.rs index 4ba81575bb0..656b7bd05b3 100644 --- a/src/group/random_perm.rs +++ b/src/group/random_perm.rs @@ -1,12 +1,19 @@ //! Utility for generating random elements of a subgroup -use super::Group; -use crate::perm::impls::word::WordPermutation; -use crate::perm::{DefaultPermutation, Permutation}; -use rand::prelude::SliceRandom; -use rand::rngs::ThreadRng; -use rand::Rng; -use std::cmp::max; +use { + super::Group, + crate::perm::{ + impls::word::WordPermutation, + DefaultPermutation, + Permutation, + }, + rand::{ + prelude::SliceRandom, + rngs::ThreadRng, + Rng, + }, + std::cmp::max, +}; /// Calling random_element from this struct repetedly will generate random permutations in the subgroup #[derive(Debug)] @@ -36,7 +43,7 @@ where } let accum = P::id(); let size = max(min_size, k); - let mut rand = RandPerm { + let mut rand = Self { size, rng, gen_elements, @@ -156,12 +163,7 @@ mod tests { /// Test that elements generated are in the subgroup generated by the generator fn closure_small() { let generator = DefaultPermutation::from_images(&[3, 0, 1, 2]); - let elements = vec![ - generator.clone(), - generator.pow(2), - generator.pow(3), - generator.pow(4), - ]; + let elements = [generator.clone(), generator.pow(2), generator.pow(3), generator.pow(4)]; let mut rand_perm = RandPerm::from_generators(10, &Group::new(&elements[..]), 50); for _ in 0..50 { assert!(elements.contains(&rand_perm.random_permutation())); @@ -171,8 +173,10 @@ mod tests { #[test] /// Test that elements generated are in the subgroup for multiple generators. fn closure_larger_disjoint() { - use crate::group::Group; - use crate::perm::export::CyclePermutation; + use crate::{ + group::Group, + perm::export::CyclePermutation, + }; let g = Group::::new(&[ CyclePermutation::single_cycle(&[1, 2, 4]).into(), CyclePermutation::single_cycle(&[3, 5, 8]).into(), diff --git a/src/group/stabchain/base/mod.rs b/src/group/stabchain/base/mod.rs index 5f38671dc1f..82eba6411ab 100644 --- a/src/group/stabchain/base/mod.rs +++ b/src/group/stabchain/base/mod.rs @@ -1,7 +1,11 @@ pub mod selectors; -use crate::perm::actions::SimpleApplication; -use crate::perm::{Action, DefaultPermutation, Permutation}; +use crate::perm::{ + actions::SimpleApplication, + Action, + DefaultPermutation, + Permutation, +}; #[derive(Clone)] pub struct Base

> where @@ -55,13 +59,15 @@ where .map(move |i| (i.clone(), self.action.apply(&perm, i.clone()))), ) }) - .flat_map(|(p, mut it)| { - if it.all(|pair| pair.0 == pair.1) { - Some(p) - } else { - None - } - }) + .flat_map( + |(p, mut it)| { + if it.all(|pair| pair.0 == pair.1) { + Some(p) + } else { + None + } + }, + ) .next() } diff --git a/src/group/stabchain/base/selectors/adaptors.rs b/src/group/stabchain/base/selectors/adaptors.rs index 116be18cdb4..47f0699968d 100644 --- a/src/group/stabchain/base/selectors/adaptors.rs +++ b/src/group/stabchain/base/selectors/adaptors.rs @@ -14,11 +14,7 @@ impl PartialSelector { /// Create a new selector, that uses the first selector for limit number of points, and /// the second from there on pub fn new(first: F, limit: usize, second: S) -> Self { - PartialSelector { - limit, - first, - second, - } + Self { limit, first, second } } } @@ -47,12 +43,8 @@ where { pub fn new(base: &[T], after_partial: S) -> Self { // Create a partial selector that uses the fixed base first and then the second selector. - PartialFixedBaseSelector { - selector: PartialSelector::new( - super::FixedBaseSelector::new(base), - base.len(), - after_partial, - ), + Self { + selector: PartialSelector::new(super::FixedBaseSelector::new(base), base.len(), after_partial), } } } @@ -98,15 +90,19 @@ mod tests { #[test] fn partial_lmp() { - use super::super::{FixedBaseSelector, LmpSelector}; - use crate::group::Group; + use { + super::super::{ + FixedBaseSelector, + LmpSelector, + }, + crate::group::Group, + }; use crate::perm::*; let base = [0, 1, 2, 3, 4, 5]; - let mut selector = - PartialSelector::new(FixedBaseSelector::new(&base), 6, LmpSelector::default()); + let mut selector = PartialSelector::new(FixedBaseSelector::new(&base), 6, LmpSelector); let g = Group::symmetric(10); let mut rand = g.rng(); @@ -114,23 +110,23 @@ mod tests { assert_eq!(selector.moved_point(&perm, i), i); } - for (i, perm) in - (6..20).zip(std::iter::repeat_with(|| rand.random_permutation()).filter(|p| !p.is_id())) - { + for (i, perm) in (6..20).zip(std::iter::repeat_with(|| rand.random_permutation()).filter(|p| !p.is_id())) { assert_eq!(selector.moved_point(&perm, i), perm.lmp().unwrap()); } } #[test] fn partial_fixed_base_lmp() { - use super::super::LmpSelector; - use crate::group::Group; + use { + super::super::LmpSelector, + crate::group::Group, + }; use crate::perm::*; let base = [0, 1, 2, 3, 4, 5]; - let mut selector = PartialFixedBaseSelector::new(&base, LmpSelector::default()); + let mut selector = PartialFixedBaseSelector::new(&base, LmpSelector); let g = Group::symmetric(10); let mut rand = g.rng(); @@ -138,9 +134,7 @@ mod tests { assert_eq!(selector.moved_point(&perm, i), i); } - for (i, perm) in - (6..20).zip(std::iter::repeat_with(|| rand.random_permutation()).filter(|p| !p.is_id())) - { + for (i, perm) in (6..20).zip(std::iter::repeat_with(|| rand.random_permutation()).filter(|p| !p.is_id())) { assert_eq!(selector.moved_point(&perm, i), perm.lmp().unwrap()); } } diff --git a/src/group/stabchain/base/selectors/fixed_base.rs b/src/group/stabchain/base/selectors/fixed_base.rs index 3c3aeede841..b5493219924 100644 --- a/src/group/stabchain/base/selectors/fixed_base.rs +++ b/src/group/stabchain/base/selectors/fixed_base.rs @@ -14,9 +14,7 @@ where { /// Create from the given base pub fn new(base: &[T]) -> Self { - FixedBaseSelector { - base: base.to_vec(), - } + Self { base: base.to_vec() } } } @@ -25,10 +23,7 @@ where T: Clone + Debug, { fn moved_point(&mut self, _: &P, pos: usize) -> T { - self.base - .get(pos) - .cloned() - .expect("Base was shorter than expected") + self.base.get(pos).cloned().expect("Base was shorter than expected") } } @@ -36,7 +31,7 @@ use std::iter::FromIterator; impl FromIterator for FixedBaseSelector { fn from_iter>(iter: T) -> Self { - FixedBaseSelector { + Self { base: iter.into_iter().collect(), } } diff --git a/src/group/stabchain/base/selectors/mod.rs b/src/group/stabchain/base/selectors/mod.rs index d0dc8127e0b..9afe3f9b2ec 100644 --- a/src/group/stabchain/base/selectors/mod.rs +++ b/src/group/stabchain/base/selectors/mod.rs @@ -4,8 +4,13 @@ pub mod adaptors; pub mod fixed_base; pub mod moved_point; -pub use fixed_base::FixedBaseSelector; -pub use moved_point::{FmpSelector, LmpSelector}; +pub use { + fixed_base::FixedBaseSelector, + moved_point::{ + FmpSelector, + LmpSelector, + }, +}; use std::fmt::Debug; @@ -22,8 +27,10 @@ pub type DefaultSelector = LmpSelector; #[cfg(test)] mod tests { - use super::*; - use crate::perm::*; + use { + super::*, + crate::perm::*, + }; #[test] fn lmp_test() { diff --git a/src/group/stabchain/base_change_builder/mod.rs b/src/group/stabchain/base_change_builder/mod.rs index 8255801bee9..e41b1e5a8c8 100644 --- a/src/group/stabchain/base_change_builder/mod.rs +++ b/src/group/stabchain/base_change_builder/mod.rs @@ -1,9 +1,21 @@ //! Traits for creating chains -use super::Stabchain; -use crate::group::orbit::abstraction::{FactoredTransversalResolver, TransversalResolver}; -use crate::group::stabchain::base::Base; -use crate::perm::{Action, Permutation}; +use { + super::Stabchain, + crate::{ + group::{ + orbit::abstraction::{ + FactoredTransversalResolver, + TransversalResolver, + }, + stabchain::base::Base, + }, + perm::{ + Action, + Permutation, + }, + }, +}; mod random; @@ -55,7 +67,7 @@ pub struct RandomBaseChangeStrategy { impl RandomBaseChangeStrategy { /// Create the strategy pub fn new(action: A) -> Self { - RandomBaseChangeStrategy { action } + Self { action } } } diff --git a/src/group/stabchain/base_change_builder/random.rs b/src/group/stabchain/base_change_builder/random.rs index 55f53d28ade..5fdce87e92d 100644 --- a/src/group/stabchain/base_change_builder/random.rs +++ b/src/group/stabchain/base_change_builder/random.rs @@ -1,14 +1,29 @@ -use super::super::order; -use crate::group::orbit::transversal::shallow_transversal::shallow_transversal; -use crate::DetHashSet; -use crate::{ - group::{ - orbit::abstraction::{FactoredTransversalResolver, TransversalResolver}, - random_perm::RandPerm, - stabchain::{base::Base, Stabchain, StabchainRecord}, - Group, +use { + super::super::order, + crate::{ + group::{ + orbit::{ + abstraction::{ + FactoredTransversalResolver, + TransversalResolver, + }, + transversal::shallow_transversal::shallow_transversal, + }, + random_perm::RandPerm, + stabchain::{ + base::Base, + Stabchain, + StabchainRecord, + }, + Group, + }, + perm::{ + actions::SimpleApplication, + Action, + Permutation, + }, + DetHashSet, }, - perm::{actions::SimpleApplication, Action, Permutation}, }; const MIN_SIZE: usize = 11; @@ -30,7 +45,7 @@ where A: Action

, { pub(super) fn new(action: A) -> Self { - RandomBaseChangeBuilder { + Self { chain: Vec::new(), action, } @@ -107,8 +122,7 @@ where } } -impl super::BaseChangeBuilder, A> - for RandomBaseChangeBuilder +impl super::BaseChangeBuilder, A> for RandomBaseChangeBuilder where P: Permutation, A: Action

, @@ -119,12 +133,7 @@ where { //Bases should simply be alternative orderings (or with new without duplicates unneccessary elements added) debug_assert!( - base.base() - .iter() - .cloned() - .collect::>() - .len() - == base.base().len() + base.base().iter().cloned().collect::>().len() == base.base().len() && chain.base().iter().all(|point| base.base().contains(point)) ); self.random_base_change(chain, base); diff --git a/src/group/stabchain/builder/ift.rs b/src/group/stabchain/builder/ift.rs index b02f5cfac16..856002be5a3 100644 --- a/src/group/stabchain/builder/ift.rs +++ b/src/group/stabchain/builder/ift.rs @@ -1,15 +1,32 @@ -use super::Stabchain; -use crate::group::orbit::abstraction::FactoredTransversalResolver; -use crate::group::orbit::transversal::factored_transversal::representative_raw; -use crate::group::stabchain::base::selectors::BaseSelector; -use crate::group::stabchain::{element_testing, StabchainRecord}; -use crate::group::Group; -use crate::perm::actions::SimpleApplication; -use crate::perm::{Action, Permutation}; -use crate::DetHashMap; -use std::collections::VecDeque; - -use tracing::{debug, trace}; +use { + super::Stabchain, + crate::{ + group::{ + orbit::{ + abstraction::FactoredTransversalResolver, + transversal::factored_transversal::representative_raw, + }, + stabchain::{ + base::selectors::BaseSelector, + element_testing, + StabchainRecord, + }, + Group, + }, + perm::{ + actions::SimpleApplication, + Action, + Permutation, + }, + DetHashMap, + }, + std::collections::VecDeque, +}; + +use tracing::{ + debug, + trace, +}; // Helper struct, used to build the stabilizer chain #[derive(Debug)] @@ -30,7 +47,7 @@ where P: Permutation, { pub(super) fn new(selector: S, action: A) -> Self { - StabchainBuilderIft { + Self { current_pos: 0, chain: Vec::new(), selector, @@ -42,9 +59,7 @@ where self.current_pos == self.chain.len() } - fn current_chain( - &self, - ) -> impl Iterator, A>> { + fn current_chain(&self) -> impl Iterator, A>> { self.chain.iter().skip(self.current_pos) } } @@ -113,23 +128,14 @@ where let new_image = self.action.apply(&p, orbit_element); // If we already saw the element - if record.transversal.contains_key(&new_image) - || new_transversal.contains_key(&new_image) - { + if record.transversal.contains_key(&new_image) || new_transversal.contains_key(&new_image) { let image_repr = representative_raw( &record.transversal, record.base.clone(), new_image.clone(), &self.action, ) - .or_else(|| { - representative_raw( - &new_transversal, - record.base.clone(), - new_image, - &self.action, - ) - }) + .or_else(|| representative_raw(&new_transversal, record.base.clone(), new_image, &self.action)) .unwrap(); let new_perm = orbit_element_repr.multiply(&p).multiply(&image_repr.inv()); @@ -146,9 +152,8 @@ where record.transversal.extend(new_transversal); // While we have orbit elements (and representatives to check) - while !to_check.is_empty() { + while let Some(orbit_element) = to_check.pop_back() { // Get the pair - let orbit_element = to_check.pop_back().unwrap(); let orbit_element_repr = representative_raw( &record.transversal, record.base.clone(), @@ -173,15 +178,11 @@ where .unwrap(); // Extend lower level - let new_perm = orbit_element_repr - .multiply(generator) - .multiply(&image_repr.inv()); + let new_perm = orbit_element_repr.multiply(generator).multiply(&image_repr.inv()); self.extend_lower_level(new_perm); } else { // Store in transversal - record - .transversal - .insert(new_image.clone(), generator.inv()); + record.transversal.insert(new_image.clone(), generator.inv()); // Update and ask to check the new image to_check.push_back(new_image); @@ -190,10 +191,7 @@ where } // Update the generators adding p - record.gens = std::iter::once(&p) - .chain(record.gens.generators()) - .cloned() - .collect(); + record.gens = std::iter::once(&p).chain(record.gens.generators()).cloned().collect(); // Store the updated record in the chain self.chain[self.current_pos] = record; diff --git a/src/group/stabchain/builder/mod.rs b/src/group/stabchain/builder/mod.rs index 574e525b779..c79e377b3e3 100644 --- a/src/group/stabchain/builder/mod.rs +++ b/src/group/stabchain/builder/mod.rs @@ -1,15 +1,28 @@ //! Traits for creating chains -use super::Stabchain; -use crate::group::orbit::abstraction::{ - FactoredTransversalResolver, SimpleTransversalResolver, TransversalResolver, +use { + super::Stabchain, + crate::{ + group::{ + orbit::abstraction::{ + FactoredTransversalResolver, + SimpleTransversalResolver, + TransversalResolver, + }, + stabchain::base::selectors::BaseSelector, + Group, + }, + perm::{ + Action, + Permutation, + }, + }, }; -use crate::group::stabchain::base::selectors::BaseSelector; -use crate::group::Group; -use crate::perm::{Action, Permutation}; -use rand::rngs::ThreadRng; -use rand::Rng; +use rand::{ + rngs::ThreadRng, + Rng, +}; use std::fmt::Debug; @@ -66,7 +79,7 @@ pub struct NaiveBuilderStrategy { impl NaiveBuilderStrategy { /// Create the strategy pub fn new(action: A, selector: S) -> Self { - NaiveBuilderStrategy { selector, action } + Self { selector, action } } } @@ -96,7 +109,7 @@ pub struct IftBuilderStrategy { impl IftBuilderStrategy { /// Create the strategy pub fn new(action: A, selector: S) -> Self { - IftBuilderStrategy { selector, action } + Self { selector, action } } } @@ -123,10 +136,7 @@ use random::parameters::RandomAlgoParameters; /// This should be faster than the naive and IFT methods, but is not deterministic. /// This should not be used, as the shallow version is faster and more reliable. #[derive(Debug, Clone)] -#[deprecated( - since = "0.1.1", - note = "please use `RandomBuilderStrategyShallow` instead" -)] +#[deprecated(since = "0.1.1", note = "please use `RandomBuilderStrategyShallow` instead")] pub struct RandomBuilderStrategyNaive { selector: S, action: A, @@ -136,7 +146,7 @@ pub struct RandomBuilderStrategyNaive { #[allow(deprecated)] impl RandomBuilderStrategyNaive { pub fn new(action: A, selector: S) -> Self { - RandomBuilderStrategyNaive { + Self { selector, action, params: random::parameters::RandomAlgoParameters::default(), @@ -147,7 +157,7 @@ impl RandomBuilderStrategyNaive { #[allow(deprecated)] impl RandomBuilderStrategyNaive { pub fn new_with_params(action: A, selector: S, params: RandomAlgoParameters) -> Self { - RandomBuilderStrategyNaive { + Self { selector, action, params, @@ -183,7 +193,7 @@ pub struct RandomBuilderStrategyShallow { impl RandomBuilderStrategyShallow { pub fn new(action: A, selector: S) -> Self { - RandomBuilderStrategyShallow { + Self { action, selector, params: RandomAlgoParameters::default(), @@ -193,7 +203,7 @@ impl RandomBuilderStrategyShallow { impl RandomBuilderStrategyShallow { pub fn new_with_params(action: A, selector: S, params: RandomAlgoParameters) -> Self { - RandomBuilderStrategyShallow { + Self { selector, action, params, @@ -213,10 +223,6 @@ where type BuilderT = random::random_strees::StabchainBuilderRandomSTrees; fn make_builder(self) -> Self::BuilderT { - random::random_strees::StabchainBuilderRandomSTrees::new( - self.selector, - self.action, - self.params, - ) + random::random_strees::StabchainBuilderRandomSTrees::new(self.selector, self.action, self.params) } } diff --git a/src/group/stabchain/builder/naive.rs b/src/group/stabchain/builder/naive.rs index 831c1efbd0f..549cd5d2852 100644 --- a/src/group/stabchain/builder/naive.rs +++ b/src/group/stabchain/builder/naive.rs @@ -1,13 +1,31 @@ -use super::{BaseSelector, Stabchain}; -use crate::group::orbit::abstraction::SimpleTransversalResolver; -use crate::group::stabchain::{element_testing, StabchainRecord}; -use crate::group::Group; -use crate::perm::actions::SimpleApplication; -use crate::perm::{Action, Permutation}; -use crate::DetHashMap; -use std::collections::VecDeque; - -use tracing::{debug, trace}; +use { + super::{ + BaseSelector, + Stabchain, + }, + crate::{ + group::{ + orbit::abstraction::SimpleTransversalResolver, + stabchain::{ + element_testing, + StabchainRecord, + }, + Group, + }, + perm::{ + actions::SimpleApplication, + Action, + Permutation, + }, + DetHashMap, + }, + std::collections::VecDeque, +}; + +use tracing::{ + debug, + trace, +}; // Helper struct, used to build the stabilizer chain #[derive(Debug)] @@ -28,7 +46,7 @@ where P: Permutation, { pub(super) fn new(selector: S, action: A) -> Self { - StabchainBuilderNaive { + Self { current_pos: 0, chain: Vec::new(), selector, @@ -40,9 +58,7 @@ where self.current_pos == self.chain.len() } - fn current_chain( - &self, - ) -> impl Iterator> { + fn current_chain(&self) -> impl Iterator> { self.chain.iter().skip(self.current_pos) } } @@ -102,15 +118,12 @@ where let mut to_check: VecDeque<_> = record.transversal.keys().cloned().collect(); let mut new_transversal = DetHashMap::default(); - while !to_check.is_empty() { - let orbit_element = to_check.pop_back().unwrap(); + while let Some(orbit_element) = to_check.pop_back() { let orbit_element_repr = record.transversal.get(&orbit_element).unwrap(); let new_image = self.action.apply(&p, orbit_element); // If we already saw the element - if record.transversal.contains_key(&new_image) - || new_transversal.contains_key(&new_image) - { + if record.transversal.contains_key(&new_image) || new_transversal.contains_key(&new_image) { let image_repr = record .transversal .get(&new_image) @@ -125,19 +138,14 @@ where } // We now want to check all the newly added elements - let mut to_check: VecDeque<_> = new_transversal - .iter() - .map(|(o, p)| (o.clone(), p.clone())) - .collect(); + let mut to_check: VecDeque<_> = new_transversal.iter().map(|(o, p)| (o.clone(), p.clone())).collect(); // Update the record record.transversal.extend(new_transversal); // While we have orbit elements (and representatives to check) - while !to_check.is_empty() { + while let Some((orbit_element, orbit_element_repr)) = to_check.pop_back() { // Get the pair - let (orbit_element, orbit_element_repr) = to_check.pop_back().unwrap(); - // For each generator (and p) for generator in std::iter::once(&p).chain(record.gens.generators()) { let new_image = self.action.apply(generator, orbit_element.clone()); @@ -148,9 +156,7 @@ where let image_repr = record.transversal.get(&new_image).unwrap(); // Extend lower level - let new_perm = orbit_element_repr - .multiply(generator) - .multiply(&image_repr.inv()); + let new_perm = orbit_element_repr.multiply(generator).multiply(&image_repr.inv()); self.extend_lower_level(new_perm); } else { // Compute the repr s.t. repr^(orbit_element_repr * generator) = orbit_element ^ generator = new_image @@ -166,10 +172,7 @@ where } // Update the generators adding p - record.gens = std::iter::once(&p) - .chain(record.gens.generators()) - .cloned() - .collect(); + record.gens = std::iter::once(&p).chain(record.gens.generators()).cloned().collect(); // Store the updated record in the chain self.chain[self.current_pos] = record; diff --git a/src/group/stabchain/builder/random/parameters.rs b/src/group/stabchain/builder/random/parameters.rs index 71561273c65..f981ca52036 100644 --- a/src/group/stabchain/builder/random/parameters.rs +++ b/src/group/stabchain/builder/random/parameters.rs @@ -1,5 +1,7 @@ -use num::BigUint; -use rand::rngs::ThreadRng; +use { + num::BigUint, + rand::rngs::ThreadRng, +}; #[derive(Debug, Clone)] pub struct RandomAlgoParameters { @@ -28,7 +30,7 @@ pub struct Constants { impl RandomAlgoParameters { pub fn new() -> Self { - RandomAlgoParameters::default() + Self::default() } } @@ -106,7 +108,7 @@ impl RandomAlgoParameters { impl Default for RandomAlgoParameters { fn default() -> Self { - RandomAlgoParameters { + Self { c1: 1, c2: 1, c3: 1, diff --git a/src/group/stabchain/builder/random/random_ift.rs b/src/group/stabchain/builder/random/random_ift.rs index 8f9d70007bf..5e727777957 100644 --- a/src/group/stabchain/builder/random/random_ift.rs +++ b/src/group/stabchain/builder/random/random_ift.rs @@ -1,26 +1,53 @@ use super::parameters::RandomAlgoParameters; -use crate::group::orbit::abstraction::{FactoredTransversalResolver, TransversalResolver}; #[allow(deprecated)] use crate::group::orbit::transversal::factored_transversal::{ - factored_transversal_complete_opt, representative_raw_as_word, + factored_transversal_complete_opt, + representative_raw_as_word, +}; +use { + crate::{ + group::{ + orbit::abstraction::{ + FactoredTransversalResolver, + TransversalResolver, + }, + stabchain::{ + base::selectors::BaseSelector, + order, + Stabchain, + StabchainRecord, + }, + Group, + }, + perm::{ + actions::SimpleApplication, + Action, + Permutation, + }, + DetHashMap, + }, + itertools::Itertools, + rand::{ + rngs::ThreadRng, + seq::{ + IteratorRandom, + SliceRandom, + }, + Rng, + }, + std::{ + cell::RefCell, + collections::VecDeque, + fmt::Debug, + iter::repeat_with, + }, +}; + +use tracing::{ + debug, + trace, }; -use crate::group::stabchain::{base::selectors::BaseSelector, order, Stabchain, StabchainRecord}; -use crate::group::Group; -use crate::perm::actions::SimpleApplication; -use crate::perm::{Action, Permutation}; -use crate::DetHashMap; -use itertools::Itertools; -use rand::rngs::ThreadRng; -use rand::seq::IteratorRandom; -use rand::seq::SliceRandom; -use rand::Rng; -use std::cell::RefCell; -use std::collections::VecDeque; -use std::fmt::Debug; -use std::iter::repeat_with; - -use tracing::{debug, trace}; // Helper struct, used to build the stabilizer chain @@ -56,7 +83,7 @@ where pub fn new(selector: S, action: A, params: RandomAlgoParameters) -> Self { let (constants, random) = params.consts(); - StabchainBuilderRandom { + Self { current_pos: 0, chain: Vec::new(), selector, @@ -69,9 +96,7 @@ where } } - fn current_chain( - &self, - ) -> impl Iterator, A>> { + fn current_chain(&self) -> impl Iterator, A>> { self.chain.iter().skip(self.current_pos) } @@ -115,10 +140,7 @@ where coset_representatives: usize, gens: &[P], ) -> Vec> { - debug!( - level = self.current_pos, - "Random generation of Schrier Generators" - ); + debug!(level = self.current_pos, "Random generation of Schrier Generators"); //Sum of all "depths". In reality the transversal doesn't have a depth, so we use this as a upper bound. let t = self .chain @@ -127,8 +149,7 @@ where .sum::(); let record = &self.chain[self.current_pos]; //Create an iterator of subproducts w and w2 - let subproduct_w1_iter = - repeat_with(|| random_subproduct_word_full(&mut *self.rng.borrow_mut(), gens)); + let subproduct_w1_iter = repeat_with(|| random_subproduct_word_full(&mut *self.rng.borrow_mut(), gens)); let subproduct_w2_iter = repeat_with(|| { let k = rand::Rng::gen_range(&mut *self.rng.borrow_mut(), 0..1 + gens.len() / 2); random_subproduct_word_subset(&mut *self.rng.borrow_mut(), gens, k) @@ -146,13 +167,7 @@ where .keys() .choose(&mut *self.rng.borrow_mut()) .map(|point| { - representative_raw_as_word( - &record.transversal, - record.base, - *point, - &self.action, - ) - .unwrap() + representative_raw_as_word(&record.transversal, record.base, *point, &self.action).unwrap() }) .expect("should be present") }) @@ -177,14 +192,11 @@ where // If this element is already a generator, then we can exit let mut to_check: VecDeque<_> = record.transversal.keys().cloned().collect(); let mut new_transversal = DetHashMap::default(); - while !to_check.is_empty() { - let orbit_element = to_check.pop_back().unwrap(); + while let Some(orbit_element) = to_check.pop_back() { let new_image = self.action.apply(&p, orbit_element); // If we haven't seen this element. - if !(record.transversal.contains_key(&new_image) - || new_transversal.contains_key(&new_image)) - { + if !(record.transversal.contains_key(&new_image) || new_transversal.contains_key(&new_image)) { new_transversal.insert(new_image, p.inv()); } } @@ -196,9 +208,8 @@ where record.transversal.extend(new_transversal); // While we have orbit elements (and representatives to check) - while !to_check.is_empty() { + while let Some(orbit_element) = to_check.pop_back() { // Get the pair - let orbit_element = to_check.pop_back().unwrap(); // For each generator (and p) for generator in std::iter::once(&p).chain(record.gens.generators()) { let new_image = self.action.apply(generator, orbit_element); @@ -213,10 +224,7 @@ where // Update the generators adding p if it isn't already present. if !record.gens.generators().contains(&p) { debug!("Adding perm to generating set"); - record.gens = std::iter::once(&p) - .chain(record.gens.generators()) - .cloned() - .collect(); + record.gens = std::iter::once(&p).chain(record.gens.generators()).cloned().collect(); } // Store the updated record in the chain self.chain[self.current_pos] = record; @@ -231,25 +239,17 @@ where } fn sgc(&mut self) { - trace!( - level = self.current_pos, - "Strong Generating Set Construction" - ); + trace!(level = self.current_pos, "Strong Generating Set Construction"); let record = self.chain[self.current_pos].clone(); //Number of base points than are in the current orbit. - let b_star = self - .base - .iter() - .filter(|&b| record.transversal.contains_key(b)) - .count(); + let b_star = self.base.iter().filter(|&b| record.transversal.contains_key(b)).count(); let gens = self .current_chain() .flat_map(|record| record.gens.generators()) .cloned() .collect::>(); //Random products of the form gw - let mut random_gens = - self.random_schrier_generators_as_word(self.constants.c1, self.constants.c2, &gens[..]); + let mut random_gens = self.random_schrier_generators_as_word(self.constants.c1, self.constants.c2, &gens[..]); //Convert these into random schrier generators, by concatenating the resdiue of the inverse to it. random_gens.iter_mut().for_each(|gw| { //Get the residue of this word @@ -263,29 +263,28 @@ where let (drop_out_level, h_residue) = residue_as_words_from_words(self.current_chain(), &h); if self.sifted(drop_out_level) { //Pick the points that should be evaluated. This is a heuristic to speed up run times. - let evaluated_points: Vec = - if record.transversal.len() <= self.constants.orbit_bound { - //Evaluate on all points of the current orbit. - record.transversal.keys().cloned().collect() - } else if self.base.len() <= self.constants.base_bound { - //Evaluate on BASE_BOUND randomly chosen points. - record - .transversal - .keys() - .choose_multiple(&mut *self.rng.borrow_mut(), self.constants.base_bound) - .into_iter() - .cloned() - .collect() - } else { - //Evaluate on b_star randomly chosen points. - record - .transversal - .keys() - .choose_multiple(&mut *self.rng.borrow_mut(), b_star) - .into_iter() - .cloned() - .collect() - }; + let evaluated_points: Vec = if record.transversal.len() <= self.constants.orbit_bound { + //Evaluate on all points of the current orbit. + record.transversal.keys().cloned().collect() + } else if self.base.len() <= self.constants.base_bound { + //Evaluate on BASE_BOUND randomly chosen points. + record + .transversal + .keys() + .choose_multiple(&mut *self.rng.borrow_mut(), self.constants.base_bound) + .into_iter() + .cloned() + .collect() + } else { + //Evaluate on b_star randomly chosen points. + record + .transversal + .keys() + .choose_multiple(&mut *self.rng.borrow_mut(), b_star) + .into_iter() + .cloned() + .collect() + }; //If any point is not fixed by the residue, then we add the residue as a generator. if !self.is_trivial_residue(&h_residue, evaluated_points) { //Not all permutations have been discarded @@ -299,8 +298,7 @@ where self.base.push(new_base_point); //Fields for the new record. let gens = Group::new(&[h_star]); - let transversal = - factored_transversal_complete_opt(&gens, new_base_point, &self.action); + let transversal = factored_transversal_complete_opt(&gens, new_base_point, &self.action); let record = StabchainRecord::new(new_base_point, gens, transversal); self.chain.push(record); //Now up to date beneath the newly added point. @@ -362,11 +360,7 @@ where .generators .iter() .map(|p| vec![p.clone()]) - .chain(self.random_schrier_generators_as_word( - self.constants.c3, - self.constants.c4, - &gens[..], - )) + .chain(self.random_schrier_generators_as_word(self.constants.c3, self.constants.c4, &gens[..])) .collect(); //Sift the original generators, and all products of the form g*w_{1,2}. for p in products { @@ -396,13 +390,10 @@ where let collapsed_residue = collapse_perm_word(&residue); //If this point sifted through but isn't trivial, then we need a new record and base point. if self.sifted(drop_out_level) { - let moved_point = self - .selector - .moved_point(&collapsed_residue, self.current_pos); + let moved_point = self.selector.moved_point(&collapsed_residue, self.current_pos); debug!(perm = %collapsed_residue, moved_point = moved_point, "Extending chain"); let gens = Group::new(&[collapsed_residue]); - let transversal = - factored_transversal_complete_opt(&gens, moved_point, &self.action); + let transversal = factored_transversal_complete_opt(&gens, moved_point, &self.action); let initial_record = StabchainRecord::new(moved_point, gens, transversal); self.base.push(moved_point); self.chain.push(initial_record); @@ -425,11 +416,7 @@ where /// Check if a residue acts trivially on a set of points. /// This is just done by checking that the given permutation fixes all given points. - fn is_trivial_residue( - &self, - p_as_words: &[P], - points: impl IntoIterator, - ) -> bool { + fn is_trivial_residue(&self, p_as_words: &[P], points: impl IntoIterator) -> bool { points .into_iter() .all(|x| apply_permutation_word(p_as_words, x, &self.action) == x) @@ -482,18 +469,12 @@ where } /// Apply a point to permutations stored as a word. -fn apply_permutation_word<'a, P, A>( - perm_word: impl IntoIterator, - x: A::OrbitT, - strat: &A, -) -> A::OrbitT +fn apply_permutation_word<'a, P, A>(perm_word: impl IntoIterator, x: A::OrbitT, strat: &A) -> A::OrbitT where P: 'a + Permutation, A: Action

, { - perm_word - .into_iter() - .fold(x, |accum, p| strat.apply(p, accum)) + perm_word.into_iter().fold(x, |accum, p| strat.apply(p, accum)) } /// Convert from a permutation stored as a word, into a single permutation. @@ -544,12 +525,18 @@ mod tests { ///Test that applying a permutation as a word gives the same image as collapsing that permutation. #[test] fn test_apply_permutation_word() { - use super::apply_permutation_word; - use super::collapse_perm_word; - use crate::perm::actions::SimpleApplication; - use crate::perm::export::CyclePermutation; - use crate::perm::impls::standard::StandardPermutation; - use crate::perm::Permutation; + use { + super::{ + apply_permutation_word, + collapse_perm_word, + }, + crate::perm::{ + actions::SimpleApplication, + export::CyclePermutation, + impls::standard::StandardPermutation, + Permutation, + }, + }; //Test an empty word. let empty_word = vec![]; let strat = SimpleApplication::default(); @@ -562,10 +549,7 @@ mod tests { ]; let collapsed_word = collapse_perm_word(&perm_word); for i in 0..9 { - assert_eq!( - collapsed_word.apply(i), - apply_permutation_word(&perm_word, i, &strat) - ); + assert_eq!(collapsed_word.apply(i), apply_permutation_word(&perm_word, i, &strat)); } } } diff --git a/src/group/stabchain/builder/random/random_strees.rs b/src/group/stabchain/builder/random/random_strees.rs index f11e7068e62..8995f1326d8 100644 --- a/src/group/stabchain/builder/random/random_strees.rs +++ b/src/group/stabchain/builder/random/random_strees.rs @@ -1,28 +1,62 @@ -use super::parameters::RandomAlgoParameters; -use crate::group::orbit::abstraction::FactoredTransversalResolver; -use crate::group::orbit::transversal::shallow_transversal::{ - representative_raw_as_word, shallow_transversal, +use { + super::parameters::RandomAlgoParameters, + crate::{ + group::{ + orbit::{ + abstraction::FactoredTransversalResolver, + transversal::shallow_transversal::{ + representative_raw_as_word, + shallow_transversal, + }, + }, + stabchain::{ + base::selectors::BaseSelector, + element_testing::residue_as_words_from_words, + order, + Stabchain, + StabchainRecord, + }, + utils::{ + random_subproduct_word_full, + random_subproduct_word_subset, + }, + Group, + }, + perm::{ + actions::SimpleApplication, + impls::word::WordPermutation, + Action, + Permutation, + }, + DetHashMap, + }, + itertools::Itertools, + num::BigUint, + rand::{ + rngs::ThreadRng, + seq::IteratorRandom, + Rng, + }, + std::{ + cell::RefCell, + cmp::max, + collections::{ + hash_map::Entry, + VecDeque, + }, + iter::{ + repeat_with, + Iterator, + }, + }, }; -use crate::group::stabchain::element_testing::residue_as_words_from_words; -use crate::group::stabchain::{base::selectors::BaseSelector, order, Stabchain, StabchainRecord}; -use crate::group::utils::{random_subproduct_word_full, random_subproduct_word_subset}; -use crate::group::Group; -use crate::perm::actions::SimpleApplication; -use crate::perm::{impls::word::WordPermutation, Action, Permutation}; -use crate::DetHashMap; -use itertools::Itertools; -use num::BigUint; -use rand::rngs::ThreadRng; -use rand::{seq::IteratorRandom, Rng}; -use std::cell::RefCell; -use std::cmp::max; -use std::collections::hash_map::Entry; -use std::collections::VecDeque; -use std::iter::{repeat_with, Iterator}; use std::fmt::Debug; -use tracing::{debug, trace}; +use tracing::{ + debug, + trace, +}; // Helper struct, used to build the stabilizer chain #[derive(Debug)] @@ -55,7 +89,7 @@ where { pub fn new(selector: S, action: A, params: RandomAlgoParameters) -> Self { let (constants, random) = params.consts(); - StabchainBuilderRandomSTrees { + Self { chain: Vec::new(), selector, action, @@ -76,9 +110,7 @@ where self.chain.iter().skip(level) } - fn full_chain( - &self, - ) -> impl Iterator, A>> { + fn full_chain(&self) -> impl Iterator, A>> { self.chain.iter() } @@ -144,14 +176,10 @@ where let record = &self.chain[level]; let k = rand::Rng::gen_range(&mut *self.rng.borrow_mut(), 0..1 + gens.len() / 2); //Create an iterator of subproducts w and w2 - let subproduct_w1_iter = - repeat_with(|| random_subproduct_word_full(&mut *self.rng.borrow_mut(), gens)); - let subproduct_w2_iter = - repeat_with(|| random_subproduct_word_subset(&mut *self.rng.borrow_mut(), gens, k)); + let subproduct_w1_iter = repeat_with(|| random_subproduct_word_full(&mut *self.rng.borrow_mut(), gens)); + let subproduct_w2_iter = repeat_with(|| random_subproduct_word_subset(&mut *self.rng.borrow_mut(), gens, k)); //Iterleave the two iterators. - let subproduct_iter = subproduct_w1_iter - .interleave(subproduct_w2_iter) - .take(2 * subproducts); + let subproduct_iter = subproduct_w1_iter.interleave(subproduct_w2_iter).take(2 * subproducts); // First create coset_representative * t random coset reprensentatives. //Precompute all coset representatives if we'll be selecting more than there are in the orbit let mut gens: Vec> = { @@ -226,7 +254,7 @@ where /// Check if adding a new element modifies the current layer of the chain. fn check_transversal_augmentation(&mut self, p: &P, level: usize, check_transversal: bool) { debug!(level = level, perm = %p, "Checking transversal augmentation with perm"); - let mut record = &mut self.chain[level]; + let record = &mut self.chain[level]; // We optionally check if this element alters the transversal if check_transversal && record @@ -243,11 +271,8 @@ where let mut recompute_transversal = false; // First partion points at maximum depth and those not. let max_depth = self.max_depths[level]; - let (max_depth_points, mut to_check): (VecDeque, VecDeque) = self.depths - [level] - .keys() - .cloned() - .partition(|&x| x == max_depth); + let (max_depth_points, mut to_check): (VecDeque, VecDeque) = + self.depths[level].keys().cloned().partition(|&x| x == max_depth); // If any point at maximum depth is augmented then we recompute, as this exceeds the current maximum depth. for x in max_depth_points { let application = self.action.apply(p, x); @@ -261,13 +286,10 @@ where if !recompute_transversal { let mut new_transversal = DetHashMap::default(); let mut new_depths = DetHashMap::default(); - while !to_check.is_empty() { - let x = to_check.pop_front().unwrap(); + while let Some(x) = to_check.pop_front() { let current_depth = self.depths[level].get(&x).unwrap(); let new_image = self.action.apply(p, x); - if !(record.transversal.contains_key(&new_image) - || new_transversal.contains_key(&new_image)) - { + if !(record.transversal.contains_key(&new_image) || new_transversal.contains_key(&new_image)) { new_transversal.insert(new_image, p.inv()); new_depths.insert(new_image, current_depth + 1); } @@ -277,9 +299,8 @@ where record.transversal.extend(new_transversal); self.depths[level].extend(new_depths); // Check the newly added points - 'element_checking: while !to_check.is_empty() { + 'element_checking: while let Some(orbit_element) = to_check.pop_front() { // Get the pair - let orbit_element = to_check.pop_front().unwrap(); let orbit_depth = *self.depths[level].get(&orbit_element).unwrap(); // For each generator (and p) for generator in record.gens.generators() { @@ -301,12 +322,8 @@ where } //Calculate a new shallow transversal. if recompute_transversal { - let (transversal, new_depth) = shallow_transversal( - &mut record.gens, - record.base, - &self.action, - &mut *self.rng.borrow_mut(), - ); + let (transversal, new_depth) = + shallow_transversal(&mut record.gens, record.base, &self.action, &mut *self.rng.borrow_mut()); record.transversal = transversal; //Update the depths of the current position. self.max_depths.push(*new_depth.values().max().unwrap()); @@ -330,13 +347,8 @@ where // Take union of generating sets. let gens = self.union_gen_set(level); //Random products of the form gw - let random_gens = self.random_schrier_generators_as_word( - level, - self.constants.c1, - self.constants.c2, - &gens[..], - true, - ); + let random_gens = + self.random_schrier_generators_as_word(level, self.constants.c1, self.constants.c2, &gens[..], true); //To see if all generators are discarded. let mut all_discarded = true; //If the element we are testing is the first schrier generator tested. @@ -364,11 +376,7 @@ where .collect() } else { //Number of base points than are in the current orbit. - let b_star = self - .base - .iter() - .filter(|&b| transversal.contains_key(b)) - .count(); + let b_star = self.base.iter().filter(|&b| transversal.contains_key(b)).count(); //Evaluate on b_star randomly chosen points. transversal @@ -416,9 +424,7 @@ where Some(level - 1) } // Check the order for an early exit, as we know that something new has been added. - } else if self.constants.order.is_some() - && self.constants.order == Some(order(self.full_chain())) - { + } else if self.constants.order.is_some() && self.constants.order == Some(order(self.full_chain())) { None } else { // Continue with SGC. @@ -445,13 +451,7 @@ where .generators() .iter() .map(|p| WordPermutation::from_perm(p)) - .chain(self.random_schrier_generators_as_word( - 0, - self.constants.c3, - self.constants.c4, - &gens[..], - false, - )) + .chain(self.random_schrier_generators_as_word(0, self.constants.c3, self.constants.c4, &gens[..], false)) .collect(); //Sift the original generators, and all products of the form g*w_{1,2}. for p in products { @@ -531,12 +531,8 @@ where let moved_point = self.selector.moved_point(&gen, self.base.len()); debug!(perm = %gen, moved_point = moved_point, "Extending chain"); let mut gens = Group::new(&[gen]); - let (transversal, depth) = shallow_transversal( - &mut gens, - moved_point, - &self.action, - &mut *self.rng.borrow_mut(), - ); + let (transversal, depth) = + shallow_transversal(&mut gens, moved_point, &self.action, &mut *self.rng.borrow_mut()); let initial_record = StabchainRecord::new(moved_point, gens, transversal); self.base.push(moved_point); self.max_depths.push(*depth.values().max().unwrap()); @@ -552,10 +548,7 @@ where // Take the union of the generating sets from current position onwards. fn union_gen_set(&self, level: usize) -> Vec

{ let mut gen_set = Vec::new(); - for p in self - .current_chain(level) - .flat_map(|record| record.gens.generators()) - { + for p in self.current_chain(level).flat_map(|record| record.gens.generators()) { if !gen_set.contains(p) { gen_set.push(p.clone()) } diff --git a/src/group/stabchain/element_testing.rs b/src/group/stabchain/element_testing.rs index 369208ff53e..4a63ff2c428 100644 --- a/src/group/stabchain/element_testing.rs +++ b/src/group/stabchain/element_testing.rs @@ -1,15 +1,19 @@ //! Utilities for testing element membership and coset representatives -use super::StabchainRecord; -use crate::group::orbit::abstraction::TransversalResolver; -use crate::perm::impls::word::WordPermutation; -use crate::perm::{Action, Permutation}; +use { + super::StabchainRecord, + crate::{ + group::orbit::abstraction::TransversalResolver, + perm::{ + impls::word::WordPermutation, + Action, + Permutation, + }, + }, +}; /// Given a stabilizer chain, computes whether the given element is in the group -pub fn is_in_group<'a, P, A, V>( - it: impl IntoIterator>, - p: &P, -) -> bool +pub fn is_in_group<'a, P, A, V>(it: impl IntoIterator>, p: &P) -> bool where P: 'a + Permutation, A: 'a + Action

, @@ -88,10 +92,7 @@ where } /// Sift the permutation through the chain, returning the residue it generates. -pub fn residue_as_words<'a, P, A, V>( - it: impl IntoIterator>, - p: &P, -) -> Vec

+pub fn residue_as_words<'a, P, A, V>(it: impl IntoIterator>, p: &P) -> Vec

where V: 'a + TransversalResolver, P: 'a + Permutation, @@ -161,9 +162,13 @@ where #[cfg(test)] mod tests { - use super::*; - use crate::group::Group; - use crate::perm::DefaultPermutation; + use { + super::*, + crate::{ + group::Group, + perm::DefaultPermutation, + }, + }; #[test] fn id_test() { @@ -177,7 +182,7 @@ mod tests { let g = Group::cyclic(10); let stab = g.stabchain(); - let base = g.generators().get(0).cloned().unwrap(); + let base = g.generators().first().cloned().unwrap(); for i in 0..10 { assert!(is_in_group(stab.iter(), &base.pow(i))) } @@ -185,8 +190,10 @@ mod tests { #[test] fn book_example() { - use super::super::base::selectors::FixedBaseSelector; - use crate::perm::export::CyclePermutation; + use { + super::super::base::selectors::FixedBaseSelector, + crate::perm::export::CyclePermutation, + }; let g = Group::new(&[ CyclePermutation::single_cycle(&[1, 2, 3]).into(), @@ -195,8 +202,7 @@ mod tests { let chain = g.stabchain_with_selector(FixedBaseSelector::new(&[0, 1])); - let perm: DefaultPermutation = - CyclePermutation::from_vec(vec![vec![1, 2], vec![3, 4]]).into(); + let perm: DefaultPermutation = CyclePermutation::from_vec(vec![vec![1, 2], vec![3, 4]]).into(); assert!(is_in_group(chain.iter(), &perm)); } @@ -218,8 +224,10 @@ mod tests { #[test] fn book_example_complete_test() { - use super::super::base::selectors::FixedBaseSelector; - use crate::perm::export::CyclePermutation; + use { + super::super::base::selectors::FixedBaseSelector, + crate::perm::export::CyclePermutation, + }; let g = Group::::new(&[ CyclePermutation::single_cycle(&[1, 2, 3]).into(), @@ -299,10 +307,7 @@ mod tests { let repr = coset_representative(stab.iter(), &DefaultPermutation::id()); assert!(repr.is_some()); assert_eq!(repr.unwrap().len(), 0); - assert!( - coset_representative(stab.iter(), &DefaultPermutation::from_images(&[1, 2, 0])) - .is_none() - ); + assert!(coset_representative(stab.iter(), &DefaultPermutation::from_images(&[1, 2, 0])).is_none()); } #[test] @@ -317,8 +322,7 @@ mod tests { let mut repr = repr.unwrap(); assert_eq!(repr.len(), stab.len()); let mut acc = DefaultPermutation::id(); - while !repr.is_empty() { - let elem = repr.pop().unwrap(); + while let Some(elem) = repr.pop() { acc = acc.multiply(&elem); } assert_eq!(acc, perm); diff --git a/src/group/stabchain/mod.rs b/src/group/stabchain/mod.rs index be5c84c8726..9fdd18619da 100644 --- a/src/group/stabchain/mod.rs +++ b/src/group/stabchain/mod.rs @@ -5,13 +5,28 @@ pub mod base_change_builder; pub mod builder; pub mod element_testing; -use crate::group::Group; -use crate::perm::actions::SimpleApplication; -use crate::perm::*; -use crate::{group::orbit::abstraction::TransversalResolver, perm::impls::word::WordPermutation}; -use base::Base; -use base_change_builder::{BaseChangeBuilder, BaseChangeBuilderStrategy}; -use builder::{Builder, BuilderStrategy}; +use { + crate::{ + group::{ + orbit::abstraction::TransversalResolver, + Group, + }, + perm::{ + actions::SimpleApplication, + impls::word::WordPermutation, + *, + }, + }, + base::Base, + base_change_builder::{ + BaseChangeBuilder, + BaseChangeBuilderStrategy, + }, + builder::{ + Builder, + BuilderStrategy, + }, +}; use crate::DetHashMap; @@ -88,10 +103,7 @@ where /// Get the base corresponding to this stabilizer chain pub fn base(&self) -> Base { - Base::new_with_action( - self.chain.iter().map(|g| &g.base).cloned().collect(), - A::default(), - ) + Base::new_with_action(self.chain.iter().map(|g| &g.base).cloned().collect(), A::default()) } /// Get the strong generating set of this stabiliser chain. @@ -132,12 +144,7 @@ where ) -> Stabchain, A> where B: BaseChangeBuilder, A>, - S: BaseChangeBuilderStrategy< - P, - Action = A, - Transversal = FactoredTransversalResolver, - BuilderT = B, - >, + S: BaseChangeBuilderStrategy, BuilderT = B>, { let mut builder = build_strategy.make_builder(); builder.set_base(self, base); @@ -170,9 +177,7 @@ where //Skeleton of the chain. let mut chain: Vec, A>> = base .iter() - .map(|point| { - StabchainRecord::new(point.clone(), Group::new(&[]), DetHashMap::default()) - }) + .map(|point| StabchainRecord::new(point.clone(), Group::new(&[]), DetHashMap::default())) .collect(); //Add the generators in the correct location, from back to front. for p in sgs { @@ -191,10 +196,9 @@ where } //Now fill in the transversal chain.iter_mut().for_each(|record| { - record.transversal = - factored_transversal_complete_opt(record.group(), record.base.clone(), &strat) + record.transversal = factored_transversal_complete_opt(record.group(), record.base.clone(), &strat) }); - Stabchain { chain } + Self { chain } } } @@ -247,12 +251,8 @@ where A: Action

, V: TransversalResolver, { - pub(crate) fn new( - base: A::OrbitT, - gens: Group

, - transversal: DetHashMap, - ) -> Self { - StabchainRecord { + pub(crate) fn new(base: A::OrbitT, gens: Group

, transversal: DetHashMap) -> Self { + Self { base, gens, transversal, @@ -262,7 +262,7 @@ where } ///Create a trivial record that represents the trivial group. pub(crate) fn trivial_record(base: A::OrbitT) -> Self { - StabchainRecord { + Self { base: base.clone(), gens: Group::new(&[]), transversal: [(base, P::id())].iter().cloned().collect(), @@ -283,8 +283,10 @@ where } } -use std::cell::RefCell; -use std::fmt; +use std::{ + cell::RefCell, + fmt, +}; impl fmt::Display for Stabchain where @@ -312,11 +314,16 @@ where } } -use super::orbit::{ - abstraction::FactoredTransversalResolver, - transversal::factored_transversal::factored_transversal_complete_opt, +use { + super::orbit::{ + abstraction::FactoredTransversalResolver, + transversal::factored_transversal::factored_transversal_complete_opt, + }, + crate::{ + group::orbit::transversal::TransversalError, + DetHashSet, + }, }; -use crate::{group::orbit::transversal::TransversalError, DetHashSet}; #[derive(Debug)] pub enum StabchainError { @@ -351,7 +358,10 @@ where A: Action

, A::OrbitT: std::fmt::Debug, { - use crate::group::orbit::transversal::{valid_transversal, Transversal}; + use crate::group::orbit::transversal::{ + valid_transversal, + Transversal, + }; let applicator = A::default(); @@ -386,13 +396,24 @@ macro_rules! stabchain_tests { ($strategy:expr, $short:ident) => { #[allow(deprecated)] mod $short { - use crate::group::stabchain::builder::*; - use crate::group::stabchain::{valid_stabchain, Stabchain}; - use crate::group::Group; - use crate::perm::actions::*; - use crate::perm::export::CyclePermutation; - use crate::perm::DefaultPermutation; - use num::BigUint; + use { + crate::{ + group::{ + stabchain::{ + builder::*, + valid_stabchain, + Stabchain, + }, + Group, + }, + perm::{ + actions::*, + export::CyclePermutation, + DefaultPermutation, + }, + }, + num::BigUint, + }; #[test] fn trivial_chain() { @@ -456,13 +477,12 @@ macro_rules! stabchain_tests { #[test] fn single_non_trivial_layer() { - use crate::perm::export::CyclePermutation; - use crate::perm::DefaultPermutation; + use crate::perm::{ + export::CyclePermutation, + DefaultPermutation, + }; - let g = Group::::new(&[CyclePermutation::single_cycle(&[ - 1, 2, - ]) - .into()]); + let g = Group::::new(&[CyclePermutation::single_cycle(&[1, 2]).into()]); let chain = Stabchain::new_with_strategy(&g, $strategy(i(2))); valid_stabchain(&chain).unwrap(); } @@ -487,13 +507,7 @@ macro_rules! stabchain_tests { vec![8, 9, 12, 13], ]) .into_perm(), - CyclePermutation::from_vec(vec![ - vec![1, 5], - vec![2, 6], - vec![9, 13], - vec![10, 14], - ]) - .into_perm(), + CyclePermutation::from_vec(vec![vec![1, 5], vec![2, 6], vec![9, 13], vec![10, 14]]).into_perm(), ]); let chain = Stabchain::new_with_strategy(&g, $strategy(i(128))); valid_stabchain(&chain).unwrap(); @@ -535,11 +549,20 @@ macro_rules! known_base_tests { ($strategy:expr, $short:ident, $repeats:expr) => { #[allow(deprecated)] mod $short { - use crate::group::stabchain::base_change_builder::*; - use crate::group::stabchain::{base::Base, valid_stabchain}; - use crate::group::Group; - use crate::perm::actions::*; - use rand::seq::SliceRandom; + use { + crate::{ + group::{ + stabchain::{ + base::Base, + base_change_builder::*, + valid_stabchain, + }, + Group, + }, + perm::actions::*, + }, + rand::seq::SliceRandom, + }; #[test] fn trivial_chain() { @@ -550,8 +573,7 @@ macro_rules! known_base_tests { for _ in 0..$repeats { let mut new_base = Vec::from(base.base()); new_base.shuffle(&mut rng); - let new_chain = original_chain - .from_known_base_with_strategy(Base::new(new_base), $strategy); + let new_chain = original_chain.from_known_base_with_strategy(Base::new(new_base), $strategy); valid_stabchain(&new_chain).unwrap(); } } @@ -565,8 +587,7 @@ macro_rules! known_base_tests { for _ in 0..$repeats { let mut new_base = Vec::from(base.base()); new_base.shuffle(&mut rng); - let new_chain = original_chain - .from_known_base_with_strategy(Base::new(new_base), $strategy); + let new_chain = original_chain.from_known_base_with_strategy(Base::new(new_base), $strategy); valid_stabchain(&new_chain).unwrap(); } } @@ -580,8 +601,7 @@ macro_rules! known_base_tests { for _ in 0..$repeats { let mut new_base = Vec::from(base.base()); new_base.shuffle(&mut rng); - let new_chain = original_chain - .from_known_base_with_strategy(Base::new(new_base), $strategy); + let new_chain = original_chain.from_known_base_with_strategy(Base::new(new_base), $strategy); valid_stabchain(&new_chain).unwrap(); } } @@ -595,8 +615,7 @@ macro_rules! known_base_tests { for _ in 0..$repeats { let mut new_base = Vec::from(base.base()); new_base.shuffle(&mut rng); - let new_chain = original_chain - .from_known_base_with_strategy(Base::new(new_base), $strategy); + let new_chain = original_chain.from_known_base_with_strategy(Base::new(new_base), $strategy); valid_stabchain(&new_chain).unwrap(); } } @@ -610,8 +629,7 @@ macro_rules! known_base_tests { for _ in 0..$repeats { let mut new_base = Vec::from(base.base()); new_base.shuffle(&mut rng); - let new_chain = original_chain - .from_known_base_with_strategy(Base::new(new_base), $strategy); + let new_chain = original_chain.from_known_base_with_strategy(Base::new(new_base), $strategy); valid_stabchain(&new_chain).unwrap(); } } @@ -625,8 +643,7 @@ macro_rules! known_base_tests { for _ in 0..$repeats { let mut new_base = Vec::from(base.base()); new_base.shuffle(&mut rng); - let new_chain = original_chain - .from_known_base_with_strategy(Base::new(new_base), $strategy); + let new_chain = original_chain.from_known_base_with_strategy(Base::new(new_base), $strategy); valid_stabchain(&new_chain).unwrap(); } } @@ -640,29 +657,26 @@ macro_rules! known_base_tests { for _ in 0..$repeats { let mut new_base = Vec::from(base.base()); new_base.shuffle(&mut rng); - let new_chain = original_chain - .from_known_base_with_strategy(Base::new(new_base), $strategy); + let new_chain = original_chain.from_known_base_with_strategy(Base::new(new_base), $strategy); valid_stabchain(&new_chain).unwrap(); } } #[test] fn single_non_trivial_layer() { - use crate::perm::export::CyclePermutation; - use crate::perm::DefaultPermutation; + use crate::perm::{ + export::CyclePermutation, + DefaultPermutation, + }; - let g = Group::::new(&[CyclePermutation::single_cycle(&[ - 1, 2, - ]) - .into()]); + let g = Group::::new(&[CyclePermutation::single_cycle(&[1, 2]).into()]); let original_chain = g.stabchain(); let base = original_chain.base(); let mut rng = rand::thread_rng(); for _ in 0..$repeats { let mut new_base = Vec::from(base.base()); new_base.shuffle(&mut rng); - let new_chain = original_chain - .from_known_base_with_strategy(Base::new(new_base), $strategy); + let new_chain = original_chain.from_known_base_with_strategy(Base::new(new_base), $strategy); valid_stabchain(&new_chain).unwrap(); } } @@ -672,11 +686,20 @@ macro_rules! known_base_tests { #[cfg(test)] mod tests { - use super::valid_stabchain; - use super::*; - use crate::group::Group; - use crate::perm::actions::SimpleApplication; - use rand::{seq::SliceRandom, thread_rng}; + use { + super::{ + valid_stabchain, + *, + }, + crate::{ + group::Group, + perm::actions::SimpleApplication, + }, + rand::{ + seq::SliceRandom, + thread_rng, + }, + }; //Macro for testing the reconstruction of a group. macro_rules! reconstruction_test { @@ -690,11 +713,8 @@ mod tests { let mut sgs = chain.strong_generating_set(); //To make sure we aren't relying on the ordering of the sgs. sgs.shuffle(&mut thread_rng()); - let reconstructed_chain = Stabchain::from_base_and_strong_gen_set( - base.base(), - &sgs[..], - SimpleApplication::default(), - ); + let reconstructed_chain = + Stabchain::from_base_and_strong_gen_set(base.base(), &sgs[..], SimpleApplication::default()); assert_eq!(chain.len(), reconstructed_chain.len()); assert_eq!(base.base(), reconstructed_chain.base().base()); assert_eq!(chain.order(), reconstructed_chain.order()); @@ -722,37 +742,40 @@ mod tests { stabchain_tests!( |_g| NaiveBuilderStrategy::new( SimpleApplication::default(), - crate::group::stabchain::base::selectors::LmpSelector::default() + crate::group::stabchain::base::selectors::LmpSelector ), naive ); stabchain_tests!( |_g| IftBuilderStrategy::new( SimpleApplication::default(), - crate::group::stabchain::base::selectors::LmpSelector::default() + crate::group::stabchain::base::selectors::LmpSelector ), ift ); stabchain_tests!( |_g| { - use crate::group::stabchain::builder::random::parameters::RandomAlgoParameters; - use rand::SeedableRng; + use { + crate::group::stabchain::builder::random::parameters::RandomAlgoParameters, + rand::SeedableRng, + }; RandomBuilderStrategyNaive::new_with_params( SimpleApplication::default(), - crate::group::stabchain::base::selectors::FmpSelector::default(), - RandomAlgoParameters::default() - .rng(rand_xorshift::XorShiftRng::from_seed([58; 16])), + crate::group::stabchain::base::selectors::FmpSelector, + RandomAlgoParameters::default().rng(rand_xorshift::XorShiftRng::from_seed([58; 16])), ) }, random ); stabchain_tests!( |g| { - use crate::group::stabchain::builder::random::parameters::RandomAlgoParameters; - use rand::SeedableRng; + use { + crate::group::stabchain::builder::random::parameters::RandomAlgoParameters, + rand::SeedableRng, + }; RandomBuilderStrategyNaive::new_with_params( SimpleApplication::default(), - crate::group::stabchain::base::selectors::FmpSelector::default(), + crate::group::stabchain::base::selectors::FmpSelector, RandomAlgoParameters::default() .rng(rand_xorshift::XorShiftRng::from_seed([58; 16])) .order(g), @@ -762,11 +785,13 @@ mod tests { ); stabchain_tests!( |_g| { - use crate::group::stabchain::builder::random::parameters::RandomAlgoParameters; - use rand::SeedableRng; + use { + crate::group::stabchain::builder::random::parameters::RandomAlgoParameters, + rand::SeedableRng, + }; RandomBuilderStrategyNaive::new_with_params( SimpleApplication::default(), - crate::group::stabchain::base::selectors::FmpSelector::default(), + crate::group::stabchain::base::selectors::FmpSelector, RandomAlgoParameters::default() .rng(rand_xorshift::XorShiftRng::from_seed([33; 16])) .quick_test(true), @@ -776,24 +801,27 @@ mod tests { ); stabchain_tests!( |_g| { - use crate::group::stabchain::builder::random::parameters::RandomAlgoParameters; - use rand::SeedableRng; + use { + crate::group::stabchain::builder::random::parameters::RandomAlgoParameters, + rand::SeedableRng, + }; RandomBuilderStrategyShallow::new_with_params( SimpleApplication::default(), - crate::group::stabchain::base::selectors::FmpSelector::default(), - RandomAlgoParameters::default() - .rng(rand_xorshift::XorShiftRng::from_seed([52; 16])), + crate::group::stabchain::base::selectors::FmpSelector, + RandomAlgoParameters::default().rng(rand_xorshift::XorShiftRng::from_seed([52; 16])), ) }, random_shallow ); stabchain_tests!( |_g| { - use crate::group::stabchain::builder::random::parameters::RandomAlgoParameters; - use rand::SeedableRng; + use { + crate::group::stabchain::builder::random::parameters::RandomAlgoParameters, + rand::SeedableRng, + }; RandomBuilderStrategyShallow::new_with_params( SimpleApplication::default(), - crate::group::stabchain::base::selectors::FmpSelector::default(), + crate::group::stabchain::base::selectors::FmpSelector, RandomAlgoParameters::default() .rng(rand_xorshift::XorShiftRng::from_seed([42; 16])) .quick_test(true), diff --git a/src/group/utils.rs b/src/group/utils.rs index f4255671822..0e2e6c92e15 100644 --- a/src/group/utils.rs +++ b/src/group/utils.rs @@ -1,10 +1,16 @@ //! Group utilities which I was not sure where to place -use super::Group; -use crate::perm::impls::word::WordPermutation; -use crate::perm::Permutation; -use rand::seq::SliceRandom; -use rand::Rng; +use { + super::Group, + crate::perm::{ + impls::word::WordPermutation, + Permutation, + }, + rand::{ + seq::SliceRandom, + Rng, + }, +}; /// Creates a group generated from n copies of the cyclic group pub fn copies_of_cyclic(specification: &[usize]) -> Group { @@ -31,14 +37,13 @@ where P: Permutation, R: Rng, { - gens.choose_multiple(rng, k) - .fold(Permutation::id(), |accum, elem| { - if rng.gen::() { - accum - } else { - accum.multiply(elem) - } - }) + gens.choose_multiple(rng, k).fold(Permutation::id(), |accum, elem| { + if rng.gen::() { + accum + } else { + accum.multiply(elem) + } + }) } /// Generate a word representation of a random subproduct of the given generators. @@ -65,10 +70,14 @@ where #[cfg(test)] mod tests { - use super::*; - use crate::perm::export::CyclePermutation; - use crate::perm::impls::standard::StandardPermutation; - use rand::thread_rng; + use { + super::*, + crate::perm::{ + export::CyclePermutation, + impls::standard::StandardPermutation, + }, + rand::thread_rng, + }; #[test] fn test_generator_len() { diff --git a/src/lib.rs b/src/lib.rs index 90d7a16b727..cca52977d79 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,9 +1,16 @@ pub mod group; pub mod perm; -use std::collections::hash_map::{DefaultHasher, HashMap}; -use std::collections::HashSet; -use std::hash::BuildHasherDefault; +use std::{ + collections::{ + hash_map::{ + DefaultHasher, + HashMap, + }, + HashSet, + }, + hash::BuildHasherDefault, +}; /// A type of HashMap that uses a determined seed pub type DetHashMap = HashMap>; diff --git a/src/perm/actions.rs b/src/perm/actions.rs index b4c1fefe80a..73a173e3644 100644 --- a/src/perm/actions.rs +++ b/src/perm/actions.rs @@ -6,7 +6,7 @@ pub struct SimpleApplication

(std::marker::PhantomData

); impl

Default for SimpleApplication

{ fn default() -> Self { - SimpleApplication(std::marker::PhantomData::default()) + Self(std::marker::PhantomData) } } @@ -34,7 +34,7 @@ pub struct ConjugationAction

(std::marker::PhantomData

); impl

Default for ConjugationAction

{ fn default() -> Self { - Self(std::marker::PhantomData::default()) + Self(std::marker::PhantomData) } } @@ -55,7 +55,7 @@ pub struct MultiplicationAction

(std::marker::PhantomData

); impl

Default for MultiplicationAction

{ fn default() -> Self { - Self(std::marker::PhantomData::default()) + Self(std::marker::PhantomData) } } @@ -77,9 +77,13 @@ mod tests { ($id:ty, $testing:expr, $name:ident) => { mod $name { - use super::super::*; - use crate::perm::utils::random_permutation; - use crate::perm::DefaultPermutation; + use { + super::super::*, + crate::perm::{ + utils::random_permutation, + DefaultPermutation, + }, + }; #[test] fn test_identity() { diff --git a/src/perm/algos.rs b/src/perm/algos.rs index 72983c62563..616e8f79b6a 100644 --- a/src/perm/algos.rs +++ b/src/perm/algos.rs @@ -1,5 +1,7 @@ -use super::impls::standard::StandardPermutation; -use crate::perm::Permutation; +use { + super::impls::standard::StandardPermutation, + crate::perm::Permutation, +}; /// The implementation of inverse, to be used mostly for benchmarking pub fn inv(p: &StandardPermutation) -> StandardPermutation { diff --git a/src/perm/builder/join.rs b/src/perm/builder/join.rs index 691ff177183..b759f61186d 100644 --- a/src/perm/builder/join.rs +++ b/src/perm/builder/join.rs @@ -1,6 +1,8 @@ -use super::PermBuilder; -use crate::perm::Permutation; -use std::iter::FromIterator; +use { + super::PermBuilder, + crate::perm::Permutation, + std::iter::FromIterator, +}; #[derive(Debug, Clone)] pub struct Join { @@ -39,7 +41,7 @@ pub struct MultiJoin

{ impl

FromIterator

for MultiJoin

{ fn from_iter>(iter: T) -> Self { - MultiJoin { + Self { args: iter.into_iter().collect(), } } @@ -66,16 +68,18 @@ impl PermBuilder

for MultiJoin

{ #[cfg(test)] mod tests { - use super::*; - use crate::perm::{builder::PermBuilder, DefaultPermutation}; + use { + super::*, + crate::perm::{ + builder::PermBuilder, + DefaultPermutation, + }, + }; #[test] fn test_single_join() { let cycle = DefaultPermutation::from_images(&[1, 2, 0]); - assert_eq!( - cycle.multiply(&cycle), - cycle.build_multiply(&cycle).collapse() - ) + assert_eq!(cycle.multiply(&cycle), cycle.build_multiply(&cycle).collapse()) } #[test] diff --git a/src/perm/builder/mod.rs b/src/perm/builder/mod.rs index fd33be82043..823db8de2d6 100644 --- a/src/perm/builder/mod.rs +++ b/src/perm/builder/mod.rs @@ -1,9 +1,11 @@ pub mod join; pub mod pow; -use crate::perm::Permutation; -use join::Join; -use pow::Pow; +use { + crate::perm::Permutation, + join::Join, + pow::Pow, +}; pub trait PermBuilder: Clone { /// Computes f(x) diff --git a/src/perm/builder/pow.rs b/src/perm/builder/pow.rs index 32d84bfe40b..e19dd08db3c 100644 --- a/src/perm/builder/pow.rs +++ b/src/perm/builder/pow.rs @@ -1,5 +1,7 @@ -use super::PermBuilder; -use crate::perm::Permutation; +use { + super::PermBuilder, + crate::perm::Permutation, +}; #[derive(Debug, Clone)] pub struct Pow { @@ -9,7 +11,7 @@ pub struct Pow { impl Pow { pub(crate) fn new(perm: Perm, power: isize) -> Self { - Pow { perm, power } + Self { perm, power } } // TODO: This is not really the conjugate I just wanted a nice name @@ -74,8 +76,14 @@ pub fn pow(perm: P, n: usize) -> P { #[cfg(test)] mod tests { - use crate::perm::{builder::PermBuilder, DefaultPermutation, Permutation}; - use std::iter::FromIterator; + use { + crate::perm::{ + builder::PermBuilder, + DefaultPermutation, + Permutation, + }, + std::iter::FromIterator, + }; #[test] fn simple_exponentiation() { let perm = DefaultPermutation::from_images(&[1, 2, 3, 4, 5, 0]); @@ -114,7 +122,7 @@ mod tests { use crate::perm::builder::join::MultiJoin; let perm = DefaultPermutation::from_images(&[1, 3, 2, 4, 5, 0]); let lazy_pow = perm.build_pow(4); - let lazy_mult = MultiJoin::from_iter(std::iter::repeat(perm.clone()).take(4)); + let lazy_mult = MultiJoin::from_iter(std::iter::repeat_n(perm.clone(), 4)); let full = perm.multiply(&perm).multiply(&perm).multiply(&perm); for i in 0..5 { @@ -129,7 +137,7 @@ mod tests { let perm_inv = DefaultPermutation::from_images(&[1, 3, 2, 4, 5, 0]); let perm = perm_inv.inv(); let lazy_pow = perm_inv.build_pow(-4); - let lazy_mult = MultiJoin::from_iter(std::iter::repeat(perm.clone()).take(4)); + let lazy_mult = MultiJoin::from_iter(std::iter::repeat_n(perm.clone(), 4)); let full = perm.multiply(&perm).multiply(&perm).multiply(&perm); for i in 0..5 { diff --git a/src/perm/export/classic.rs b/src/perm/export/classic.rs index 43305385cfa..1822e92e251 100644 --- a/src/perm/export/classic.rs +++ b/src/perm/export/classic.rs @@ -1,5 +1,10 @@ -use super::cycles::CyclePermutation; -use crate::perm::{impls::standard::StandardPermutation, Permutation}; +use { + super::cycles::CyclePermutation, + crate::perm::{ + impls::standard::StandardPermutation, + Permutation, + }, +}; /// A permutation, that is on the integral set [1, n]. /// It is called classical as classically this is how permutations are stored @@ -9,7 +14,7 @@ pub struct ClassicalPermutation(StandardPermutation); impl ClassicalPermutation { /// Get a identity permutation pub fn id() -> Self { - ClassicalPermutation(StandardPermutation::id()) + Self(StandardPermutation::id()) } /// Is this permutation the identity? @@ -28,7 +33,7 @@ impl ClassicalPermutation { /// range [1, n]. Panics otherwise pub fn from_slice(images: &[usize]) -> Self { assert!(images.iter().all(|&x| x != 0)); - ClassicalPermutation(StandardPermutation::from_images( + Self(StandardPermutation::from_images( &images.iter().map(|i| i - 1).collect::>()[..], )) } @@ -49,7 +54,7 @@ impl From for ClassicalPermutation { let n = cycles.iter().flatten().max().cloned().unwrap_or(0); if n == 0 { - return ClassicalPermutation::id(); + return Self::id(); } let mut images = Vec::with_capacity(n); @@ -68,7 +73,7 @@ impl From for ClassicalPermutation { images.push(cycle[(i_index + 1) % cycle.len()]); } - ClassicalPermutation::from_slice(&images[..]) + Self::from_slice(&images[..]) } } @@ -77,7 +82,7 @@ where P: Permutation, { fn from(p: P) -> Self { - ClassicalPermutation(StandardPermutation::from_images(&p.images()[..])) + Self(StandardPermutation::from_images(&p.images()[..])) } } @@ -104,15 +109,13 @@ macro_rules! impl_all { } use crate::perm::impls::{ - based::BasedPermutation, map::MapPermutation, sync::SyncPermutation, word::WordPermutation, + based::BasedPermutation, + map::MapPermutation, + sync::SyncPermutation, + word::WordPermutation, }; -impl_all!( - BasedPermutation, - MapPermutation, - SyncPermutation, - WordPermutation -); +impl_all!(BasedPermutation, MapPermutation, SyncPermutation, WordPermutation); #[cfg(test)] mod tests { @@ -127,14 +130,14 @@ mod tests { #[test] fn non_conventional_id() { - let id = ClassicalPermutation::from_slice(&vec![1, 2, 3, 4, 5, 6]); + let id = ClassicalPermutation::from_slice(&[1, 2, 3, 4, 5, 6]); assert!(id.is_id()); assert!(id.images().is_empty()); } #[test] fn from_vector() { - let perm = ClassicalPermutation::from_slice(&vec![1, 3, 4, 2, 5, 6]); + let perm = ClassicalPermutation::from_slice(&[1, 3, 4, 2, 5, 6]); assert!(!perm.is_id()); assert_eq!(perm.images(), vec![1, 3, 4, 2]); } @@ -142,12 +145,12 @@ mod tests { #[test] #[should_panic] fn from_invalid_vector() { - let _perm = ClassicalPermutation::from_slice(&vec![1, 3, 4, 2, 0]); + let _perm = ClassicalPermutation::from_slice(&[1, 3, 4, 2, 0]); } #[test] fn application() { - let perm = ClassicalPermutation::from_slice(&vec![1, 3, 4, 2]); + let perm = ClassicalPermutation::from_slice(&[1, 3, 4, 2]); assert_eq!(perm.apply(1), 1); assert_eq!(perm.apply(2), 3); assert_eq!(perm.apply(3), 4); @@ -158,7 +161,7 @@ mod tests { #[test] #[should_panic] fn invalid_application() { - let perm = ClassicalPermutation::from_slice(&vec![1, 3, 4, 2]); + let perm = ClassicalPermutation::from_slice(&[1, 3, 4, 2]); perm.apply(0); } @@ -171,7 +174,7 @@ mod tests { #[test] fn to_permutation() { - let classic = ClassicalPermutation::from_slice(&vec![1, 3, 2]); + let classic = ClassicalPermutation::from_slice(&[1, 3, 2]); let basic: StandardPermutation = classic.into(); assert_eq!(basic.as_vec(), &vec![0, 2, 1][..]); } diff --git a/src/perm/export/cycles.rs b/src/perm/export/cycles.rs index 5c0a3e131a6..3567b2faff4 100644 --- a/src/perm/export/cycles.rs +++ b/src/perm/export/cycles.rs @@ -1,6 +1,11 @@ -use super::ClassicalPermutation; -use crate::perm::Permutation; -use serde::{Deserialize, Serialize}; +use { + super::ClassicalPermutation, + crate::perm::Permutation, + serde::{ + Deserialize, + Serialize, + }, +}; use std::fmt; @@ -14,7 +19,7 @@ pub struct CyclePermutation { impl CyclePermutation { pub fn id() -> Self { - CyclePermutation::from_vec(Vec::new()) + Self::from_vec(Vec::new()) } /// Take some images in the 1..=n range and output a cycled repr @@ -34,7 +39,7 @@ impl CyclePermutation { let n = cycles.iter().flatten().max().cloned().unwrap_or(0); if n == 0 { - return CyclePermutation::from_vec_unchecked(cycles); + return Self::from_vec_unchecked(cycles); } let mut counts = DetHashMap::default(); @@ -46,7 +51,7 @@ impl CyclePermutation { // Check every element occurs at most once assert!(counts.values().all(|&i| i <= 1)); - CyclePermutation::from_vec_unchecked(cycles) + Self::from_vec_unchecked(cycles) } /// Get the order of the permutations @@ -56,11 +61,11 @@ impl CyclePermutation { /// Been needing this for a while. (1 2 3) pub fn single_cycle(cycle: &[usize]) -> Self { - Self::from_vec(vec![cycle.iter().copied().collect()]) + Self::from_vec(vec![cycle.to_vec()]) } fn from_vec_unchecked(v: Vec>) -> Self { - CyclePermutation { cycles: v } + Self { cycles: v } } pub fn cycles(&self) -> &[Vec] { @@ -78,7 +83,7 @@ where P: Permutation, { fn from(perm: P) -> Self { - CyclePermutation::from(ClassicalPermutation::from(perm)) + Self::from(ClassicalPermutation::from(perm)) } } @@ -108,7 +113,7 @@ impl From for CyclePermutation { let n = perm.lmp(); // This path means that the permutation is the identity if n.is_none() { - return CyclePermutation::from_vec_unchecked(Vec::new()); + return Self::from_vec_unchecked(Vec::new()); } let n = n.unwrap(); @@ -140,7 +145,7 @@ impl From for CyclePermutation { } } - CyclePermutation::from_vec_unchecked(cycles) + Self::from_vec_unchecked(cycles) } } @@ -162,8 +167,11 @@ macro_rules! impl_all { } use crate::perm::impls::{ - based::BasedPermutation, map::MapPermutation, standard::StandardPermutation, - sync::SyncPermutation, word::WordPermutation, + based::BasedPermutation, + map::MapPermutation, + standard::StandardPermutation, + sync::SyncPermutation, + word::WordPermutation, }; impl_all!( @@ -193,8 +201,7 @@ mod tests { #[test] fn cyclic_perm() { - let perm: CyclePermutation = - ClassicalPermutation::from_slice(&[4, 5, 7, 6, 8, 2, 1, 3]).into(); + let perm: CyclePermutation = ClassicalPermutation::from_slice(&[4, 5, 7, 6, 8, 2, 1, 3]).into(); assert_eq!(perm.cycles().len(), 1); assert_eq!(perm.cycles, vec![vec![1, 4, 6, 2, 5, 8, 3, 7]]) } @@ -238,8 +245,7 @@ mod tests { #[test] fn cyclical_to_classical_multiple_cycles() { - let cyclic: ClassicalPermutation = - CyclePermutation::from_vec(vec![vec![1, 3], vec![2, 4]]).into(); + let cyclic: ClassicalPermutation = CyclePermutation::from_vec(vec![vec![1, 3], vec![2, 4]]).into(); let classic = ClassicalPermutation::from_slice(&[3, 4, 1, 2]); assert_eq!(cyclic, classic); } diff --git a/src/perm/export/mod.rs b/src/perm/export/mod.rs index 4983a386ad7..2a2d1601fb0 100644 --- a/src/perm/export/mod.rs +++ b/src/perm/export/mod.rs @@ -1,10 +1,15 @@ mod classic; mod cycles; -use serde::{Deserialize, Serialize}; +use serde::{ + Deserialize, + Serialize, +}; -pub use classic::ClassicalPermutation; -pub use cycles::CyclePermutation; +pub use { + classic::ClassicalPermutation, + cycles::CyclePermutation, +}; use crate::perm::Permutation; @@ -23,7 +28,7 @@ where impl From for ExportablePermutation { fn from(perm: ClassicalPermutation) -> Self { - ExportablePermutation(perm.images()) + Self(perm.images()) } } @@ -45,8 +50,11 @@ macro_rules! impl_all { } use super::impls::{ - based::BasedPermutation, map::MapPermutation, standard::StandardPermutation, - sync::SyncPermutation, word::WordPermutation, + based::BasedPermutation, + map::MapPermutation, + standard::StandardPermutation, + sync::SyncPermutation, + word::WordPermutation, }; impl_all!( diff --git a/src/perm/impls/based.rs b/src/perm/impls/based.rs index 5139aff0bcc..35b2638ebbf 100644 --- a/src/perm/impls/based.rs +++ b/src/perm/impls/based.rs @@ -1,5 +1,7 @@ -use crate::perm::impls::standard::StandardPermutation; -use crate::perm::Permutation; +use crate::perm::{ + impls::standard::StandardPermutation, + Permutation, +}; #[derive(Debug, Clone, Eq)] pub struct BasedPermutation { @@ -18,7 +20,7 @@ impl BasedPermutation { let perm = StandardPermutation::from_vec_unchecked(values); if perm.is_id() { - return BasedPermutation::id(); + return Self::id(); } Self { base, perm } @@ -27,7 +29,7 @@ impl BasedPermutation { impl Permutation for BasedPermutation { fn id() -> Self { - BasedPermutation { + Self { base: 0, perm: Permutation::id(), } @@ -38,7 +40,7 @@ impl Permutation for BasedPermutation { return self.clone(); } - BasedPermutation { + Self { base: self.base + k, perm: self.perm.clone(), } @@ -58,51 +60,46 @@ impl Permutation for BasedPermutation { fn from_images(images: &[usize]) -> Self { crate::perm::utils::valid_images(images).unwrap(); - BasedPermutation::from_vec_unchecked(images) + Self::from_vec_unchecked(images) } fn inv(&self) -> Self { - BasedPermutation { + Self { perm: self.perm.inv(), base: self.base, } } - fn multiply(&self, other: &BasedPermutation) -> Self { + fn multiply(&self, other: &Self) -> Self { let result = if self.is_id() { other.clone() } else if other.is_id() { self.clone() } else if self.base == other.base { - BasedPermutation { + Self { perm: self.perm.multiply(&other.perm), base: self.base, } } else if self.base < other.base { - BasedPermutation { + Self { base: self.base, - perm: self - .perm - .multiply(&other.perm.shift(other.base - self.base)), + perm: self.perm.multiply(&other.perm.shift(other.base - self.base)), } } else { - BasedPermutation { + Self { base: other.base, - perm: self - .perm - .shift(self.base - other.base) - .multiply(&other.perm), + perm: self.perm.shift(self.base - other.base).multiply(&other.perm), } }; if result.perm.is_id() { - return BasedPermutation::id(); + return Self::id(); } let perm_images = result.perm.as_vec(); let new_based = Self::from_images(perm_images); - BasedPermutation { + Self { base: result.base + new_based.base, perm: new_based.perm, } @@ -111,12 +108,9 @@ impl Permutation for BasedPermutation { fn pow(&self, pow: isize) -> Self { let perm = self.perm.pow(pow); if perm.is_id() { - BasedPermutation::id() + Self::id() } else { - BasedPermutation { - perm, - base: self.base, - } + Self { perm, base: self.base } } } @@ -125,7 +119,7 @@ impl Permutation for BasedPermutation { } /// Computes f * g^-1 - fn divide(&self, other: &BasedPermutation) -> Self { + fn divide(&self, other: &Self) -> Self { self.multiply(&other.inv()) } diff --git a/src/perm/impls/map.rs b/src/perm/impls/map.rs index ab182a84b8c..bf4d9f4fd48 100644 --- a/src/perm/impls/map.rs +++ b/src/perm/impls/map.rs @@ -1,8 +1,10 @@ use crate::perm::Permutation; // BTree is used since it supports hash -use std::collections::BTreeMap; -use std::iter::FromIterator; -use std::rc::Rc; +use std::{ + collections::BTreeMap, + iter::FromIterator, + rc::Rc, +}; #[derive(Debug, Clone, Hash, PartialEq, Eq)] pub struct MapPermutation { @@ -16,18 +18,13 @@ impl MapPermutation { } fn from_vec_unchecked(images: &[usize]) -> Self { - images - .iter() - .copied() - .enumerate() - .filter(|(i, o)| i != o) - .collect() + images.iter().copied().enumerate().filter(|(i, o)| i != o).collect() } } impl Permutation for MapPermutation { fn id() -> Self { - MapPermutation { + Self { images: Rc::new(BTreeMap::new()), } } @@ -60,10 +57,7 @@ impl Permutation for MapPermutation { .filter(|(i, _)| !self.images.contains_key(*i)) .map(|(&i, &o)| (i, o)); - first_changes - .chain(second_changes) - .filter(|(i, o)| i != o) - .collect() + first_changes.chain(second_changes).filter(|(i, o)| i != o).collect() } fn inv(&self) -> Self { @@ -75,16 +69,13 @@ impl Permutation for MapPermutation { } fn shift(&self, pos: usize) -> Self { - self.images - .iter() - .map(|(i, o)| (i + pos, o + pos)) - .collect() + self.images.iter().map(|(i, o)| (i + pos, o + pos)).collect() } } impl FromIterator<(usize, usize)> for MapPermutation { fn from_iter>(iter: T) -> Self { - MapPermutation { + Self { images: Rc::new(iter.into_iter().collect()), } } diff --git a/src/perm/impls/mod.rs b/src/perm/impls/mod.rs index f1841a0e9ad..285c34d7f92 100644 --- a/src/perm/impls/mod.rs +++ b/src/perm/impls/mod.rs @@ -126,10 +126,7 @@ macro_rules! permutation_tests { use crate::perm::builder::PermBuilder; let perm1 = <$name>::from_images(&[2, 3, 0, 1]); let perm2 = <$name>::from_images(&[2, 1, 0]); - assert_eq!( - perm1.multiply(&perm2), - perm1.build_multiply(&perm2).collapse() - ) + assert_eq!(perm1.multiply(&perm2), perm1.build_multiply(&perm2).collapse()) } /// Test inverse for the indentity. diff --git a/src/perm/impls/standard.rs b/src/perm/impls/standard.rs index bdb725718a0..4b17c7810b7 100644 --- a/src/perm/impls/standard.rs +++ b/src/perm/impls/standard.rs @@ -1,9 +1,11 @@ use crate::perm::Permutation; -use std::cell::RefCell; -use std::cmp::max; -use std::iter::FromIterator; -use std::rc::Rc; +use std::{ + cell::RefCell, + cmp::max, + iter::FromIterator, + rc::Rc, +}; /// Represents a permutation /// The vals are reference counted and stored to allow for easy copy @@ -30,7 +32,7 @@ impl StandardPermutation { pub fn from_vec(vals: Vec) -> Self { crate::perm::utils::valid_images(&vals[..]).unwrap(); - StandardPermutation::from_vec_unchecked(vals) + Self::from_vec_unchecked(vals) } pub(crate) fn from_vec_unchecked(mut vals: Vec) -> Self { @@ -71,10 +73,7 @@ impl Permutation for StandardPermutation { fn inv(&self) -> Self { if self.invvals.borrow().is_some() { - return StandardPermutation::make_inverse( - self.vals.clone(), - self.invvals.borrow().clone().unwrap(), - ); + return Self::make_inverse(self.vals.clone(), self.invvals.borrow().clone().unwrap()); } let v = crate::perm::algos::inv_unchecked(&self.vals[..]); @@ -83,10 +82,10 @@ impl Permutation for StandardPermutation { *self.invvals.borrow_mut() = Some(ptr.clone()); - StandardPermutation::make_inverse(self.vals.clone(), ptr) + Self::make_inverse(self.vals.clone(), ptr) } - fn multiply(&self, other: &StandardPermutation) -> Self { + fn multiply(&self, other: &Self) -> Self { // id * g = g if self.is_id() { other.clone() @@ -113,13 +112,11 @@ impl Permutation for StandardPermutation { result } else { // Otherwise we can skip bounds checking for self - (0..self_size + 1) - .map(|x| other.apply(self.vals[x])) - .collect() + (0..self_size + 1).map(|x| other.apply(self.vals[x])).collect() }; // TODO check for premultiplying inverses if both exist debug_assert!(v.len() == max(self_size, other_size) + 1); - StandardPermutation::from_vec_unchecked(v) + Self::from_vec_unchecked(v) } } @@ -133,13 +130,13 @@ impl Permutation for StandardPermutation { fn shift(&self, k: usize) -> Self { if self.is_id() { - return StandardPermutation::id(); + return Self::id(); } let mut images: Vec<_> = (0..k).collect(); let new_images = self.vals.iter().map(|i| i + k); images.extend(new_images); - StandardPermutation::from_vec_unchecked(images) + Self::from_vec_unchecked(images) } } @@ -163,12 +160,12 @@ impl std::hash::Hash for StandardPermutation { impl From> for StandardPermutation { fn from(v: Vec) -> Self { - StandardPermutation::from_vec(v) + Self::from_vec(v) } } impl FromIterator for StandardPermutation { fn from_iter>(iter: T) -> Self { - StandardPermutation::from_vec(iter.into_iter().collect()) + Self::from_vec(iter.into_iter().collect()) } } diff --git a/src/perm/impls/sync.rs b/src/perm/impls/sync.rs index 72052105089..941525f89e8 100644 --- a/src/perm/impls/sync.rs +++ b/src/perm/impls/sync.rs @@ -1,7 +1,9 @@ use crate::perm::Permutation; -use std::iter::FromIterator; -use std::sync::Arc; +use std::{ + iter::FromIterator, + sync::Arc, +}; use super::standard::StandardPermutation; @@ -19,7 +21,7 @@ impl SyncPermutation { pub fn from_vec(vals: Vec) -> Self { crate::perm::utils::valid_images(&vals[..]).unwrap(); - SyncPermutation::from_vec_unchecked(vals) + Self::from_vec_unchecked(vals) } pub(crate) fn from_vec_unchecked(mut vals: Vec) -> Self { @@ -67,7 +69,7 @@ impl Permutation for SyncPermutation { } } - fn multiply(&self, other: &SyncPermutation) -> Self { + fn multiply(&self, other: &Self) -> Self { if self.is_id() { other.clone() } else if other.is_id() { @@ -91,11 +93,9 @@ impl Permutation for SyncPermutation { result } else { // Otherwise we can skip bounds checking for self - (0..self_size + 1) - .map(|x| other.apply(self.vals[x])) - .collect() + (0..self_size + 1).map(|x| other.apply(self.vals[x])).collect() }; - SyncPermutation::from_vec_unchecked(v) + Self::from_vec_unchecked(v) } } @@ -109,13 +109,13 @@ impl Permutation for SyncPermutation { fn shift(&self, k: usize) -> Self { if self.is_id() { - return SyncPermutation::id(); + return Self::id(); } let mut images: Vec<_> = (0..k).collect(); let new_images = self.vals.iter().map(|i| i + k); images.extend(new_images); - SyncPermutation::from_vec_unchecked(images) + Self::from_vec_unchecked(images) } } @@ -144,7 +144,7 @@ impl From for SyncPermutation { let vals = p.images(); let invvals = p.inv().images(); - SyncPermutation { + Self { vals: vals.into(), invvals: invvals.into(), } @@ -155,12 +155,12 @@ impl From for StandardPermutation { fn from(p: SyncPermutation) -> Self { let vals = p.vals.to_vec().into(); let invvals = p.invvals.to_vec().into(); - StandardPermutation::make_inverse(vals, invvals) + Self::make_inverse(vals, invvals) } } impl FromIterator for SyncPermutation { fn from_iter>(iter: T) -> Self { - SyncPermutation::from_vec(iter.into_iter().collect()) + Self::from_vec(iter.into_iter().collect()) } } diff --git a/src/perm/impls/word.rs b/src/perm/impls/word.rs index 4906ad4cb6a..a22e44c7d6f 100644 --- a/src/perm/impls/word.rs +++ b/src/perm/impls/word.rs @@ -1,5 +1,10 @@ -use crate::perm::*; -use std::iter::{self, FromIterator}; +use { + crate::perm::*, + std::iter::{ + self, + FromIterator, + }, +}; #[derive(Debug, Clone, Eq)] pub struct WordPermutation

@@ -15,7 +20,7 @@ where { /// Custom initialiser that can take a vector capacity. pub(crate) fn id_with_capacity(capacity: usize) -> Self { - WordPermutation { + Self { word: Vec::with_capacity(capacity), } } @@ -61,7 +66,7 @@ where /// Lazily evaluate the inverse of the permutation, using the identify (ab)^-1 = b^-1a^-1 pub fn inv_lazy(&self) -> Self { // We know each word is not the identity, so it's inverse isn't either. - WordPermutation { + Self { word: self.word.iter().map(|p| p.inv()).rev().collect(), } } @@ -75,8 +80,7 @@ where /// Multiply in place by another word. pub fn multiply_mut_word(&mut self, other: &Self) { - self.word - .extend(other.word.iter().filter(|p| !p.is_id()).cloned()); + self.word.extend(other.word.iter().filter(|p| !p.is_id()).cloned()); } // Invert word permutation lazily in place. @@ -95,7 +99,7 @@ where P: Permutation, { fn from_iter>(iter: T) -> Self { - WordPermutation { + Self { word: iter.into_iter().filter(|p| !p.is_id()).collect(), } } @@ -221,19 +225,18 @@ where #[cfg(test)] mod tests { - use super::*; - use crate::perm::{DefaultPermutation, Permutation}; + use { + super::*, + crate::perm::{ + DefaultPermutation, + Permutation, + }, + }; #[test] fn inv_lazy() { - let images = vec![ - vec![0, 2, 1], - vec![0, 1, 2, 4, 3], - vec![0, 1, 2, 3, 4, 5, 7, 6], - ]; - let perms = images - .iter() - .map(|arr| DefaultPermutation::from_images(arr)); + let images = [vec![0, 2, 1], vec![0, 1, 2, 4, 3], vec![0, 1, 2, 3, 4, 5, 7, 6]]; + let perms = images.iter().map(|arr| DefaultPermutation::from_images(arr)); let perm = WordPermutation::from_iter(perms); assert_eq!(perm.inv_lazy().evaluate(), perm.inv().evaluate()); let id = WordPermutation::::id(); @@ -249,14 +252,8 @@ mod tests { #[test] fn lmp_upper_bound() { - let images = vec![ - vec![0, 2, 1], - vec![0, 1, 2, 4, 3], - vec![0, 1, 2, 3, 4, 5, 7, 6], - ]; - let perms = images - .iter() - .map(|arr| DefaultPermutation::from_images(arr)); + let images = [vec![0, 2, 1], vec![0, 1, 2, 4, 3], vec![0, 1, 2, 3, 4, 5, 7, 6]]; + let perms = images.iter().map(|arr| DefaultPermutation::from_images(arr)); let perm = WordPermutation::from_iter(perms); assert!(perm.lmp_upper().unwrap() >= perm.lmp().unwrap()); assert!(perm.lmp_upper().unwrap() >= 7); @@ -265,10 +262,8 @@ mod tests { #[test] fn lmp_not_eq_ub() { - let images = vec![vec![0, 1, 2, 4, 3], vec![0, 1, 2, 4, 3]]; - let perms = images - .iter() - .map(|arr| DefaultPermutation::from_images(arr)); + let images = [vec![0, 1, 2, 4, 3], vec![0, 1, 2, 4, 3]]; + let perms = images.iter().map(|arr| DefaultPermutation::from_images(arr)); let perm = WordPermutation::from_iter(perms); assert!(perm.lmp_upper().unwrap() >= perm.lmp().unwrap_or(0)); assert!(perm.lmp_upper().unwrap() >= 4); diff --git a/src/perm/mod.rs b/src/perm/mod.rs index 94a3a8a9f20..8e251880670 100644 --- a/src/perm/mod.rs +++ b/src/perm/mod.rs @@ -9,8 +9,13 @@ pub mod export; pub mod impls; pub mod utils; -use std::fmt::{Debug, Display}; -use std::hash::Hash; +use std::{ + fmt::{ + Debug, + Display, + }, + hash::Hash, +}; // Very much arbitrary const ORDER_LIMIT: usize = 12; @@ -28,7 +33,7 @@ pub trait Permutation: Clone + Eq + Hash + Debug + Display { fn images(&self) -> Vec { self.lmp() .map(|n| (0..=n).map(|i| self.apply(i)).collect()) - .unwrap_or_else(Vec::new) + .unwrap_or_default() } /// Get the identity @@ -50,7 +55,7 @@ pub trait Permutation: Clone + Eq + Hash + Debug + Display { fn pow(&self, pow: isize) -> Self { let perm = if pow < 0 { self.inv() } else { self.clone() }; - builder::pow::pow(perm, pow.abs() as usize) + builder::pow::pow(perm, pow.unsigned_abs()) } /// Shift the permutation some places on the right @@ -126,16 +131,14 @@ macro_rules! impl_all { } use crate::perm::impls::{ - based::BasedPermutation, map::MapPermutation, standard::StandardPermutation, - sync::SyncPermutation, word::WordPermutation, + based::BasedPermutation, + map::MapPermutation, + standard::StandardPermutation, + sync::SyncPermutation, + word::WordPermutation, }; -impl_all!( - [StandardPermutation], - BasedPermutation, - MapPermutation, - WordPermutation, -); +impl_all!([StandardPermutation], BasedPermutation, MapPermutation, WordPermutation,); impl_all!( [BasedPermutation], @@ -153,12 +156,7 @@ impl_all!( WordPermutation, ); -impl_all!( - [SyncPermutation], - MapPermutation, - BasedPermutation, - WordPermutation, -); +impl_all!([SyncPermutation], MapPermutation, BasedPermutation, WordPermutation,); impl_all_conversions!( [WordPermutation], diff --git a/src/perm/utils.rs b/src/perm/utils.rs index bdcf2f4ac5e..c29ff135c8f 100644 --- a/src/perm/utils.rs +++ b/src/perm/utils.rs @@ -1,6 +1,10 @@ -use super::export::CyclePermutation; -use super::Permutation; -use rand::seq::SliceRandom; +use { + super::{ + export::CyclePermutation, + Permutation, + }, + rand::seq::SliceRandom, +}; use crate::perm::impls::standard::StandardPermutation; @@ -52,8 +56,10 @@ pub fn valid_images(images: &[usize]) -> Result<(), ImageError> { #[cfg(test)] mod tests { - use super::*; - use crate::perm::DefaultPermutation; + use { + super::*, + crate::perm::DefaultPermutation, + }; #[test] fn create_random() { diff --git a/tests/integration_tests.rs b/tests/integration_tests.rs index dca8ae5e80a..6bd94f0b23e 100644 --- a/tests/integration_tests.rs +++ b/tests/integration_tests.rs @@ -1,21 +1,40 @@ -use std::fs::File; -use std::io::BufReader; -use std::stringify; - -use lazy_static::lazy_static; -use rand::seq::IteratorRandom; -use rayon::prelude::*; - -use stabchain::group::group_library::DecoratedGroup; -use stabchain::group::orbit::transversal::valid_transversal; -use stabchain::group::stabchain::{correct_stabchain_order, valid_stabchain}; -use stabchain::perm::export::ExportablePermutation; -use stabchain::perm::impls::sync::SyncPermutation; - -use stabchain::group::stabchain::base::selectors::*; -use stabchain::group::stabchain::builder::random::parameters::RandomAlgoParameters; -use stabchain::group::stabchain::builder::*; -use stabchain::perm::actions::*; +use std::{ + fs::File, + io::BufReader, + stringify, +}; + +use { + lazy_static::lazy_static, + rand::seq::IteratorRandom, + rayon::prelude::*, +}; + +use stabchain::{ + group::{ + group_library::DecoratedGroup, + orbit::transversal::valid_transversal, + stabchain::{ + correct_stabchain_order, + valid_stabchain, + }, + }, + perm::{ + export::ExportablePermutation, + impls::sync::SyncPermutation, + }, +}; + +use stabchain::{ + group::stabchain::{ + base::selectors::*, + builder::{ + random::parameters::RandomAlgoParameters, + *, + }, + }, + perm::actions::*, +}; // We use this to limit the number of groups to test const DEFAULT_LIMIT: usize = 1000; @@ -41,7 +60,7 @@ fn load_libraries(zip: &str) -> Vec> { if let Some(p) = outpath.parent() { if !p.exists() { - std::fs::create_dir_all(&p).unwrap(); + std::fs::create_dir_all(p).unwrap(); } } @@ -50,17 +69,14 @@ fn load_libraries(zip: &str) -> Vec> { paths.push(outpath); } - paths.iter().map(|p| group_library(p)).flatten().collect() + paths.iter().flat_map(|p| group_library(p)).collect() } -fn group_library( - path: &std::path::Path, -) -> impl IntoIterator> { +fn group_library(path: &std::path::Path) -> impl IntoIterator> { let input = File::open(path).unwrap(); let input = BufReader::new(input); - let groups: Vec> = - serde_json::from_reader(input).unwrap(); + let groups: Vec> = serde_json::from_reader(input).unwrap(); groups.into_iter().map(|g| g.map(SyncPermutation::from)) } @@ -82,10 +98,7 @@ where let groups = if *NO_LIMIT { GROUP_LIBRARY.to_vec() } else { - GROUP_LIBRARY - .iter() - .cloned() - .choose_multiple(&mut rng, *LIMIT) + GROUP_LIBRARY.iter().cloned().choose_multiple(&mut rng, *LIMIT) }; let errors = groups @@ -97,12 +110,7 @@ where }) .collect::>(); - println!( - "[{}] {} errors out of {}", - name, - errors.len(), - number_of_tests() - ); + println!("[{}] {} errors out of {}", name, errors.len(), number_of_tests()); for (g, err) in &errors { println!("[{}] Error {:?}", name, &err); @@ -150,9 +158,7 @@ macro_rules! test_stabilizer_on_strategy_with_order { general_test( stringify!($short), |g| { - let stabilizer = g - .group() - .stabchain_with_strategy($strategy(g.order().clone())); + let stabilizer = g.group().stabchain_with_strategy($strategy(g.order().clone())); correct_stabchain_order(&stabilizer, g.order().clone())?; valid_stabchain(&stabilizer) }, @@ -163,19 +169,19 @@ macro_rules! test_stabilizer_on_strategy_with_order { } test_stabilizer_on_strategy!( - NaiveBuilderStrategy::new(SimpleApplication::default(), LmpSelector::default(),), + NaiveBuilderStrategy::new(SimpleApplication::default(), LmpSelector,), test_naive_stabilizer, 0 ); test_stabilizer_on_strategy!( - IftBuilderStrategy::new(SimpleApplication::default(), LmpSelector::default(),), + IftBuilderStrategy::new(SimpleApplication::default(), LmpSelector,), test_ift_stabilizer, 0 ); test_stabilizer_on_strategy!( - RandomBuilderStrategyShallow::new(SimpleApplication::default(), FmpSelector::default(),), + RandomBuilderStrategyShallow::new(SimpleApplication::default(), FmpSelector,), test_random_shallow_stabilizer, (number_of_tests() as f32 * 0.005).floor() as usize ); @@ -183,7 +189,7 @@ test_stabilizer_on_strategy!( test_stabilizer_on_strategy!( RandomBuilderStrategyShallow::new_with_params( SimpleApplication::default(), - FmpSelector::default(), + FmpSelector, RandomAlgoParameters::default().quick_test(true) ), test_random_shallow_stabilizer_quick_test, @@ -193,10 +199,8 @@ test_stabilizer_on_strategy!( test_stabilizer_on_strategy_with_order!( |order| RandomBuilderStrategyShallow::new_with_params( SimpleApplication::default(), - FmpSelector::default(), - RandomAlgoParameters::default() - .quick_test(true) - .order(order) + FmpSelector, + RandomAlgoParameters::default().quick_test(true).order(order) ), test_random_shallow_known_order, 0