Add test for Knapsack 0/1 problem and fix "tracing" part of this algorithm.

This commit is contained in:
Dmitry Naimark 2019-04-25 12:37:21 +03:00
parent 94abfec91d
commit 3c7e32370c
2 changed files with 33 additions and 23 deletions

View File

@ -120,30 +120,20 @@ export default class Knapsack {
let itemIndex = this.possibleItems.length - 1; let itemIndex = this.possibleItems.length - 1;
let weightIndex = this.weightLimit; let weightIndex = this.weightLimit;
while (itemIndex > 0) { while (itemIndex >= 0) {
const currentItem = this.possibleItems[itemIndex];
const prevItem = this.possibleItems[itemIndex - 1];
// Check if matrix value came from top (from previous item). // Check if matrix value came from top (from previous item).
// In this case this would mean that we need to include previous item // In this case this would mean that we need to include the topmost item with the
// to the list of selected items. // same max possible value and the same weight to the list of selected items.
if ( while (knapsackMatrix[itemIndex - 1] !== undefined
knapsackMatrix[itemIndex][weightIndex] && knapsackMatrix[itemIndex][weightIndex] === knapsackMatrix[itemIndex - 1][weightIndex]) {
&& knapsackMatrix[itemIndex][weightIndex] === knapsackMatrix[itemIndex - 1][weightIndex] itemIndex -= 1;
) {
// Check if there are several items with the same weight but with the different values.
// We need to add highest item in the matrix that is possible to get the highest value.
const prevSumValue = knapsackMatrix[itemIndex - 1][weightIndex];
const prevPrevSumValue = knapsackMatrix[itemIndex - 2][weightIndex];
if (
!prevSumValue
|| (prevSumValue && prevPrevSumValue !== prevSumValue)
) {
this.selectedItems.push(prevItem);
} }
} else if (knapsackMatrix[itemIndex - 1][weightIndex - currentItem.weight]) {
this.selectedItems.push(prevItem); // If max possible value in the cell is not zero(and not undefined).
weightIndex -= currentItem.weight; if (knapsackMatrix[itemIndex][weightIndex]) {
// Add item to knapsack and decrease remaining weight capacity by item's weight.
this.selectedItems.push(this.possibleItems[itemIndex]);
weightIndex -= this.possibleItems[itemIndex].weight;
} }
itemIndex -= 1; itemIndex -= 1;

View File

@ -44,6 +44,26 @@ describe('Knapsack', () => {
expect(knapsack.selectedItems[1].toString()).toBe('v4 w3 x 1'); expect(knapsack.selectedItems[1].toString()).toBe('v4 w3 x 1');
}); });
it('should solve 0/1 knapsack problem 2', () => {
const possibleKnapsackItems = [
new KnapsackItem({ value: 5, weight: 3 }),
new KnapsackItem({ value: 3, weight: 2 }),
new KnapsackItem({ value: 4, weight: 1 }),
];
const maxKnapsackWeight = 5;
const knapsack = new Knapsack(possibleKnapsackItems, maxKnapsackWeight);
knapsack.solveZeroOneKnapsackProblem();
expect(knapsack.totalValue).toBe(9);
expect(knapsack.totalWeight).toBe(4);
expect(knapsack.selectedItems.length).toBe(2);
expect(knapsack.selectedItems[0].toString()).toBe('v5 w3 x 1');
expect(knapsack.selectedItems[1].toString()).toBe('v4 w1 x 1');
});
it('should solve 0/1 knapsack problem with impossible items set', () => { it('should solve 0/1 knapsack problem with impossible items set', () => {
const possibleKnapsackItems = [ const possibleKnapsackItems = [
new KnapsackItem({ value: 5, weight: 40 }), new KnapsackItem({ value: 5, weight: 40 }),