Skip to content

Commit

Permalink
✨ feat(integerValuesKnapsackUnbounded): First draft.
Browse files Browse the repository at this point in the history
  • Loading branch information
make-github-pseudonymous-again committed Oct 13, 2020
1 parent 21699cb commit 42ff4a8
Show file tree
Hide file tree
Showing 3 changed files with 58 additions and 1 deletion.
3 changes: 3 additions & 0 deletions src/index.js
Original file line number Diff line number Diff line change
@@ -1,18 +1,21 @@
import integerValuesKnapsack from './integerValuesKnapsack';
import integerValuesKnapsackUnbounded from './integerValuesKnapsackUnbounded';
import integerWeightsKnapsack from './integerWeightsKnapsack';
import integerWeightsKnapsackUnbounded from './integerWeightsKnapsackUnbounded';
import knapsackApprox from './knapsackApprox';

/* eslint import/no-anonymous-default-export: [2, {"allowObject": true}] */
export default {
integerValuesKnapsack,
integerValuesKnapsackUnbounded,
integerWeightsKnapsack,
integerWeightsKnapsackUnbounded,
knapsackApprox,
};

export {
integerValuesKnapsack,
integerValuesKnapsackUnbounded,
integerWeightsKnapsack,
integerWeightsKnapsackUnbounded,
knapsackApprox,
Expand Down
47 changes: 47 additions & 0 deletions src/integerValuesKnapsackUnbounded.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import assert from 'assert';
import {increasing} from '@aureooms/js-compare';
import {max, map, range} from '@aureooms/js-itertools';

const integerValuesKnapsackUnbounded = (
v,
w,
n,
W,
V = Math.floor(
W *
max(
increasing,
map((i) => v[i] / w[i], range(n)),
),
),
m = new w.constructor(V + 1).fill(W + 1),
) => {
assert(v.length === n);
assert(w.length === n);
assert(Number.isInteger(V) && V >= 0);
assert(m.length >= V + 1);
m[0] = 0;
for (let j = 1; j <= V; ++j) {
let temporary = m[j];
for (let i = 0; i < n; ++i) {
const wi = w[i];
const vi = v[i];
assert(Number.isInteger(vi) && vi >= 0);
const k = j - vi;
// TODO sort by value to avoid branching
// from larger to smaller so that m is scanned
// from left to right
if (k >= 0) temporary = Math.min(temporary, m[k] + wi);
}

m[j] = temporary;
}

for (let j = V; j > 0; --j) {
if (m[j] <= W) return j;
}

return 0;
};

export default integerValuesKnapsackUnbounded;
9 changes: 8 additions & 1 deletion test/src/unbounded-knapsack-problem.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,10 @@ import test from 'ava';

import {all, map} from '@aureooms/js-itertools';

import {integerWeightsKnapsackUnbounded} from '../../src';
import {
integerValuesKnapsackUnbounded,
integerWeightsKnapsackUnbounded,
} from '../../src';

const macro = (t, solve, _name, v, w, n, W, opt, approx) => {
t.is(n, v.length);
Expand All @@ -27,6 +30,10 @@ macro.title = (title, solve, name, v, w, n, W, opt, approx) =>
)}, ${n}, ${W}) >= ${approx} * ${opt}`;

const solvers = [
{
solve: integerValuesKnapsackUnbounded,
hypothesis: (v) => all(map((x) => Number.isInteger(x), v)),
},
{
solve: integerWeightsKnapsackUnbounded,
hypothesis: (_, w) => all(map((x) => Number.isInteger(x), w)),
Expand Down

0 comments on commit 42ff4a8

Please sign in to comment.