Skip to content

Commit 3d0898c

Browse files
zazabapclaude
andcommitted
fix: add Knapsack re-export and edge-case tests
- Re-export Knapsack from models/mod.rs (structural review finding) - Add tests: zero capacity, single item, greedy-not-optimal adversarial case Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent c189700 commit 3d0898c

2 files changed

Lines changed: 36 additions & 1 deletion

File tree

src/models/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,5 +15,5 @@ pub use graph::{
1515
BicliqueCover, KColoring, MaxCut, MaximalIS, MaximumClique, MaximumIndependentSet,
1616
MaximumMatching, MinimumDominatingSet, MinimumVertexCover, SpinGlass, TravelingSalesman,
1717
};
18-
pub use misc::{BinPacking, Factoring, PaintShop};
18+
pub use misc::{BinPacking, Factoring, Knapsack, PaintShop};
1919
pub use set::{MaximumSetPacking, MinimumSetCovering};

src/unit_tests/models/misc/knapsack.rs

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,41 @@ fn test_knapsack_serialization() {
8686
assert_eq!(restored.capacity(), problem.capacity());
8787
}
8888

89+
#[test]
90+
fn test_knapsack_zero_capacity() {
91+
// Capacity 0: only empty set is feasible
92+
let problem = Knapsack::new(vec![1, 2], vec![10, 20], 0);
93+
assert_eq!(problem.evaluate(&[0, 0]), SolutionSize::Valid(0));
94+
assert_eq!(problem.evaluate(&[1, 0]), SolutionSize::Invalid);
95+
let solver = BruteForce::new();
96+
let solution = solver.find_best(&problem).unwrap();
97+
assert_eq!(problem.evaluate(&solution), SolutionSize::Valid(0));
98+
}
99+
100+
#[test]
101+
fn test_knapsack_single_item() {
102+
// Single item that fits
103+
let problem = Knapsack::new(vec![3], vec![5], 3);
104+
assert_eq!(problem.evaluate(&[1]), SolutionSize::Valid(5));
105+
assert_eq!(problem.evaluate(&[0]), SolutionSize::Valid(0));
106+
let solver = BruteForce::new();
107+
let solution = solver.find_best(&problem).unwrap();
108+
assert_eq!(problem.evaluate(&solution), SolutionSize::Valid(5));
109+
}
110+
111+
#[test]
112+
fn test_knapsack_greedy_not_optimal() {
113+
// Classic case where greedy by value/weight ratio is suboptimal:
114+
// Item 0: w=6, v=7, ratio=1.17 (greedy picks this first, then nothing else fits)
115+
// Item 1: w=5, v=5, ratio=1.00
116+
// Item 2: w=5, v=5, ratio=1.00
117+
// Capacity=10. Greedy: {0} value=7. Optimal: {1,2} value=10.
118+
let problem = Knapsack::new(vec![6, 5, 5], vec![7, 5, 5], 10);
119+
let solver = BruteForce::new();
120+
let solution = solver.find_best(&problem).unwrap();
121+
assert_eq!(problem.evaluate(&solution), SolutionSize::Valid(10));
122+
}
123+
89124
#[test]
90125
#[should_panic(expected = "weights and values must have the same length")]
91126
fn test_knapsack_mismatched_lengths() {

0 commit comments

Comments
 (0)