use std::collections::HashSet;
use crate::cyclotomic::IsRing;
use crate::enumerate::canonical::make_ops;
use crate::enumerate::dfs::{hashset_recorder, rat_enum_step};
use crate::enumerate::prune::snapshot_prunes;
use crate::enumerate::seed::parallel::{branch_factor, parallel_drain_seeds, splitting_depth};
use crate::enumerate::stats::DfsStats;
use crate::geom::snake::Snake;
type SeedListing = (HashSet<Vec<i8>>, Vec<Vec<i8>>);
pub fn collect_seed_prefixes<ZZ: IsRing>(
max_steps: usize,
step: i8,
split_depth: usize,
free: bool,
) -> (HashSet<Vec<i8>>, Vec<Vec<i8>>) {
let ops = make_ops(free);
let prunes = snapshot_prunes();
let mut snake: Snake<ZZ> = Snake::new();
let mut seeds: Vec<Vec<i8>> = Vec::new();
let mut closed: HashSet<Vec<i8>> = HashSet::new();
let mut stats = DfsStats::default();
{
let mut record_closed = hashset_recorder(&mut closed);
rat_enum_step::<ZZ, Snake<ZZ>>(
&mut snake,
max_steps,
step,
&mut record_closed,
&mut stats,
ops,
false,
&prunes,
None,
split_depth,
&mut seeds,
);
}
(closed, seeds)
}
pub fn enumerate_from_seed<ZZ: IsRing + Sync>(
max_steps: usize,
step: i8,
seed: &[i8],
n_threads: usize,
free: bool,
paranoid: bool,
) -> HashSet<Vec<i8>> {
let ops = make_ops(free);
let prunes = snapshot_prunes();
if n_threads <= 1 {
let mut snake: Snake<ZZ> = Snake::from_slice_trusted(seed);
let mut local: HashSet<Vec<i8>> = HashSet::new();
let mut stats = DfsStats::default();
{
let mut record = hashset_recorder(&mut local);
rat_enum_step::<ZZ, Snake<ZZ>>(
&mut snake,
max_steps,
step,
&mut record,
&mut stats,
ops,
paranoid,
&prunes,
None,
usize::MAX,
&mut Vec::new(),
);
}
return local;
}
let branching = branch_factor(ZZ::hturn(), step);
let sub_split = splitting_depth(n_threads, branching);
let split_depth = (seed.len() + sub_split).min(max_steps);
let mut closed_main: HashSet<Vec<i8>> = HashSet::new();
let mut sub_seeds: Vec<Vec<i8>> = Vec::new();
let mut seed_stats = DfsStats::default();
{
let mut snake: Snake<ZZ> = Snake::from_slice_trusted(seed);
let mut record_closed = hashset_recorder(&mut closed_main);
rat_enum_step::<ZZ, Snake<ZZ>>(
&mut snake,
max_steps,
step,
&mut record_closed,
&mut seed_stats,
ops,
paranoid,
&prunes,
None,
split_depth,
&mut sub_seeds,
);
}
let mk = |seed: &[i8]| Snake::<ZZ>::from_slice_trusted(seed);
let (merged, _) = parallel_drain_seeds::<ZZ, _, _>(
&mk,
&sub_seeds,
closed_main,
seed_stats,
max_steps,
step,
n_threads,
ops,
paranoid,
&prunes,
);
merged
}
pub fn dispatch_collect_seed_prefixes(
ring: u8,
max_steps: usize,
step: i8,
split_depth: usize,
free: bool,
) -> SeedListing {
crate::dispatch_ring!(
ring,
collect_seed_prefixes::<ZZ>(max_steps, step, split_depth, free)
)
}
pub fn dispatch_enumerate_from_seed(
ring: u8,
max_steps: usize,
step: i8,
seed: &[i8],
n_threads: usize,
free: bool,
paranoid: bool,
) -> HashSet<Vec<i8>> {
crate::dispatch_ring!(
ring,
enumerate_from_seed::<ZZ>(max_steps, step, seed, n_threads, free, paranoid)
)
}