use std::time::Instant;
use super::graph::EliminationGraph;
pub(super) const DEADLINE_CHECK_STRIDE: u32 = 64;
#[derive(Clone, Copy, Default)]
pub(crate) struct ElimStop {
pub(crate) soft_deadline: Option<Instant>,
pub(crate) hard_deadline: Option<Instant>,
pub(crate) width_bound: Option<u32>,
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub(super) enum ElimExit {
Complete,
DeadlineReached,
WidthLimitExceeded,
}
#[inline]
pub(super) fn exceeds_width_bound(bag_len: usize, bound: Option<u32>) -> bool {
matches!(bound, Some(b) if bag_len > b as usize + 1)
}
#[derive(Clone, Default)]
pub(super) struct ElimSteps {
pub(super) bags: Vec<Vec<u32>>,
pub(super) rank_pairs: Vec<(u32, usize)>,
}
impl ElimSteps {
pub(super) fn sink(&mut self) -> ElimSink<'_> {
let start_step = self.bags.len();
ElimSink::new(&mut self.bags, &mut self.rank_pairs, start_step)
}
pub(super) fn append_reindexed(self, comp: &[u32], bags: &mut Vec<Vec<u32>>, rank: &mut [u32]) {
let base = bags.len();
for mut bag in self.bags {
for v in &mut bag {
*v = comp[*v as usize];
}
bags.push(bag);
}
for (local_v, step) in self.rank_pairs {
rank[comp[local_v as usize] as usize] = (base + step) as u32;
}
}
}
pub(super) struct ElimSink<'a> {
bags: &'a mut Vec<Vec<u32>>,
ranks: &'a mut Vec<(u32, usize)>,
step: usize,
}
impl<'a> ElimSink<'a> {
pub(super) fn new(
bags: &'a mut Vec<Vec<u32>>,
ranks: &'a mut Vec<(u32, usize)>,
start_step: usize,
) -> Self {
Self {
bags,
ranks,
step: start_step,
}
}
#[inline]
pub(super) fn record(&mut self, vertex: u32, bag: Vec<u32>) {
self.bags.push(bag);
self.ranks.push((vertex, self.step));
self.step += 1;
}
}
pub(super) fn complete_residual_as_path(graph: &EliminationGraph, sink: &mut ElimSink<'_>) {
let remaining: Vec<u32> = (0..graph.len() as u32)
.filter(|&v| graph.active[v as usize])
.collect();
for (vertex, bag) in path_completion(&remaining) {
sink.record(vertex, bag);
}
}
pub(super) fn path_completion(vertices: &[u32]) -> impl Iterator<Item = (u32, Vec<u32>)> + '_ {
vertices
.iter()
.enumerate()
.map(|(index, &vertex)| (vertex, vertices[index..].to_vec()))
}