From 8c206a9976994218824b0425348be90034a17f0f Mon Sep 17 00:00:00 2001 From: Sina Sharafzadeh Date: Mon, 18 Jun 2018 17:20:02 +0430 Subject: [PATCH] fix unbound knapsack problem with items more than 1(default value) (#73) --- .../sets/knapsack-problem/Knapsack.js | 5 +- .../__test__/Knapsack.test.js | 50 +++++++++++++++++++ 2 files changed, 54 insertions(+), 1 deletion(-) diff --git a/src/algorithms/sets/knapsack-problem/Knapsack.js b/src/algorithms/sets/knapsack-problem/Knapsack.js index d23e12e0fb..10ce6334b3 100644 --- a/src/algorithms/sets/knapsack-problem/Knapsack.js +++ b/src/algorithms/sets/knapsack-problem/Knapsack.js @@ -165,7 +165,10 @@ export default class Knapsack { const availableWeight = this.weightLimit - this.totalWeight; const maxPossibleItemsCount = Math.floor(availableWeight / currentItem.weight); - if (maxPossibleItemsCount) { + if (maxPossibleItemsCount > currentItem.itemsInStock) { + currentItem.quantity = currentItem.itemsInStock; + this.selectedItems.push(currentItem); + } else if (maxPossibleItemsCount) { currentItem.quantity = maxPossibleItemsCount; this.selectedItems.push(currentItem); } diff --git a/src/algorithms/sets/knapsack-problem/__test__/Knapsack.test.js b/src/algorithms/sets/knapsack-problem/__test__/Knapsack.test.js index 9569908f45..d322445a72 100644 --- a/src/algorithms/sets/knapsack-problem/__test__/Knapsack.test.js +++ b/src/algorithms/sets/knapsack-problem/__test__/Knapsack.test.js @@ -96,6 +96,31 @@ describe('Knapsack', () => { new KnapsackItem({ value: 20, weight: 2 }), // v/w ratio is 10 ]; + const maxKnapsackWeight = 15; + + const knapsack = new Knapsack(possibleKnapsackItems, maxKnapsackWeight); + + knapsack.solveUnboundedKnapsackProblem(); + + expect(knapsack.totalValue).toBe(84 + 20 + 12 + 10 + 5); + expect(knapsack.totalWeight).toBe(15); + expect(knapsack.selectedItems.length).toBe(5); + expect(knapsack.selectedItems[0].toString()).toBe('v84 w7 x 1'); + expect(knapsack.selectedItems[1].toString()).toBe('v20 w2 x 1'); + expect(knapsack.selectedItems[2].toString()).toBe('v10 w1 x 1'); + expect(knapsack.selectedItems[3].toString()).toBe('v12 w3 x 1'); + expect(knapsack.selectedItems[4].toString()).toBe('v5 w2 x 1'); + }); + + it('should solve unbound knapsack problem with items in stock', () => { + const possibleKnapsackItems = [ + new KnapsackItem({ value: 84, weight: 7, itemsInStock: 3 }), // v/w ratio is 12 + new KnapsackItem({ value: 5, weight: 2, itemsInStock: 2 }), // v/w ratio is 2.5 + new KnapsackItem({ value: 12, weight: 3, itemsInStock: 1 }), // v/w ratio is 4 + new KnapsackItem({ value: 10, weight: 1, itemsInStock: 6 }), // v/w ratio is 10 + new KnapsackItem({ value: 20, weight: 2, itemsInStock: 8 }), // v/w ratio is 10 + ]; + const maxKnapsackWeight = 17; const knapsack = new Knapsack(possibleKnapsackItems, maxKnapsackWeight); @@ -109,4 +134,29 @@ describe('Knapsack', () => { expect(knapsack.selectedItems[1].toString()).toBe('v20 w2 x 1'); expect(knapsack.selectedItems[2].toString()).toBe('v10 w1 x 1'); }); + + it('should solve unbound knapsack problem with items in stock and max weight more than sum of all items', () => { + const possibleKnapsackItems = [ + new KnapsackItem({ value: 84, weight: 7, itemsInStock: 3 }), // v/w ratio is 12 + new KnapsackItem({ value: 5, weight: 2, itemsInStock: 2 }), // v/w ratio is 2.5 + new KnapsackItem({ value: 12, weight: 3, itemsInStock: 1 }), // v/w ratio is 4 + new KnapsackItem({ value: 10, weight: 1, itemsInStock: 6 }), // v/w ratio is 10 + new KnapsackItem({ value: 20, weight: 2, itemsInStock: 8 }), // v/w ratio is 10 + ]; + + const maxKnapsackWeight = 60; + + const knapsack = new Knapsack(possibleKnapsackItems, maxKnapsackWeight); + + knapsack.solveUnboundedKnapsackProblem(); + + expect(knapsack.totalValue).toBe((3 * 84) + (2 * 5) + (1 * 12) + (6 * 10) + (8 * 20)); + expect(knapsack.totalWeight).toBe((3 * 7) + (2 * 2) + (1 * 3) + (6 * 1) + (8 * 2)); + expect(knapsack.selectedItems.length).toBe(5); + expect(knapsack.selectedItems[0].toString()).toBe('v84 w7 x 3'); + expect(knapsack.selectedItems[1].toString()).toBe('v20 w2 x 8'); + expect(knapsack.selectedItems[2].toString()).toBe('v10 w1 x 6'); + expect(knapsack.selectedItems[3].toString()).toBe('v12 w3 x 1'); + expect(knapsack.selectedItems[4].toString()).toBe('v5 w2 x 2'); + }); });