-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathknapsack.c
155 lines (118 loc) · 3.09 KB
/
knapsack.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
/////////////
//Knapsack definitions
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include <math.h>
#include "knapsack.h"
#include "item.h"
#include "util.h"
inline void Knapsack_initCapacity(Restr *cap)
{
for(RestrId i = 0; i < NUM_RESTRICTIONS; i++)
{
cap[i] = cap_init[i];
}
}
/**
* Sets the memory of k to that of a default knapsack
*/
void Knapsack_init(struct Knapsack *k)
{
memcpy(k, &k_init, sizeof(*k));
k->capacity = malloc(sizeof(*k->capacity) * NUM_RESTRICTIONS);
Knapsack_initCapacity(k->capacity);
k->has_item = calloc(sizeof(*k->has_item), NUM_ITEMS);
}
void Knapsack_destroy(struct Knapsack *k)
{
free(k->has_item);
free(k->capacity);
}
inline bool Knapsack_canAddItem(struct Knapsack *k, ItemId i)
{
if(k->has_item[i]) return false;
//struct Item *item = &universe[i];
for(RestrId c = 0; c < NUM_RESTRICTIONS; c++)
{
if(k->capacity[c] < universe[i].restrictions[c]){
return false;
}
}
return true;
}
void Knapsack_addItem(struct Knapsack *k, ItemId itemid)
{
assert(itemid < NUM_ITEMS);
for(RestrId c = 0; c < NUM_RESTRICTIONS; c++)
{
k->capacity[c] -= universe[itemid].restrictions[c];
}
k->has_item[itemid] = true;
k->worth += universe[itemid].value;
k->num_items++;
}
struct Neighbour *createNeighbour(struct Knapsack *k)
{
//iterate over all items and add to the neighbourhood
//only the items that can be added to the knapsack k
//allocate only as much space as necessary, multiplying by 2 each time
struct Neighbour *n = malloc(sizeof(*n));
//n->items = malloc(sizeof(*(n->items)));
n->items = malloc(sizeof(*n->items)*NUM_ITEMS);
n->size = 0;
//n->cap = 1; //neighbour array capacity
n->cap = NUM_ITEMS;
size_t j = 0; //neighbour iterator
PherDes sum = 0.0;
for(ItemId i = 0; i < NUM_ITEMS; i++)
{
if(!Knapsack_canAddItem(k, i)){
continue;
}
/*
if(j >= n->cap)
{
n->cap *= 2;
n->items = realloc(n->items, sizeof(*(n->items)) * n->cap);
}
*/
n->items[j] = (struct K_item_prob){
.itemid = i,
.prob = universe[i].pdValue
};
sum += universe[i].pdValue;
n->size++;
j++;
}
//normalize probabilities
for(size_t i = 0; i < n->size; i++)
{
n->items[i].prob = (Prob)(n->items[i].prob/sum);
}
return n;
}
void deleteNeighbour(struct Neighbour *n)
{
free(n->items);
free(n);
}
inline int32_t Neighbour_search(struct Neighbour *n, double search_val)
{
/* Sequential Search */
for(size_t i = 0; i < n->size; i++)
{
search_val -= n->items[i].prob;
if(search_val <= 0) return (int32_t)i;
}
return (int32_t)(n->size-1);
}
//Select a single item at random from a neighbour
//and return its ID
ItemId Neighbour_randSelect(struct Neighbour *n)
{
double r = rand_double(0.0, 1.0);
int32_t nid = Neighbour_search(n, r);
return n->items[nid].itemid;
}