pub(crate) mod builtin;
mod tree;
pub use builtin::{And, ApproxTopN, CoefficientThreshold, CollapseSample, Or, TopN, WeightCutoff};
pub use tree::BuiltinTruncation;
use crate::collectives::Collectives;
use crate::pauli_sum::PauliSum;
use num_complex::Complex64;
pub trait TruncationPolicy<const W: usize>: Send + Sync {
fn keep_term(&self, _x: &[u64; W], _z: &[u64; W], _c: Complex64) -> bool {
true
}
fn finalize_layer(&self, _sum: &mut PauliSum<W>) {}
fn finalizes_layer(&self) -> bool {
true
}
fn finalize_layer_partitioned(&self, local: &mut PauliSum<W>, collectives: &dyn Collectives) {
if collectives.size() == 1 {
self.finalize_layer(local);
return;
}
assert!(
!self.finalizes_layer(),
"{} has a layer pass but no partitioned one: every partition sees only a disjoint \
slice of the layer, so the pass has to be collective. Override \
`finalize_layer_partitioned` and `supports_partitioned` (see `ApproxTopN`, which \
all-reduces its octave histogram), or use `ApproxTopN` itself.",
std::any::type_name_of_val(self),
);
}
fn supports_partitioned(&self) -> bool {
!self.finalizes_layer()
}
}
pub(crate) fn assert_supports_partitions<const W: usize, T>(policy: &T, partitions: usize)
where
T: TruncationPolicy<W> + ?Sized,
{
assert!(
partitions == 1 || policy.supports_partitioned(),
"{} cannot run on {partitions} partitions: its layer pass has no collective form. \
Partitioned exact `TopN` is not yet supported; `ApproxTopN` is the partitioned \
alternative.",
std::any::type_name_of_val(policy),
);
}
#[cfg(test)]
mod tests;