mirror of
https://git.proxmox.com/git/rustc
synced 2025-08-16 23:31:07 +00:00
142 lines
4.0 KiB
Rust
142 lines
4.0 KiB
Rust
use std::collections::HashSet;
|
|
use std::hash::Hash;
|
|
|
|
use petgraph::algo::{greedy_matching, maximum_matching};
|
|
use petgraph::prelude::*;
|
|
|
|
macro_rules! assert_one_of {
|
|
($actual:expr, [$($expected:expr),+]) => {
|
|
let expected = &[$($expected),+];
|
|
if !expected.iter().any(|expected| expected == &$actual) {
|
|
let expected = expected.iter().map(|e| format!("\n{:?}", e)).collect::<Vec<_>>();
|
|
let comma_separated = expected.join(", ");
|
|
panic!("assertion failed: `actual does not equal to any of expected`\nactual:\n{:?}\nexpected:{}", $actual, comma_separated);
|
|
}
|
|
};
|
|
}
|
|
|
|
macro_rules! set {
|
|
() => {
|
|
HashSet::new()
|
|
};
|
|
($(($source:expr, $target:expr)),+) => {
|
|
{
|
|
let mut set = HashSet::new();
|
|
$(
|
|
set.insert(($source.into(), $target.into()));
|
|
)*
|
|
set
|
|
}
|
|
};
|
|
($($elem:expr),+) => {
|
|
{
|
|
let mut set = HashSet::new();
|
|
$(
|
|
set.insert($elem.into());
|
|
)*
|
|
set
|
|
}
|
|
};
|
|
}
|
|
|
|
// So we don't have to type `.collect::<HashSet<_>>`.
|
|
fn collect<'a, T: Copy + Eq + Hash + 'a>(iter: impl Iterator<Item = T>) -> HashSet<T> {
|
|
iter.collect()
|
|
}
|
|
|
|
#[test]
|
|
fn greedy_empty() {
|
|
let g: UnGraph<(), ()> = UnGraph::default();
|
|
let m = greedy_matching(&g);
|
|
assert_eq!(collect(m.edges()), set![]);
|
|
assert_eq!(collect(m.nodes()), set![]);
|
|
}
|
|
|
|
#[test]
|
|
fn greedy_disjoint() {
|
|
let g: UnGraph<(), ()> = UnGraph::from_edges(&[(0, 1), (2, 3)]);
|
|
let m = greedy_matching(&g);
|
|
assert_eq!(collect(m.edges()), set![(0, 1), (2, 3)]);
|
|
assert_eq!(collect(m.nodes()), set![0, 1, 2, 3]);
|
|
}
|
|
|
|
#[test]
|
|
fn greedy_odd_path() {
|
|
let g: UnGraph<(), ()> = UnGraph::from_edges(&[(0, 1), (1, 2), (2, 3)]);
|
|
let m = greedy_matching(&g);
|
|
assert_one_of!(collect(m.edges()), [set![(0, 1), (2, 3)], set![(1, 2)]]);
|
|
assert_one_of!(collect(m.nodes()), [set![0, 1, 2, 3], set![1, 2]]);
|
|
}
|
|
|
|
#[test]
|
|
fn greedy_star() {
|
|
let g: UnGraph<(), ()> = UnGraph::from_edges(&[(0, 1), (0, 2), (0, 3)]);
|
|
let m = greedy_matching(&g);
|
|
assert_one_of!(
|
|
collect(m.edges()),
|
|
[set![(0, 1)], set![(0, 2)], set![(0, 3)]]
|
|
);
|
|
assert_one_of!(collect(m.nodes()), [set![0, 1], set![0, 2], set![0, 3]]);
|
|
}
|
|
|
|
#[test]
|
|
fn maximum_empty() {
|
|
let g: UnGraph<(), ()> = UnGraph::default();
|
|
let m = maximum_matching(&g);
|
|
assert_eq!(collect(m.edges()), set![]);
|
|
assert_eq!(collect(m.nodes()), set![]);
|
|
}
|
|
|
|
#[test]
|
|
fn maximum_disjoint() {
|
|
let g: UnGraph<(), ()> = UnGraph::from_edges(&[(0, 1), (2, 3)]);
|
|
let m = maximum_matching(&g);
|
|
assert_eq!(collect(m.edges()), set![(0, 1), (2, 3)]);
|
|
assert_eq!(collect(m.nodes()), set![0, 1, 2, 3]);
|
|
}
|
|
|
|
#[test]
|
|
fn maximum_odd_path() {
|
|
let g: UnGraph<(), ()> = UnGraph::from_edges(&[(0, 1), (1, 2), (2, 3)]);
|
|
let m = maximum_matching(&g);
|
|
assert_eq!(collect(m.edges()), set![(0, 1), (2, 3)]);
|
|
assert_eq!(collect(m.nodes()), set![0, 1, 2, 3]);
|
|
}
|
|
|
|
#[cfg(feature = "stable_graph")]
|
|
#[test]
|
|
fn maximum_in_stable_graph() {
|
|
let mut g: StableUnGraph<(), ()> =
|
|
StableUnGraph::from_edges(&[(0, 1), (0, 2), (1, 2), (1, 3), (2, 4), (3, 4), (3, 5)]);
|
|
|
|
// Create a hole by removing node that would otherwise belong to the maximum
|
|
// matching.
|
|
g.remove_node(NodeIndex::new(4));
|
|
|
|
let m = maximum_matching(&g);
|
|
assert_one_of!(
|
|
collect(m.edges()),
|
|
[
|
|
set![(0, 1), (3, 5)],
|
|
set![(0, 2), (1, 3)],
|
|
set![(0, 2), (3, 5)]
|
|
]
|
|
);
|
|
assert_one_of!(
|
|
collect(m.nodes()),
|
|
[set![0, 1, 3, 5], set![0, 2, 1, 3], set![0, 2, 3, 5]]
|
|
);
|
|
}
|
|
|
|
#[cfg(feature = "stable_graph")]
|
|
#[test]
|
|
fn is_perfect_in_stable_graph() {
|
|
let mut g: StableUnGraph<(), ()> = StableUnGraph::from_edges(&[(0, 1), (1, 2), (2, 3)]);
|
|
g.remove_node(NodeIndex::new(0));
|
|
g.remove_node(NodeIndex::new(1));
|
|
|
|
let m = maximum_matching(&g);
|
|
assert_eq!(m.len(), 1);
|
|
assert!(m.is_perfect());
|
|
}
|