PostgreSQL Source Code git master
Loading...
Searching...
No Matches
knapsack.c
Go to the documentation of this file.
1/*-------------------------------------------------------------------------
2 *
3 * knapsack.c
4 * Knapsack problem solver
5 *
6 * Given input vectors of integral item weights (must be >= 0) and values
7 * (double >= 0), compute the set of items which produces the greatest total
8 * value without exceeding a specified total weight; each item is included at
9 * most once (this is the 0/1 knapsack problem). Weight 0 items will always be
10 * included.
11 *
12 * The performance of this algorithm is pseudo-polynomial, O(nW) where W is the
13 * weight limit. To use with non-integral weights or approximate solutions,
14 * the caller should pre-scale the input weights to a suitable range. This
15 * allows approximate solutions in polynomial time (the general case of the
16 * exact problem is NP-hard).
17 *
18 * Copyright (c) 2017-2026, PostgreSQL Global Development Group
19 *
20 * IDENTIFICATION
21 * src/backend/lib/knapsack.c
22 *
23 *-------------------------------------------------------------------------
24 */
25#include "postgres.h"
26
27#include <limits.h>
28
29#include "lib/knapsack.h"
30#include "nodes/bitmapset.h"
31#include "utils/memutils.h"
32
33/*
34 * DiscreteKnapsack
35 *
36 * The item_values input is optional; if omitted, all the items are assumed to
37 * have value 1.
38 *
39 * Returns a Bitmapset of the 0..(n-1) indexes of the items chosen for
40 * inclusion in the solution.
41 *
42 * This uses the usual dynamic-programming algorithm, adapted to reuse the
43 * memory on each pass (by working from larger weights to smaller). At the
44 * start of pass number i, the values[w] array contains the largest value
45 * computed with total weight <= w, using only items with indices < i; and
46 * sets[w] contains the bitmap of items actually used for that value. (The
47 * bitmapsets are all pre-initialized with an unused high bit so that memory
48 * allocation is done only once.)
49 */
51DiscreteKnapsack(int max_weight, int num_items,
52 int *item_weights, double *item_values)
53{
55 "Knapsack",
58 double *values;
60 Bitmapset *result;
61 int i,
62 j;
63
64 Assert(max_weight >= 0);
65 Assert(num_items > 0 && item_weights);
66
67 values = palloc((1 + max_weight) * sizeof(double));
68 sets = palloc((1 + max_weight) * sizeof(Bitmapset *));
69
70 for (i = 0; i <= max_weight; ++i)
71 {
72 values[i] = 0;
73 sets[i] = bms_make_singleton(num_items);
74 }
75
76 for (i = 0; i < num_items; ++i)
77 {
78 int iw = item_weights[i];
79 double iv = item_values ? item_values[i] : 1;
80
81 for (j = max_weight; j >= iw; --j)
82 {
83 int ow = j - iw;
84
85 if (values[j] <= values[ow] + iv)
86 {
87 /* copy sets[ow] to sets[j] without realloc */
88 if (j != ow)
90
92
93 values[j] = values[ow] + iv;
94 }
95 }
96 }
97
99
100 result = bms_del_member(bms_copy(sets[max_weight]), num_items);
101
103
104 return result;
105}
Bitmapset * bms_replace_members(Bitmapset *a, const Bitmapset *b)
Definition bitmapset.c:971
Bitmapset * bms_make_singleton(int x)
Definition bitmapset.c:216
Bitmapset * bms_del_member(Bitmapset *a, int x)
Definition bitmapset.c:867
Bitmapset * bms_add_member(Bitmapset *a, int x)
Definition bitmapset.c:814
Bitmapset * bms_copy(const Bitmapset *a)
Definition bitmapset.c:122
static Datum values[MAXATTR]
Definition bootstrap.c:155
#define Assert(condition)
Definition c.h:873
int j
Definition isn.c:78
int i
Definition isn.c:77
Bitmapset * DiscreteKnapsack(int max_weight, int num_items, int *item_weights, double *item_values)
Definition knapsack.c:51
void * palloc(Size size)
Definition mcxt.c:1387
MemoryContext CurrentMemoryContext
Definition mcxt.c:160
void MemoryContextDelete(MemoryContext context)
Definition mcxt.c:472
#define AllocSetContextCreate
Definition memutils.h:129
#define ALLOCSET_SMALL_SIZES
Definition memutils.h:170
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition palloc.h:124
static int fb(int x)