use std::collections::HashSet;
use crate::cyclotomic::IsRing;
use crate::geom::snake::Snake;
use crate::rat_enum::canonical::make_ops;
use crate::rat_enum::dfs::{SeedGather, collect_seeds, hashset_recorder, rat_enum_step};
use crate::rat_enum::prune::snapshot_prunes;
use crate::rat_enum::seed::parallel::{parallel_drain_seeds, splitting_depth};
use crate::rat_enum::stats::DfsStats;
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);
let mut gather = SeedGather {
seeds: &mut seeds,
record_closed: &mut record_closed,
stats: &mut stats,
};
collect_seeds::<ZZ>(
&mut snake,
max_steps,
step,
split_depth,
&mut gather,
ops,
false,
&prunes,
);
}
(closed, seeds)
}
pub fn enumerate_from_seed<ZZ: IsRing>(
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_unsafe(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>(
&mut snake,
max_steps,
step,
&mut record,
&mut stats,
ops,
paranoid,
&prunes,
);
}
return local;
}
let hm1 = (ZZ::hturn() as usize).saturating_sub(1);
let branching = 2 * (hm1 / step.max(1) as usize) + 1;
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_unsafe(seed);
let mut record_closed = hashset_recorder(&mut closed_main);
let mut gather = SeedGather {
seeds: &mut sub_seeds,
record_closed: &mut record_closed,
stats: &mut seed_stats,
};
collect_seeds::<ZZ>(
&mut snake,
max_steps,
step,
split_depth,
&mut gather,
ops,
paranoid,
&prunes,
);
}
let (merged, _) = parallel_drain_seeds::<ZZ>(
&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)
)
}