mod generic;
mod partitioned;
use alloc::vec::Vec;
pub(crate) use generic::search as generic_search;
pub(crate) use partitioned::partial_u32_best_size_with_budget;
pub use partitioned::{
OwnedPartitionLabels, PartitionInfo, PartitionSide, SearchOutcome, all_best_search,
choose_partition_side_by_atom_counts, greedy_lower_bound, partial_search, partial_search_u32,
partial_search_u32_with_bounds, partial_search_with_bounds,
};
use crate::{impls::BitSquareMatrix, traits::SquareMatrix};
pub trait MaximumClique {
#[must_use]
fn maximum_clique(&self) -> Vec<usize>;
#[must_use]
fn all_maximum_cliques(&self) -> Vec<Vec<usize>>;
#[must_use]
fn maximum_clique_where<F>(&self, accept_clique: F) -> Vec<usize>
where
F: FnMut(&[usize]) -> bool;
#[must_use]
fn all_maximum_cliques_where<F>(&self, accept_clique: F) -> Vec<Vec<usize>>
where
F: FnMut(&[usize]) -> bool;
}
pub trait PartitionedMaximumClique {
#[must_use]
fn maximum_clique_with_partition(&self, partition: &PartitionInfo<'_>) -> Vec<usize>;
#[must_use]
fn all_maximum_cliques_with_partition(&self, partition: &PartitionInfo<'_>) -> Vec<Vec<usize>>;
#[must_use]
fn maximum_clique_with_partition_where<F>(
&self,
partition: &PartitionInfo<'_>,
accept_clique: F,
) -> Vec<usize>
where
F: FnMut(&[usize]) -> bool;
#[must_use]
fn all_maximum_cliques_with_partition_where<F>(
&self,
partition: &PartitionInfo<'_>,
accept_clique: F,
) -> Vec<Vec<usize>>
where
F: FnMut(&[usize]) -> bool;
#[must_use]
fn maximum_clique_with_pairs(&self, pairs: &[(usize, usize)]) -> Vec<usize>
where
Self: Sized,
{
let labels = OwnedPartitionLabels::unlabeled(pairs);
self.maximum_clique_with_partition(&labels.as_info(pairs))
}
#[must_use]
fn maximum_clique_with_pairs_where<F>(
&self,
pairs: &[(usize, usize)],
accept_clique: F,
) -> Vec<usize>
where
Self: Sized,
F: FnMut(&[usize]) -> bool,
{
let labels = OwnedPartitionLabels::unlabeled(pairs);
self.maximum_clique_with_partition_where(&labels.as_info(pairs), accept_clique)
}
#[must_use]
fn all_maximum_cliques_with_pairs(&self, pairs: &[(usize, usize)]) -> Vec<Vec<usize>>
where
Self: Sized,
{
let labels = OwnedPartitionLabels::unlabeled(pairs);
self.all_maximum_cliques_with_partition(&labels.as_info(pairs))
}
#[must_use]
fn all_maximum_cliques_with_pairs_where<F>(
&self,
pairs: &[(usize, usize)],
accept_clique: F,
) -> Vec<Vec<usize>>
where
Self: Sized,
F: FnMut(&[usize]) -> bool,
{
let labels = OwnedPartitionLabels::unlabeled(pairs);
self.all_maximum_cliques_with_partition_where(&labels.as_info(pairs), accept_clique)
}
}
impl MaximumClique for BitSquareMatrix {
fn maximum_clique(&self) -> Vec<usize> {
self.maximum_clique_where(|_| true)
}
fn all_maximum_cliques(&self) -> Vec<Vec<usize>> {
self.all_maximum_cliques_where(|_| true)
}
fn maximum_clique_where<F>(&self, accept_clique: F) -> Vec<usize>
where
F: FnMut(&[usize]) -> bool,
{
generic::search(self, false, usize::MAX, accept_clique)
.cliques
.into_iter()
.next()
.unwrap_or_default()
}
fn all_maximum_cliques_where<F>(&self, accept_clique: F) -> Vec<Vec<usize>>
where
F: FnMut(&[usize]) -> bool,
{
generic::search(self, true, usize::MAX, accept_clique).cliques
}
}
impl PartitionedMaximumClique for BitSquareMatrix {
fn maximum_clique_with_partition(&self, partition: &PartitionInfo<'_>) -> Vec<usize> {
self.maximum_clique_with_partition_where(partition, |_| true)
}
fn all_maximum_cliques_with_partition(&self, partition: &PartitionInfo<'_>) -> Vec<Vec<usize>> {
self.all_maximum_cliques_with_partition_where(partition, |_| true)
}
fn maximum_clique_with_partition_where<F>(
&self,
partition: &PartitionInfo<'_>,
accept_clique: F,
) -> Vec<usize>
where
F: FnMut(&[usize]) -> bool,
{
assert_eq!(partition.pairs.len(), self.order(), "partition length must equal graph order");
partitioned::search(self, partition, false, 0, accept_clique)
.into_iter()
.next()
.unwrap_or_default()
}
fn all_maximum_cliques_with_partition_where<F>(
&self,
partition: &PartitionInfo<'_>,
accept_clique: F,
) -> Vec<Vec<usize>>
where
F: FnMut(&[usize]) -> bool,
{
assert_eq!(partition.pairs.len(), self.order(), "partition length must equal graph order");
partitioned::search(self, partition, true, 0, accept_clique)
}
}