The Knapsack Problem Is All Around Us
smithsonianmag.com
smithsonianmag.com
Once upon a time, I had a 4x8 sheet of small plastic parts to route out on a ShopBot. The naive layout from the vector drawing program was incredibly inefficient, and we ended up downloading a general-purpose traveling-salesman-solver written in Java.
It converged upon a dramatically better solution in a few seconds, and didn't really improve it in the next few minutes. So we just stopped it and ran the good-enough route, while leaving the solver running for two days out of pure curiosity.
Now, it was visibly not perfect, there were a couple skips where we could see a shorter way to do it. And it did eventually find those routes.
So if all you need is a reasonable route for your traveling salespersons, or an acceptably efficient packing arrangement for your shipping container, this is achievable and easy, if you're willing to leave that last 1-2% sitting on the table.
Still these type of problems are much trickier in practise, e.g. with time windows or even with multiple salesmen (then it is a vehicle routing problem).
For these problems still specialized software exists like jsprit (shameless plug!) and others:
https://github.com/graphhopper/jsprit/blob/master/docs/Other...
You don’t know if you’ve converged on THE solution but you can know you have a solution.
Which in turn is, I think, a manifestation of the Secretary Problem.
Piece of cake I thought. After a couple hours of fruitless coding I realized some research might help. After a few more hours of googling, I finally figured out the name for this type of problem. Actually, I first came across the term "subset sum problem" which led to "knapsack problem". That led to an introduction to the concept of "nondeterministic polynomial time".
Eventually I found a diophantine algorithm someone had written in Rexx and managed to translate it to Python. It worked! Sorta. (I was surprised by how many different matching combinations a random set of numbers could generate for a given value.)
By the time I returned to my sister with my solution, I think she had found a Excel plugin that did it for her.
Then I remembered to ask: how many things are you going to sort? He said 10. Always 10.
So, yeah. I didn't really even know the answer at the time.
I'm not sure what brute-forcing means in this context. Do you mean hard-coding every way to order 10 unique elements?
My mental algorithm is:
1) Set a value/weight ratio above which new items are picked up
2) If I run out of space and find something above that threshold, start dropping the worst-ratio'd items to make room
3) Raise the threshold accordingly
4) Repeat
Your bag can hold 10 kg. Item a weighs 10kg and is worth $10. Item b weighs 5kg and is worth $6.
Item b is more value dense, but picking up item a is optimal.
In videogames, making the user GC isn't fun, and therefore reducing the number of GCs is more optimal than strictly solving the problem.
Item B is better than item A, even when you're just choosing from those two items, because more items will come along later to fill the space that item B leaves empty.
Here's a more explicit description of the problem space:
- Items arrive in a stream.
- Picking up an item is free.
- Overlooking an item is free.
- Discarding an item is expensive.
- Once an item is overlooked or discarded, it can't be picked back up.
What you're trying to do is finish the stream with the most valuable knapsack without having to go through too much discarding. An item that fills your entire inventory can never be worth picking up, unless it has an awesome value/space ratio, because picking up any other item guarantees that you have to discard that one.
I would call this the "Diablo I" problem.
"Optimizing your solution ensures someone else can't come into your industry, get the same suppliers and contract terms, and beat you"
We then went through an example for an oil refinery with different sources of oil (differing proportions of sweet and sour, and quantities available), refinery production constraints, and market prices for different end products. He showed the difference between a "naive manual optimization" and the mathematical optimal.
Ever since that class, I'm particular about what "optimize" means. Factories talk about optimizing many things at the same time (on-time delivery, profit, throughput on a machine, throughput on the bottleneck machine, minimizing labor). I can't tell you how many times I've said "pick one thing to optimize - you're not going to hit them all at once". You can make an objective function a weighting of all those factors, but they won't all be at their best possible values.
What to optimize is actually probably one of the most interesting optimization problems out there. In a factory you always need to search for the bottleneck. That's why I think Kaizen is so important. Apply incremental optimization to the biggest issues and you will succeed.
Since I had not much time left I switched to an inefficient brute force approach, basically a test of all possible combinations, which wasn't well received by the interviewer back then since he was expecting a recursive dynamic solution [2].
When I started a blog last year I decided to revisit this problem while writing about complexity classes of problems, and tried to demonstrate how to translate a solver to the Knapsack problem for solving another NP-complete problem, the partition problem [3] ;)
It's indeed a very interesting and fun problem to tackle!
[1] https://en.wikipedia.org/wiki/Knapsack_problem#Greedy_approx...
[2] https://github.com/TCGV/Knapsack/blob/master/Tcgv.Combinator...
[3] https://thomasvilhena.com/2019/08/complexity-classes-of-prob...
To factorize integer N invoke a Knapsack solver with knapsack size of log(N) and items of size logarithm of all prime numbers up to sqrt(N): [log 2, log 3, log 5, ...].
If N=pq (say p and q are prime) then log(N)=log(p)+log(q).
So from all possible items in the item set, only log(p) and log(q) will fill the knapsack as tight as possible leaving zero empty space in it.
[1]: https://en.wikipedia.org/wiki/Merkle%E2%80%93Hellman_knapsac...
If I have a set of retail promotional offers going such as:
Offer 1: buy two shirts from this set of shirts, and get a 50% discount
Offer 2: buy a shirt from this set of shirts, a jacket from this set of jackets, and a tie from this set of ties all for a set price of $99
Offer 3: all ties are on sale at half price
I'm trying to figure out if the google libraries linked above can be used to solve this problem, but I can't figure out how to convert the offers into values that can be used by the google library...