Skip to content

Commit

Permalink
Benchmarking combinatorics
Browse files Browse the repository at this point in the history
  • Loading branch information
ekoutanov committed Nov 24, 2023
1 parent 548b80c commit 08bdc03
Show file tree
Hide file tree
Showing 3 changed files with 54 additions and 1 deletion.
4 changes: 4 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,10 @@ assert_float_eq = "1.1.3"
criterion = { version = "0.5.1", features = ["html_reports"] }
tinyrand-alloc = "0.5.0"

[[bench]]
name = "cri_comb"
harness = false

[[bench]]
name = "cri_mc"
harness = false
Expand Down
45 changes: 45 additions & 0 deletions benches/cri_comb.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
use criterion::{criterion_group, criterion_main, Criterion};

use brumby::comb::{count_combinations, is_unique_linear, pick};

fn criterion_benchmark(c: &mut Criterion) {
fn fixtures(items: usize, times: usize) -> (Vec<bool>, Vec<usize>, Vec<usize>) {
let mut bitmap = Vec::with_capacity(items);
bitmap.resize(bitmap.capacity(), true);
let mut cardinalities = Vec::with_capacity(times);
cardinalities.resize(cardinalities.capacity(), items);
let mut ordinals = Vec::with_capacity(times);
ordinals.resize(ordinals.capacity(), 0usize);
(bitmap, cardinalities, ordinals)
}

let (mut bitmap, cardinalities, mut ordinals) = fixtures(10, 5);

// sanity check
let unique_combinations = (0..count_combinations(&cardinalities))
.into_iter()
.map(|combination| {
pick(&cardinalities, combination, &mut ordinals);
is_unique_linear(&ordinals, &mut bitmap)
})
.filter(|&unique| unique)
.count();
assert_eq!(10 * 9 * 8 * 7 * 6, unique_combinations);

fn bench(c: &mut Criterion, items: usize, times: usize) {
let (mut bitmap, cardinalities, mut ordinals) = fixtures(items, times);
c.bench_function(&format!("cri_comb_{items}c{times}"), |b| {
b.iter(|| {
for combination in 0..count_combinations(&cardinalities) {
pick(&cardinalities, combination, &mut ordinals);
is_unique_linear(&ordinals, &mut bitmap);
}
});
});
}
bench(c, 10, 3);
bench(c, 10, 4);
}

criterion_group!(benches, criterion_benchmark);
criterion_main!(benches);
6 changes: 5 additions & 1 deletion src/comb.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
//! Combinatorics.
#[inline]
pub fn pick(cardinalities: &[usize], combination: u64, ordinals: &mut [usize]) {
let mut residual = combination;
for (index, &cardinality) in cardinalities.iter().enumerate() {
Expand All @@ -10,8 +11,9 @@ pub fn pick(cardinalities: &[usize], combination: u64, ordinals: &mut [usize]) {
}
}

#[inline]
pub fn count_combinations(cardinalities: &[usize]) -> u64 {
cardinalities.iter().product::<usize>() as u64
cardinalities.iter().fold(1u64, |acc, &num| acc * num as u64)
}

pub struct Combinator<'a> {
Expand Down Expand Up @@ -63,6 +65,7 @@ impl<'a> Iterator for Iter<'a> {
}
}

#[inline]
pub fn is_unique_quadratic(elements: &[usize]) -> bool {
for (index, element) in elements.iter().enumerate() {
for other in &elements[index + 1..] {
Expand All @@ -74,6 +77,7 @@ pub fn is_unique_quadratic(elements: &[usize]) -> bool {
true
}

#[inline]
pub fn is_unique_linear(elements: &[usize], bitmap: &mut [bool]) -> bool {
bitmap.fill(false);
for &element in elements {
Expand Down

0 comments on commit 08bdc03

Please sign in to comment.