Reformat source code using "cargo fmt"
This commit is contained in:
parent
75f19c85cd
commit
46599ee62a
@ -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();
|
||||||
|
|
||||||
|
202
src/lib.rs
202
src/lib.rs
@ -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());
|
||||||
|
@ -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();
|
||||||
|
|
||||||
|
@ -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);
|
||||||
|
Loading…
Reference in New Issue
Block a user