Reformat source code using "cargo fmt"

This commit is contained in:
Michael Neumann 2018-01-30 15:09:27 +01:00
parent 75f19c85cd
commit 46599ee62a
4 changed files with 165 additions and 111 deletions

View File

@ -34,9 +34,9 @@ impl Coverage {
/// find a single uncovered (row, col) pair. Iterates in col, row order. /// find a single uncovered (row, col) pair. Iterates in col, row order.
#[inline] #[inline]
pub fn find_uncovered_col_row<F>(&self, mut f: F) -> Option<(usize, usize)> pub fn find_uncovered_col_row<F>(&self, mut f: F) -> Option<(usize, usize)>
where F: FnMut((usize, usize)) -> bool where
F: FnMut((usize, usize)) -> bool,
{ {
let n = self.n(); let n = self.n();
for col in 0..n { for col in 0..n {
@ -61,7 +61,8 @@ impl Coverage {
/// iterates over all uncovered (row, col) pairs in row, col order /// iterates over all uncovered (row, col) pairs in row, col order
#[inline] #[inline]
pub fn iter_uncovered_row_col<F>(&self, mut f: F) pub fn iter_uncovered_row_col<F>(&self, mut f: F)
where F: FnMut((usize, usize)) where
F: FnMut((usize, usize)),
{ {
let n = self.n(); let n = self.n();
@ -83,7 +84,8 @@ impl Coverage {
/// iterates over all uncovered (row, col) pairs in row, col order, and set covered if f returns true. /// iterates over all uncovered (row, col) pairs in row, col order, and set covered if f returns true.
#[inline] #[inline]
pub fn iter_uncovered_row_col_and_cover<F>(&mut self, mut f: F) pub fn iter_uncovered_row_col_and_cover<F>(&mut self, mut f: F)
where F: FnMut((usize, usize)) -> bool where
F: FnMut((usize, usize)) -> bool,
{ {
let n = self.n(); let n = self.n();

View File

@ -8,13 +8,10 @@
/// This code is derived from a port of the Python version found here: /// This code is derived from a port of the Python version found here:
/// https://github.com/bmc/munkres/blob/master/munkres.py /// https://github.com/bmc/munkres/blob/master/munkres.py
/// which is Copyright (c) 2008 Brian M. Clapper. /// which is Copyright (c) 2008 Brian M. Clapper.
// TODO: // TODO:
// * Cleanup // * Cleanup
// * More test cases // * More test cases
// * Non-square matrices // * Non-square matrices
extern crate fixedbitset; extern crate fixedbitset;
extern crate ndarray; extern crate ndarray;
@ -38,19 +35,71 @@ pub mod weight_matrix;
pub trait WeightNum: PartialOrd + Copy + Sub<Output = Self> + Add<Output = Self> { pub trait WeightNum: PartialOrd + Copy + Sub<Output = Self> + Add<Output = Self> {
fn is_zero(&self) -> bool; fn is_zero(&self) -> bool;
fn is_disallowed(&self) -> bool { false } fn is_disallowed(&self) -> bool {
false
}
} }
impl WeightNum for usize { #[inline(always)] fn is_zero(&self) -> bool { *self == 0 } } impl WeightNum for usize {
impl WeightNum for isize { #[inline(always)] fn is_zero(&self) -> bool { *self == 0 } } #[inline(always)]
impl WeightNum for u64 { #[inline(always)] fn is_zero(&self) -> bool { *self == 0 } } fn is_zero(&self) -> bool {
impl WeightNum for i64 { #[inline(always)] fn is_zero(&self) -> bool { *self == 0 } } *self == 0
impl WeightNum for u32 { #[inline(always)] fn is_zero(&self) -> bool { *self == 0 } } }
impl WeightNum for i32 { #[inline(always)] fn is_zero(&self) -> bool { *self == 0 } } }
impl WeightNum for u16 { #[inline(always)] fn is_zero(&self) -> bool { *self == 0 } } impl WeightNum for isize {
impl WeightNum for i16 { #[inline(always)] fn is_zero(&self) -> bool { *self == 0 } } #[inline(always)]
impl WeightNum for u8 { #[inline(always)] fn is_zero(&self) -> bool { *self == 0 } } fn is_zero(&self) -> bool {
impl WeightNum for i8 { #[inline(always)] fn is_zero(&self) -> bool { *self == 0 } } *self == 0
}
}
impl WeightNum for u64 {
#[inline(always)]
fn is_zero(&self) -> bool {
*self == 0
}
}
impl WeightNum for i64 {
#[inline(always)]
fn is_zero(&self) -> bool {
*self == 0
}
}
impl WeightNum for u32 {
#[inline(always)]
fn is_zero(&self) -> bool {
*self == 0
}
}
impl WeightNum for i32 {
#[inline(always)]
fn is_zero(&self) -> bool {
*self == 0
}
}
impl WeightNum for u16 {
#[inline(always)]
fn is_zero(&self) -> bool {
*self == 0
}
}
impl WeightNum for i16 {
#[inline(always)]
fn is_zero(&self) -> bool {
*self == 0
}
}
impl WeightNum for u8 {
#[inline(always)]
fn is_zero(&self) -> bool {
*self == 0
}
}
impl WeightNum for i8 {
#[inline(always)]
fn is_zero(&self) -> bool {
*self == 0
}
}
impl WeightNum for f64 { impl WeightNum for f64 {
#[inline(always)] #[inline(always)]
@ -105,7 +154,8 @@ enum Step {
/// For each row of the matrix, find the smallest element and /// For each row of the matrix, find the smallest element and
/// subtract it from every element in its row. Go to Step 2. /// subtract it from every element in its row. Go to Step 2.
fn step1<W>(c: &mut W) -> Step fn step1<W>(c: &mut W) -> Step
where W: Weights where
W: Weights,
{ {
c.sub_min_of_each_row(); c.sub_min_of_each_row();
return Step::Step2; return Step::Step2;
@ -115,9 +165,9 @@ fn step1<W>(c: &mut W) -> Step
/// zero in its row or column, star Z. Repeat for each element in the /// zero in its row or column, star Z. Repeat for each element in the
/// matrix. Go to Step 3. /// matrix. Go to Step 3.
fn step2<W>(c: &W, marks: &mut MarkMatrix, cov: &mut Coverage) -> Step fn step2<W>(c: &W, marks: &mut MarkMatrix, cov: &mut Coverage) -> Step
where W: Weights where
W: Weights,
{ {
let n = c.n(); let n = c.n();
assert!(marks.n() == n); assert!(marks.n() == n);
@ -143,9 +193,9 @@ fn step2<W>(c: &W, marks: &mut MarkMatrix, cov: &mut Coverage) -> Step
/// covered, the starred zeros describe a complete set of unique /// covered, the starred zeros describe a complete set of unique
/// assignments. In this case, Go to DONE, otherwise, Go to Step 4. /// assignments. In this case, Go to DONE, otherwise, Go to Step 4.
fn step3<W>(c: &W, marks: &MarkMatrix, cov: &mut Coverage) -> Step fn step3<W>(c: &W, marks: &MarkMatrix, cov: &mut Coverage) -> Step
where W: Weights where
W: Weights,
{ {
let n = c.n(); let n = c.n();
assert!(marks.n() == n); assert!(marks.n() == n);
@ -172,16 +222,15 @@ fn step3<W>(c: &W, marks: &MarkMatrix, cov: &mut Coverage) -> Step
/// zero. Continue in this manner until there are no uncovered zeros /// zero. Continue in this manner until there are no uncovered zeros
/// left. Save the smallest uncovered value and Go to Step 6. /// left. Save the smallest uncovered value and Go to Step 6.
fn step4<W>(c: &W, marks: &mut MarkMatrix, cov: &mut Coverage) -> Step fn step4<W>(c: &W, marks: &mut MarkMatrix, cov: &mut Coverage) -> Step
where W: Weights where
W: Weights,
{ {
let n = c.n(); let n = c.n();
assert!(marks.n() == n); assert!(marks.n() == n);
assert!(cov.n() == n); assert!(cov.n() == n);
loop { loop {
// find uncovered zero element // find uncovered zero element
match cov.find_uncovered_col_row(|pos| c.is_element_zero(pos)) { match cov.find_uncovered_col_row(|pos| c.is_element_zero(pos)) {
None => { None => {
@ -202,7 +251,6 @@ fn step4<W>(c: &W, marks: &mut MarkMatrix, cov: &mut Coverage) -> Step
} }
} }
} }
} }
/// Construct a series of alternating primed and starred zeros as /// Construct a series of alternating primed and starred zeros as
@ -213,7 +261,12 @@ fn step4<W>(c: &W, marks: &mut MarkMatrix, cov: &mut Coverage) -> Step
/// that has no starred zero in its column. Unstar each starred zero /// that has no starred zero in its column. Unstar each starred zero
/// of the series, star each primed zero of the series, erase all /// of the series, star each primed zero of the series, erase all
/// primes and uncover every line in the matrix. Return to Step 3 /// primes and uncover every line in the matrix. Return to Step 3
fn step5(marks: &mut MarkMatrix, cov: &mut Coverage, z0: (usize, usize), path: &mut Vec<(usize, usize)>) -> Step { fn step5(
marks: &mut MarkMatrix,
cov: &mut Coverage,
z0: (usize, usize),
path: &mut Vec<(usize, usize)>,
) -> Step {
let n = cov.n(); let n = cov.n();
assert!(marks.n() == n); assert!(marks.n() == n);
@ -252,15 +305,14 @@ fn step5(marks: &mut MarkMatrix, cov: &mut Coverage, z0: (usize, usize), path: &
return Step::Step3; return Step::Step3;
} }
/// Add the value found in Step 4 to every element of each covered /// Add the value found in Step 4 to every element of each covered
/// row, and subtract it from every element of each uncovered column. /// row, and subtract it from every element of each uncovered column.
/// Return to Step 4 without altering any stars, primes, or covered /// Return to Step 4 without altering any stars, primes, or covered
/// lines. /// lines.
fn step6<W>(c: &mut W, cov: &Coverage) -> Step fn step6<W>(c: &mut W, cov: &Coverage) -> Step
where W: Weights where
W: Weights,
{ {
let n = c.n(); let n = c.n();
assert!(cov.n() == n); assert!(cov.n() == n);
@ -276,9 +328,7 @@ fn step6<W>(c: &mut W, cov: &Coverage) -> Step
elm elm
} }
} }
None => { None => elm,
elm
}
}); });
}); });
@ -298,7 +348,8 @@ fn step6<W>(c: &mut W, cov: &Coverage) -> Step
} }
pub fn solve_assignment<W>(weights: &mut W) -> Vec<(usize, usize)> pub fn solve_assignment<W>(weights: &mut W) -> Vec<(usize, usize)>
where W: Weights where
W: Weights,
{ {
if !weights.is_solvable() { if !weights.is_solvable() {
panic!("Matrix can not be solved"); panic!("Matrix can not be solved");
@ -313,9 +364,7 @@ pub fn solve_assignment<W>(weights: &mut W) -> Vec<(usize, usize)>
let mut step = Step::Step1; let mut step = Step::Step1;
loop { loop {
match step { match step {
Step::Step1 => { Step::Step1 => step = step1(weights),
step = step1(weights)
}
Step::Step2 => { Step::Step2 => {
step = step2(weights, &mut marks, &mut coverage); step = step2(weights, &mut marks, &mut coverage);
} }
@ -365,7 +414,6 @@ fn test_step1() {
assert_eq!(exp, weights.as_slice()); assert_eq!(exp, weights.as_slice());
} }
#[test] #[test]
fn test_step2() { fn test_step2() {
let c = vec![0, 150, 100, 50, 250, 0, 0, 200, 50]; let c = vec![0, 150, 100, 50, 250, 0, 0, 200, 50];
@ -569,7 +617,6 @@ fn test_step5() {
assert_eq!(true, marks.is_none((2, 2))); assert_eq!(true, marks.is_none((2, 2)));
} }
#[test] #[test]
fn test_solve() { fn test_solve() {
let c = vec![250, 400, 350, // row 1 let c = vec![250, 400, 350, // row 1
@ -586,10 +633,7 @@ fn test_solve() {
#[test] #[test]
fn test_solve_equal_rows_stepwise() { fn test_solve_equal_rows_stepwise() {
const N: usize = 2; const N: usize = 2;
let c = vec![ let c = vec![1, 1, 2, 2];
1, 1,
2, 2,
];
let mut weights: WeightMatrix<u32> = WeightMatrix::from_row_vec(N, c); let mut weights: WeightMatrix<u32> = WeightMatrix::from_row_vec(N, c);
@ -625,10 +669,7 @@ fn test_solve_equal_rows_stepwise() {
#[test] #[test]
fn test_solve_equal_rows2() { fn test_solve_equal_rows2() {
const N: usize = 2; const N: usize = 2;
let c = vec![ let c = vec![1, 1, 2, 2];
1, 1,
2, 2,
];
let mut weights: WeightMatrix<u32> = WeightMatrix::from_row_vec(N, c.clone()); let mut weights: WeightMatrix<u32> = WeightMatrix::from_row_vec(N, c.clone());
let matching = solve_assignment(&mut weights); let matching = solve_assignment(&mut weights);
@ -647,11 +688,7 @@ fn test_solve_equal_rows2() {
fn test_solve_equal_rows5() { fn test_solve_equal_rows5() {
const N: usize = 5; const N: usize = 5;
let c = vec![ let c = vec![
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
0, 0, 0, 0, 0,
0, 0, 0, 0, 0,
1, 1, 1, 1, 1,
1, 1, 1, 1, 1,
]; ];
let mut weights: WeightMatrix<u32> = WeightMatrix::from_row_vec(N, c.clone()); let mut weights: WeightMatrix<u32> = WeightMatrix::from_row_vec(N, c.clone());
@ -671,11 +708,8 @@ fn test_solve_equal_rows5() {
fn test_solve_equal_rows5_float() { fn test_solve_equal_rows5_float() {
const N: usize = 5; const N: usize = 5;
let c = vec![ let c = vec![
0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 1.0, 1.0,
0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0,
0.0, 0.0, 0.0, 0.0, 0.0,
1.0, 1.0, 1.0, 1.0, 1.0,
1.0, 1.0, 1.0, 1.0, 1.0,
]; ];
let mut weights: WeightMatrix<f32> = WeightMatrix::from_row_vec(N, c.clone()); let mut weights: WeightMatrix<f32> = WeightMatrix::from_row_vec(N, c.clone());
@ -695,11 +729,8 @@ fn test_solve_equal_rows5_float() {
fn test_solve_equal_rows5_float2() { fn test_solve_equal_rows5_float2() {
const N: usize = 5; const N: usize = 5;
let c = vec![ let c = vec![
1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 0.0, 0.0, 0.0,
1.0, 1.0, 1.0, 1.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,
1.0, 1.0, 1.0, 1.0, 1.0,
0.0, 0.0, 0.0, 0.0, 0.0,
0.0, 0.0, 0.0, 0.0, 0.0,
]; ];
let mut weights: WeightMatrix<f32> = WeightMatrix::from_row_vec(N, c.clone()); let mut weights: WeightMatrix<f32> = WeightMatrix::from_row_vec(N, c.clone());
@ -719,16 +750,12 @@ fn test_solve_equal_rows5_float2() {
fn test_solve_random10() { fn test_solve_random10() {
const N: usize = 10; const N: usize = 10;
let c = vec![ let c = vec![
612, 643, 717, 2, 946, 534, 242, 235, 376, 839, 612, 643, 717, 2, 946, 534, 242, 235, 376, 839, 224, 141, 799, 180, 386, 745, 592, 822,
224, 141, 799, 180, 386, 745, 592, 822, 421, 42, 421, 42, 241, 369, 831, 67, 258, 549, 615, 529, 458, 524, 231, 649, 287, 910, 12, 820, 31,
241, 369, 831, 67, 258, 549, 615, 529, 458, 524, 92, 217, 555, 912, 81, 568, 241, 292, 653, 417, 652, 630, 788, 32, 822, 788, 166, 122, 690,
231, 649, 287, 910, 12, 820, 31, 92, 217, 555, 304, 568, 449, 214, 441, 469, 584, 633, 213, 414, 498, 500, 317, 391, 798, 581, 183, 420,
912, 81, 568, 241, 292, 653, 417, 652, 630, 788, 16, 748, 35, 516, 639, 356, 351, 921, 67, 33, 592, 775, 780, 335, 464, 788, 771, 455, 950,
32, 822, 788, 166, 122, 690, 304, 568, 449, 214, 25, 22, 576, 969, 122, 86, 74,
441, 469, 584, 633, 213, 414, 498, 500, 317, 391,
798, 581, 183, 420, 16, 748, 35, 516, 639, 356,
351, 921, 67, 33, 592, 775, 780, 335, 464, 788,
771, 455, 950, 25, 22, 576, 969, 122, 86, 74,
]; ];
let mut weights: WeightMatrix<i32> = WeightMatrix::from_row_vec(N, c.clone()); let mut weights: WeightMatrix<i32> = WeightMatrix::from_row_vec(N, c.clone());
@ -743,7 +770,18 @@ fn test_solve_random10() {
assert_eq!(1071, cost); assert_eq!(1071, cost);
let exp = &[(0, 7), (1, 9), (2, 3), (3, 4), (4, 1), (5, 0), (6, 5), (7, 6), (8, 2), (9, 8)]; let exp = &[
(0, 7),
(1, 9),
(2, 3),
(3, 4),
(4, 1),
(5, 0),
(6, 5),
(7, 6),
(8, 2),
(9, 8),
];
assert_eq!(exp, &matching[..]); assert_eq!(exp, &matching[..]);
} }
@ -751,9 +789,15 @@ fn test_solve_random10() {
#[test] #[test]
fn test_disallowed() { fn test_disallowed() {
let c = vec![ let c = vec![
250.0, 400.0, 350.0, 250.0,
400.0, 600.0, f32::INFINITY, 400.0,
200.0, 400.0, 250.0 350.0,
400.0,
600.0,
f32::INFINITY,
200.0,
400.0,
250.0,
]; ];
let mut weights: WeightMatrix<f32> = WeightMatrix::from_row_vec(3, c); let mut weights: WeightMatrix<f32> = WeightMatrix::from_row_vec(3, c);
@ -767,9 +811,15 @@ fn test_disallowed() {
fn test_unsolvable() { fn test_unsolvable() {
const N: usize = 3; const N: usize = 3;
let c = vec![ let c = vec![
1.0, 1.0, 1.0, 1.0,
f32::INFINITY, f32::INFINITY, f32::INFINITY, 1.0,
1.0, 1.0, 1.0, 1.0,
f32::INFINITY,
f32::INFINITY,
f32::INFINITY,
1.0,
1.0,
1.0,
]; ];
let mut weights: WeightMatrix<f32> = WeightMatrix::from_row_vec(N, c.clone()); let mut weights: WeightMatrix<f32> = WeightMatrix::from_row_vec(N, c.clone());

View File

@ -69,7 +69,8 @@ impl MarkMatrix {
#[inline] #[inline]
pub fn each_star<F>(&self, mut f: F) pub fn each_star<F>(&self, mut f: F)
where F: FnMut((usize, usize)) where
F: FnMut((usize, usize)),
{ {
let n = self.n(); let n = self.n();

View File

@ -31,24 +31,22 @@ impl<T: WeightNum> Weights for WeightMatrix<T> {
// Add `val` to every element in row `row`. // Add `val` to every element in row `row`.
fn add_row(&mut self, row: usize, val: T) { fn add_row(&mut self, row: usize, val: T) {
self.c.row_mut(row).mapv_inplace(|cur| { self.c
if cur.is_disallowed() { .row_mut(row)
cur .mapv_inplace(|cur| if cur.is_disallowed() { cur } else { cur + val });
} else {
cur + val
}
});
} }
// Subtract `val` from every element in column `col`. // Subtract `val` from every element in column `col`.
fn sub_col(&mut self, col: usize, val: T) { fn sub_col(&mut self, col: usize, val: T) {
self.c.column_mut(col).mapv_inplace(|cur| { self.c.column_mut(col).mapv_inplace(
|cur| {
if cur.is_disallowed() { if cur.is_disallowed() {
cur cur
} else { } else {
cur - val cur - val
} }
}); },
);
} }
fn is_solvable(&self) -> bool { fn is_solvable(&self) -> bool {
@ -63,12 +61,16 @@ impl<T: WeightNum> Weights for WeightMatrix<T> {
impl<T: WeightNum> WeightMatrix<T> { impl<T: WeightNum> WeightMatrix<T> {
pub fn from_row_vec(n: usize, data: Vec<T>) -> WeightMatrix<T> { pub fn from_row_vec(n: usize, data: Vec<T>) -> WeightMatrix<T> {
WeightMatrix { c: SquareMatrix::from_shape_vec((n, n), data).unwrap() } WeightMatrix {
c: SquareMatrix::from_shape_vec((n, n), data).unwrap(),
}
} }
pub fn from_fn<F: Fn((usize, usize)) -> T>(n: usize, f: F) -> WeightMatrix<T> { pub fn from_fn<F: Fn((usize, usize)) -> T>(n: usize, f: F) -> WeightMatrix<T> {
assert!(n > 0); assert!(n > 0);
WeightMatrix { c: SquareMatrix::from_shape_fn((n, n), f) } WeightMatrix {
c: SquareMatrix::from_shape_fn((n, n), f),
}
} }
/// Return the minimum element of row `row`. /// Return the minimum element of row `row`.
@ -85,13 +87,9 @@ impl<T: WeightNum> WeightMatrix<T> {
// Subtract `val` from every element in row `row`. // Subtract `val` from every element in row `row`.
fn sub_row(&mut self, row: usize, val: T) { fn sub_row(&mut self, row: usize, val: T) {
self.c.row_mut(row).mapv_inplace(|cur| { self.c
if cur.is_disallowed() { .row_mut(row)
cur .mapv_inplace(|cur| if cur.is_disallowed() { cur } else { cur - val });
} else {
cur - val
}
});
} }
pub fn as_slice(&self) -> &[T] { pub fn as_slice(&self) -> &[T] {
@ -103,7 +101,10 @@ impl<T: WeightNum> WeightMatrix<T> {
fn test_weight_matrix() { fn test_weight_matrix() {
assert_eq!(0, WeightMatrix::from_row_vec(1, vec![0]).min_of_row(0)); assert_eq!(0, WeightMatrix::from_row_vec(1, vec![0]).min_of_row(0));
assert_eq!(1, WeightMatrix::from_row_vec(1, vec![1]).min_of_row(0)); assert_eq!(1, WeightMatrix::from_row_vec(1, vec![1]).min_of_row(0));
assert_eq!(1, WeightMatrix::from_row_vec(2, vec![5, 1, 0, 0]).min_of_row(0)); assert_eq!(
1,
WeightMatrix::from_row_vec(2, vec![5, 1, 0, 0]).min_of_row(0)
);
let mut mat = WeightMatrix::from_row_vec(2, vec![0, 1, 2, 3]); let mut mat = WeightMatrix::from_row_vec(2, vec![0, 1, 2, 3]);
mat.sub_row(1, 1); mat.sub_row(1, 1);