I was asked to research possible solutions to a problem that is as follows: We have a certain number of "bins" (~50 of them). Every bin has its own capacity. Every bin can only take items from some specific types. Items have the type and their weight (which lowers the bin's capacity after being stored). What I'm aiming to achieve is a situation in which all the items are assigned "evenly" (I will discuss it in a second) over the bins. It might happen though, that bins won't be able of storing all the items in them because sum of the item's weights will be greater than sum of the bins' capacities. In such a situation I want the script to be able of going over the bins' limit.
What I meant by "evenly" is to, when comparing between bins, take percentage of bin's filled space rather than the amount of items stored in each bin. So, even though that bin 1 has only one item and bin 2 has 10 items then we call it evenly, because in both situations bins were filled to 60% of their capacity. This also applies when bins are overfilled.
At first this seemed as a multiple knapsack problem to me, but those custom constraints (and the overfilling aspect) make me think that this might not be the best approach. Is it even possible to find an exact solution to this (or an algorithm) or does it need some approach like using ML and hoping to find somehow-optimal solutions?
@Edit: I was asked to, if possible, add a sample, anonymized data, so I'll do my best to somehow show the problem.
Let's say, that we have a set of bins as follows:
- A: capacity: 1, types: a, b,
- B: capacity: 0.5, types: b,
- C: capacity: 0.5, types: a,
- D: capacity: 0.75, types: c
- E: capacity: 0.4, types: a, b, c
The thing is - capacity is always a number between 0 and 1 and there are multiple types of things that can get to a bin: a bin can either take one type of items to it or multiple.
Now, let's say we have some sample set of items:
- a: weight: 0.1, type: a,
- b: weight: 0.75, type: b,
- c: weight: 0.5, type: a,
- d: weight: 0.1, type: c,
- e: weight: 0.25, type: a,
- f: weight: 0.1, type: b
You can easily see that every item has its weight and type (only one per item).
Now, what we want to achieve is to create a set of bin:set_of_items (like, A -> {a, b}) in which the the distribution of items over bins create a situation in which every bin is, possibly, full to the same percentage of it's capacity (so like, every bin would be full to ~60%) but most importantly all items are distributed - even if this means that we will overfill bins.
Few things to notice from that - there are situations in which bins' capacity is really small, however it is almost certain that the granularity of data is such that every bin will hold at least one item. There can be a situation in which sum_of_bins_capacities<sum_of_items_weights and we will have to overfill the bins - that's fine.
It's really hard for me to provide some reasonable dummy data set but I hope this will make a problem a little bit clearer.