Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add bertsekas algo for assignment problem #600

Open
wants to merge 15 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 10 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,8 @@ rust-version = "1.77.2"
sign-commit = true
sign-tag = true
pre-release-replacements = [
{file = "README.md", search = "pathfinding = \".*\"", replace = "pathfinding = \"{{version}}\"", exactly = 1},
{file = "CHANGELOG.md", search = "n\\.n\\.n", replace = "{{tag_name}}", exactly = 1}
{ file = "README.md", search = "pathfinding = \".*\"", replace = "pathfinding = \"{{version}}\"", exactly = 1 },
{ file = "CHANGELOG.md", search = "n\\.n\\.n", replace = "{{tag_name}}", exactly = 1 },
]

[dependencies]
Expand All @@ -43,6 +43,10 @@ regex = "1.10.6"
trybuild = "1.0.99"
version_check = "0.9.5"

[profile.profiling]
inherits = "release"
debug = true

[lints.clippy]
module_name_repetitions = { level = "allow", priority = 1 }
too_long_first_doc_paragraph = { level = "allow", priority = 1 } # Temporary
Expand All @@ -68,6 +72,10 @@ harness = false
name = "kuhn_munkres"
harness = false

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

[[bench]]
name = "separate_components"
harness = false
Expand Down
48 changes: 48 additions & 0 deletions benches/kuhn_munkres_vs_bertsekas.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
use codspeed_criterion_compat::{
black_box, criterion_group, criterion_main, BenchmarkId, Criterion, Throughput,
};
use pathfinding::bertsekas::{bertsekas_aaap, Auction};
use pathfinding::prelude::{kuhn_munkres, Matrix};
use rand::Rng;

fn create_matrices(size: usize) -> (Matrix<i64>, Matrix<f64>) {
let mut rng = rand::thread_rng();
let int_matrix: Matrix<i64> = Matrix::from_fn(size, size, |_| rng.gen_range(0..100));
let float_matrix = int_matrix.clone().map(|value| value as f64);
(int_matrix, float_matrix)
}

fn compare_algorithms(c: &mut Criterion) {
let mut group = c.benchmark_group("Assignment Problem");
let sizes = [10, 20, 50, 100, 200, 500, 1000];

for size in sizes.iter() {
let elements = size * size;

group.throughput(Throughput::Elements(elements as u64));
group.bench_function(BenchmarkId::new("Bertekas Auction", size), |b| {
let (_, float_matrix) = black_box(create_matrices(*size));
b.iter_with_large_drop(|| {
let mut auction_data = Auction::new(&float_matrix);
bertsekas_aaap(&mut auction_data);
});
});

group.throughput(Throughput::Elements(elements as u64));
group.bench_function(BenchmarkId::new("Hungarian Algorithm", size), |b| {
let (int_64matrix, _) = black_box(create_matrices(*size));
b.iter_with_large_drop(|| kuhn_munkres(&int_64matrix));
});
}

// Configure the plot
group.plot_config(
codspeed_criterion_compat::PlotConfiguration::default()
.summary_scale(codspeed_criterion_compat::AxisScale::Logarithmic),
);

group.finish();
}

criterion_group!(benches, compare_algorithms);
criterion_main!(benches);
42 changes: 42 additions & 0 deletions examples/assignment.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
use pathfinding::bertsekas::{bertsekas_aaap, Auction};
use pathfinding::kuhn_munkres::kuhn_munkres;
use pathfinding::matrix::Matrix;
use rand::Rng;
use std::time::Instant;

fn generate_random_matrices(rows: usize, cols: usize) -> (Matrix<f64>, Matrix<i64>) {
let mut rng = rand::thread_rng();
let random_numbers: Vec<i64> = (0..rows * cols).map(|_| rng.gen_range(1..500)).collect();

let matrix_int = Matrix::from_vec(rows, cols, random_numbers.clone()).unwrap();
let matrix_float = Matrix::from_vec(
rows,
cols,
random_numbers.into_iter().map(|x| x as f64).collect(),
)
.unwrap();

(matrix_float, matrix_int)
}

fn main() {
let sizes: [usize; 9] = [5, 10, 50, 100, 250, 500, 1000, 2500, 5000];

println!("Algorithm, Matrix Size, Time (ns), Score");

for &size in &sizes {
let (f_matrix, i_matrix) = generate_random_matrices(size, size);

let now = Instant::now();
let mut auction_data = Auction::new(&f_matrix);
bertsekas_aaap(&mut auction_data);
let score = auction_data.score().unwrap();
let elapsed = now.elapsed().as_nanos();
println!("Bertsekas, {size}x{size}, {elapsed}, {score}");

let now = Instant::now();
let (score, _) = kuhn_munkres(&i_matrix);
let elapsed = now.elapsed().as_nanos();
println!("Kuhn_Munkres, {size}x{size}, {elapsed}, {score}");
}
}
Loading