use set_theory::models::MultiSet;
#[test]
fn test_multiset_create() {
let ms = MultiSet::from(vec!['a', 'a', 'a', 'b', 'c']);
assert_eq!(ms.cardinality(), 5, "Total cardinality should be 5");
assert_eq!(ms.unique_count(), 3, "Unique count should be 3");
assert_eq!(ms.multiplicity(&'a'), 3, "Multiplicity of 'a' should be 3");
assert_eq!(ms.multiplicity(&'b'), 1, "Multiplicity of 'b' should be 1");
assert_eq!(ms.multiplicity(&'c'), 1, "Multiplicity of 'c' should be 1");
assert_eq!(ms.multiplicity(&'d'), 0, "Multiplicity of 'd' should be 0");
}
#[test]
fn test_multiset_empty() {
let empty = MultiSet::<i32>::empty();
assert_eq!(
empty.cardinality(),
0,
"Empty multiset should have cardinality 0"
);
assert_eq!(
empty.unique_count(),
0,
"Empty multiset should have 0 unique elements"
);
assert!(
empty.is_empty(),
"Empty multiset should return true for is_empty()"
);
}
#[test]
fn test_multiset_union() {
let p = MultiSet::from(vec!['a', 'a', 'a', 'c', 'd', 'd']);
let q = MultiSet::from(vec!['a', 'a', 'b', 'c', 'c']);
let result = p.union(&q);
assert_eq!(result.multiplicity(&'a'), 3, "Max(3, 2) = 3");
assert_eq!(result.multiplicity(&'b'), 1, "Max(0, 1) = 1");
assert_eq!(result.multiplicity(&'c'), 2, "Max(1, 2) = 2");
assert_eq!(result.multiplicity(&'d'), 2, "Max(2, 0) = 2");
}
#[test]
fn test_multiset_intersection() {
let p = MultiSet::from(vec!['a', 'a', 'a', 'c', 'd', 'd']);
let q = MultiSet::from(vec!['a', 'a', 'b', 'c', 'c']);
let result = p.intersection(&q);
assert_eq!(result.multiplicity(&'a'), 2, "Min(3, 2) = 2");
assert_eq!(result.multiplicity(&'b'), 0, "Min(0, 1) = 0");
assert_eq!(result.multiplicity(&'c'), 1, "Min(1, 2) = 1");
assert_eq!(result.multiplicity(&'d'), 0, "Min(2, 0) = 0");
}
#[test]
fn test_multiset_difference() {
let p = MultiSet::from(vec!['a', 'a', 'a', 'b', 'b', 'c', 'd', 'd', 'e']);
let q = MultiSet::from(vec!['a', 'a', 'b', 'b', 'b', 'c', 'c', 'd', 'd', 'f']);
let result = p.difference(&q);
assert_eq!(result.multiplicity(&'a'), 1, "3 - 2 = 1");
assert_eq!(result.multiplicity(&'b'), 0, "2 - 3 = 0 (not negative)");
assert_eq!(result.multiplicity(&'c'), 0, "1 - 1 = 0");
assert_eq!(result.multiplicity(&'d'), 0, "2 - 2 = 0");
assert_eq!(result.multiplicity(&'e'), 1, "1 - 0 = 1");
assert_eq!(result.multiplicity(&'f'), 0, "0 - 1 = 0 (not negative)");
}
#[test]
fn test_multiset_sum() {
let p = MultiSet::from(vec!['a', 'a', 'b', 'c', 'c']);
let q = MultiSet::from(vec!['a', 'b', 'b', 'd']);
let result = p.sum(&q);
assert_eq!(result.multiplicity(&'a'), 3, "2 + 1 = 3");
assert_eq!(result.multiplicity(&'b'), 3, "1 + 2 = 3");
assert_eq!(result.multiplicity(&'c'), 2, "2 + 0 = 2");
assert_eq!(result.multiplicity(&'d'), 1, "0 + 1 = 1");
}
#[test]
fn test_multiset_to_set() {
let ms = MultiSet::from(vec![1, 1, 1, 2, 2, 3]);
let set = ms.to_set();
assert_eq!(set.cardinality(), 3, "Set should have 3 unique elements");
assert!(set.contains(&1), "Set should contain 1");
assert!(set.contains(&2), "Set should contain 2");
assert!(set.contains(&3), "Set should contain 3");
}
#[test]
fn test_multiset_add_with_count() {
let mut ms = MultiSet::<char>::empty();
ms.add('a', 3);
assert_eq!(ms.multiplicity(&'a'), 3, "Should add 3 'a' elements");
ms.add('a', 2);
assert_eq!(ms.multiplicity(&'a'), 5, "Should add 2 more 'a' elements");
ms.add('b', 1);
assert_eq!(ms.multiplicity(&'b'), 1, "Should add 1 'b' element");
}
#[test]
fn test_multiset_remove_with_count() {
let mut ms = MultiSet::from(vec!['a', 'a', 'a', 'b', 'b']);
ms.remove(&'a', 2);
assert_eq!(ms.multiplicity(&'a'), 1, "Should remove 2 'a' elements");
ms.remove(&'b', 5);
assert_eq!(
ms.multiplicity(&'b'),
0,
"Should remove all 'b' elements (can't go negative)"
);
ms.remove(&'a', 1);
assert_eq!(
ms.multiplicity(&'a'),
0,
"Should remove remaining 'a' element"
);
}
#[test]
fn test_multiset_display() {
let ms = MultiSet::from(vec!['a', 'a', 'a', 'b', 'c']);
let display = format!("{}", ms);
assert!(display.starts_with("{"), "Display should start with {{");
assert!(display.ends_with("}"), "Display should end with }}");
assert!(display.contains("a:3"), "Display should show a:3");
let empty = MultiSet::<i32>::empty();
assert_eq!(
format!("{}", empty),
"∅",
"Empty multiset should display as ∅"
);
}
#[test]
fn test_hardware_procurement_scenario() {
let mut ti = MultiSet::<String>::empty();
ti.add("PC".to_string(), 100);
ti.add("router".to_string(), 40);
ti.add("server".to_string(), 5);
let mut ms = MultiSet::<String>::empty();
ms.add("PC".to_string(), 10);
ms.add("router".to_string(), 7);
ms.add("mainframe".to_string(), 2);
let shareable = ti.union(&ms);
assert_eq!(
shareable.multiplicity(&"PC".to_string()),
100,
"Max(100, 10) = 100"
);
assert_eq!(
shareable.multiplicity(&"router".to_string()),
40,
"Max(40, 7) = 40"
);
assert_eq!(
shareable.multiplicity(&"server".to_string()),
5,
"Max(5, 0) = 5"
);
assert_eq!(
shareable.multiplicity(&"mainframe".to_string()),
2,
"Max(0, 2) = 2"
);
let non_shareable = ti.sum(&ms);
assert_eq!(
non_shareable.multiplicity(&"PC".to_string()),
110,
"100 + 10 = 110"
);
assert_eq!(
non_shareable.multiplicity(&"router".to_string()),
47,
"40 + 7 = 47"
);
let ms_only = ms.difference(&ti);
assert_eq!(
ms_only.multiplicity(&"mainframe".to_string()),
2,
"2 - 0 = 2"
);
assert_eq!(ms_only.multiplicity(&"PC".to_string()), 0, "10 - 100 = 0");
assert_eq!(ms_only.multiplicity(&"router".to_string()), 0, "7 - 40 = 0");
}
#[test]
fn test_multiset_zero_multiplicity() {
let mut ms = MultiSet::from(vec![1, 2, 3]);
ms.add(4, 0);
assert_eq!(
ms.multiplicity(&4),
0,
"Adding 0 elements should not add anything"
);
assert_eq!(ms.unique_count(), 3, "Unique count should not change");
ms.remove(&1, 10);
assert_eq!(
ms.multiplicity(&1),
0,
"Removing more than exists should result in 0"
);
}
#[test]
fn test_multiset_cardinality() {
let ms = MultiSet::from(vec!['a', 'a', 'a', 'b', 'b', 'c', 'd', 'd', 'd', 'd']);
assert_eq!(ms.cardinality(), 10, "Total cardinality should be 10");
assert_eq!(ms.unique_count(), 4, "Unique count should be 4");
assert_eq!(ms.multiplicity(&'a'), 3);
assert_eq!(ms.multiplicity(&'b'), 2);
assert_eq!(ms.multiplicity(&'c'), 1);
assert_eq!(ms.multiplicity(&'d'), 4);
let sum: usize = ['a', 'b', 'c', 'd']
.iter()
.map(|c| ms.multiplicity(c))
.sum();
assert_eq!(
sum,
ms.cardinality(),
"Sum of multiplicities should equal cardinality"
);
}
#[test]
fn test_multiset_iteration() {
let ms = MultiSet::from(vec![1, 1, 1, 2, 2, 3]);
let mut count = 0;
for _ in ms.iter() {
count += 1;
}
assert_eq!(count, 3, "Should iterate over 3 unique elements");
}
#[test]
fn test_multiset_equality() {
let ms1 = MultiSet::from(vec!['a', 'a', 'b', 'c']);
let ms2 = MultiSet::from(vec!['c', 'a', 'b', 'a']);
let ms3 = MultiSet::from(vec!['a', 'b', 'c']);
assert_eq!(
ms1, ms2,
"Multisets with same multiplicities should be equal"
);
assert_ne!(
ms1, ms3,
"Multisets with different multiplicities should not be equal"
);
}