mod strongly_connected;
use self::SetType::*;
use crate::common::SetType;
use crate::tally::{Tally, VoteMatrix};
use strongly_connected::StronglyConnected;
pub fn smith_schwartz_condensation(x: &VoteMatrix, set: SetType) -> StronglyConnected {
match set {
Smith => x
.pairs()
.filter_map(|((r, o), (win, opp))| if win >= opp { Some((r, o)) } else { None })
.collect(),
Schwartz => x
.pairs()
.filter_map(|((r, o), (win, opp))| if win > opp { Some((r, o)) } else { None })
.chain((0..x.get_candidates()).map(|x| (x, x)))
.collect(),
}
}
pub fn smith_set(x: &VoteMatrix) -> Vec<u32> {
let mut members = smith_schwartz_condensation(x, Smith).get_max();
members.sort_unstable();
members
}
pub fn schwartz_set(x: &VoteMatrix) -> Vec<u32> {
let mut members = smith_schwartz_condensation(x, Schwartz).get_max();
members.sort_unstable();
members
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn ss_simple() {
let x: VoteMatrix = VoteMatrix::with_vector_bycol(
&vec![1, 2, 3, 4, 5, 6],
);
let sh = smith_set(&x);
let sz = schwartz_set(&x);
assert_eq!(sh, vec![0]);
assert_eq!(sz, vec![0]);
}
#[test]
fn ss_weak() {
let x: VoteMatrix = VoteMatrix::with_vector_bycol(
&vec![1, 4, 2, 3, 4, 5],
);
assert_eq!(smith_set(&x), vec![0, 1, 2]);
assert_eq!(schwartz_set(&x), vec![0]);
}
#[test]
fn ss_leader_tie() {
let x: VoteMatrix = VoteMatrix::with_vector_bycol(
&vec![9, 1, 9, 2, 3, 4],
);
assert_eq!(smith_set(&x), vec![0, 1]);
assert_eq!(schwartz_set(&x), vec![0, 1]);
}
#[test]
fn ss_full_tie() {
let x: VoteMatrix = VoteMatrix::with_vector_bycol(
&vec![7, 7, 7, 7, 7, 7],
);
assert_eq!(smith_set(&x), vec![0, 1, 2]);
assert_eq!(schwartz_set(&x), vec![0, 1, 2]);
}
#[test]
fn ss_cycle() {
let x: VoteMatrix = VoteMatrix::with_vector_bycol(
&vec![1, 2, 2, 1, 1, 2],
);
assert_eq!(smith_set(&x), vec![0, 1, 2]);
assert_eq!(schwartz_set(&x), vec![0, 1, 2]);
}
#[test]
fn ss_cycle_alt() {
let x: VoteMatrix = VoteMatrix::with_vector_bycol(
&vec![0, 1, 1, 0, 0, 1],
);
assert_eq!(smith_set(&x), vec![0, 1, 2]);
assert_eq!(schwartz_set(&x), vec![0, 1, 2]);
}
}