Skip to content

Commit 805aa83

Browse files
committed
Knapsack by value
1 parent 3914025 commit 805aa83

File tree

4 files changed

+176
-15
lines changed

4 files changed

+176
-15
lines changed

General/Knapsack.cpp

Lines changed: 131 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
#include <algorithm>
22
#include <iostream>
33

4+
#include "Matrix.h"
45
#include "Knapsack.h"
56

67
Knapsack::Item::Item():
@@ -40,20 +41,24 @@ Knapsack::Item& Knapsack::Item::operator=(Item&& i)
4041
return *this;
4142
}
4243

43-
Knapsack::ItemScore::ItemScore():
44+
Knapsack::ItemScore::ItemScore(const uint32_t idx) :
45+
m_idx(idx),
4446
m_set(false),
4547
m_val(0)
4648
{}
4749

48-
Knapsack::ItemScore::ItemScore(double val):
50+
Knapsack::ItemScore::ItemScore(const uint32_t idx, double val) :
51+
m_idx(idx),
4952
m_set(true),
5053
m_val(val)
5154
{}
5255

5356
Knapsack::ItemScore::ItemScore(ItemScore&& itemScore):
57+
m_idx(itemScore.m_idx),
5458
m_set(itemScore.m_set),
5559
m_val(itemScore.m_val)
5660
{
61+
itemScore.m_idx = 0;
5762
itemScore.m_set = false;
5863
itemScore.m_val = 0;
5964
}
@@ -64,13 +69,65 @@ Knapsack::ItemScore& Knapsack::ItemScore::operator=(ItemScore&& itemScore)
6469
{
6570
return *this;
6671
}
72+
m_idx = itemScore.m_idx;
6773
m_set = itemScore.m_set;
6874
m_val = itemScore.m_val;
75+
itemScore.m_idx = 0;
6976
itemScore.m_set = false;
7077
itemScore.m_val = 0;
7178
return *this;
7279
}
7380

81+
bool Knapsack::ItemScore::operator<(const ItemScore& itemScore)
82+
{
83+
return m_val < itemScore.m_val;
84+
}
85+
86+
Knapsack::Entity::Entity():
87+
m_set(false),
88+
m_val(0)
89+
{}
90+
91+
Knapsack::Entity::Entity(const uint32_t val):
92+
m_set(true),
93+
m_val(val)
94+
{}
95+
96+
Knapsack::Entity::Entity(Entity&& entity) :
97+
m_set(entity.m_set),
98+
m_val(entity.m_val)
99+
{
100+
entity.m_set = false;
101+
entity.m_val = 0;
102+
}
103+
104+
Knapsack::Entity& Knapsack::Entity::operator=(Entity&& entity)
105+
{
106+
if (this == &entity)
107+
{
108+
return *this;
109+
}
110+
m_set = entity.m_set;
111+
m_val = entity.m_val;
112+
entity.m_set = false;
113+
entity.m_val = 0;
114+
return *this;
115+
}
116+
117+
std::ostream& operator<< (std::ostream& out, const Knapsack::Entity& entity)
118+
{
119+
if (entity.m_set)
120+
{
121+
out << entity.m_val;
122+
}
123+
else
124+
{
125+
out << -1;
126+
}
127+
out << ';';
128+
return out;
129+
}
130+
74131
Knapsack::Knapsack()
75132
{
76133
}
@@ -126,7 +183,7 @@ bool Knapsack::run(
126183

127184
res = knapsack[numItems][m_maxWeight - 1];
128185

129-
// TODO: backpropagation
186+
// backpropagation
130187
uint32_t currentWieght = m_maxWeight;
131188
for (uint32_t i = numItems; i > 0; --i)
132189
{
@@ -143,7 +200,70 @@ bool Knapsack::run(
143200
return true;
144201
}
145202

146-
bool Knapsack::runGreedy(uint32_t &res)
203+
bool Knapsack::runByValue(uint32_t& res, ItemsList& resList)
204+
{
205+
auto it = std::max_element(m_items.begin(), m_items.end(), [](const Item& i1, const Item& i2) -> bool {
206+
return i1.m_value < i2.m_value;
207+
});
208+
uint32_t maxValue = it->m_value;
209+
uint32_t numOfItems = static_cast<uint32_t>(m_items.size());
210+
Matrix<Entity> knapsackMatrix;
211+
knapsackMatrix.resize(numOfItems + 1, numOfItems * maxValue + 1);
212+
213+
Entity minEntity;
214+
Entity tmpVal;
215+
knapsackMatrix[0][0] = std::move(Entity(0));
216+
for (uint32_t i = 1; i <= numOfItems; ++i)
217+
{
218+
for (uint32_t x = 0; x <= numOfItems * maxValue; ++x)
219+
{
220+
tmpVal = ((m_items[i - 1].m_value < x) ? knapsackMatrix[i - 1][x - m_items[i - 1].m_value] : Entity(0));
221+
minEntity = knapsackMatrix[i - 1][x];
222+
223+
if (tmpVal.m_set &&
224+
((!minEntity.m_set) ||
225+
(minEntity.m_val > m_items[i - 1].m_weight + tmpVal.m_val)))
226+
{
227+
minEntity.m_set = true;
228+
minEntity.m_val = m_items[i - 1].m_weight + tmpVal.m_val;
229+
}
230+
knapsackMatrix[i][x] = std::move(minEntity);
231+
}
232+
}
233+
// debug
234+
/*std::ofstream fout("knapsack.csv");
235+
fout << knapsackMatrix << std::endl;*/
236+
237+
res = 0;
238+
for (uint32_t x = 0; x <= numOfItems * maxValue; ++x)
239+
{
240+
if (knapsackMatrix[numOfItems][x].m_set &&
241+
knapsackMatrix[numOfItems][x].m_val <= m_maxWeight)
242+
{
243+
res = x;
244+
}
245+
}
246+
247+
// TODO: backpropagation
248+
uint32_t currVal = res;
249+
for (uint32_t i = numOfItems; i > 0; --i)
250+
{
251+
if ((m_items[i - 1].m_value <= currVal) &&
252+
knapsackMatrix[i - 1][currVal - m_items[i - 1].m_value].m_set)
253+
{
254+
if (knapsackMatrix[i][currVal].m_val ==
255+
knapsackMatrix[i - 1][currVal - m_items[i - 1].m_value].m_val + m_items[i - 1].m_weight)
256+
{
257+
currVal -= m_items[i - 1].m_value;
258+
resList.push_front(m_items[i - 1]);
259+
}
260+
}
261+
}
262+
263+
return true;
264+
}
265+
266+
bool Knapsack::runGreedy(uint32_t &res, ItemsList& resList)
147267
{
148268

149269
std::vector<ItemScore> itemsScores;
@@ -155,19 +275,19 @@ bool Knapsack::runGreedy(uint32_t &res)
155275
{
156276
if (m_items[i].m_weight != 0)
157277
{
158-
itemsScores.push_back(std::move(ItemScore(m_items[i].m_value / m_items[i].m_weight)));
278+
itemsScores.push_back(std::move(ItemScore(i, static_cast<double>(m_items[i].m_value) / m_items[i].m_weight)));
159279
}
160280
else
161281
{
162-
itemsScores.push_back(std::move(ItemScore()));
282+
itemsScores.push_back(std::move(ItemScore(i)));
163283
}
164284
}
165285
std::sort(itemsScores.begin(), itemsScores.end());
166286
// debug
167-
for (auto& itemScore : itemsScores)
287+
/*for (auto& itemScore : itemsScores)
168288
{
169289
std::cout << itemScore.m_val << std::endl;
170-
}
290+
}*/
171291

172292
res = 0;
173293
uint32_t currentWeight = 0;
@@ -181,6 +301,7 @@ bool Knapsack::runGreedy(uint32_t &res)
181301
{
182302
currentWeight += m_items[itemScore.m_idx].m_weight;
183303
res += m_items[itemScore.m_idx].m_value;
304+
resList.push_back(m_items[itemScore.m_idx]);
184305
}
185306
}
186307

@@ -190,6 +311,8 @@ bool Knapsack::runGreedy(uint32_t &res)
190311
(item.m_value > res))
191312
{
192313
res = item.m_value;
314+
resList.clear();
315+
resList.push_back(item);
193316
}
194317
}
195318

General/Knapsack.h

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -27,12 +27,24 @@ class Knapsack
2727
bool m_set;
2828
double m_val;
2929
uint32_t m_idx;
30-
ItemScore();
31-
ItemScore(double val);
30+
ItemScore(const uint32_t idx);
31+
ItemScore(const uint32_t idx, double val);
3232
ItemScore(ItemScore&& itemScore);
3333
ItemScore& operator=(ItemScore&& itemScore);
34+
bool operator<(const ItemScore& itemScore);
3435
};
35-
36+
37+
struct Entity
38+
{
39+
bool m_set;
40+
uint32_t m_val;
41+
Entity();
42+
Entity(const uint32_t val);
43+
Entity(Entity&& entity);
44+
Entity& operator=(Entity&& entity);
45+
};
46+
friend std::ostream& operator<< (std::ostream& out, const Entity& entity);
47+
3648
uint32_t m_maxWeight;
3749
ItemsVec m_items;
3850

@@ -42,7 +54,8 @@ class Knapsack
4254

4355
bool read(std::istream& in);
4456
bool run(uint32_t& res, ItemsList& resList);
45-
bool runGreedy(uint32_t &res);
57+
bool runByValue(uint32_t& res, ItemsList& resList);
58+
bool runGreedy(uint32_t &res, ItemsList& resList);
4659
};
4760

4861
#endif // KNAPSACK_H

test/knapsack.in

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
84 85
1010
87 89
1111
72 82
12-
12+
165
1313

1414
309
1515
1

test/main.cpp

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,33 @@ void knapsackFunc()
2626
exit(2);
2727
}
2828
uint32_t val = 0;
29-
knapsack.run(165, val);
29+
Knapsack::ItemsList resList;
30+
knapsack.run(val, resList);
3031
std::cout << val << std::endl;
32+
for (auto& item : resList)
33+
{
34+
std::cout << "< Weight : " << item.m_weight << " ; Value : " << item.m_value << " >" << std::endl;
35+
}
36+
37+
std::cout << "#######################################" << std::endl;
38+
std::cout << "GREEDY" << std::endl;
39+
resList.clear();
40+
knapsack.runGreedy(val, resList);
41+
std::cout << val << std::endl;
42+
for (auto& item : resList)
43+
{
44+
std::cout << "< Weight : " << item.m_weight << " ; Value : " << item.m_value << " >" << std::endl;
45+
}
46+
47+
std::cout << "#######################################" << std::endl;
48+
std::cout << "BY VALUE" << std::endl;
49+
resList.clear();
50+
knapsack.runByValue(val, resList);
51+
std::cout << val << std::endl;
52+
for (auto& item : resList)
53+
{
54+
std::cout << "< Weight : " << item.m_weight << " ; Value : " << item.m_value << " >" << std::endl;
55+
}
3156

3257
std::cin.get();
3358
}
@@ -228,7 +253,7 @@ void TspFunc()
228253

229254
int main(int argc, const char * argv[])
230255
{
231-
TspFunc();
256+
knapsackFunc();
232257

233258
return 0;
234259
}

0 commit comments

Comments
 (0)