I am working on a bin packing problem using OR-Tools and the SCIP solver. I have followed the guide provided by Google on bin packing (Google OR-Tools Bin Packing Guide).
I have successfully implemented the algorithm and achieved the objective of minimizing the number of bins used. Additionally, I have incorporated capacity constraints to ensure that the amount packed in each bin does not exceed its capacity (based on CBM and weight).
However, I'm facing difficulties in modifying the algorithm to further minimize the number of suppliers in bins. My goal is to ensure that items from the same supplier are placed in the same bin whenever possible. However, if all the items from the same supplier exceed the bin's capacity (CBM or weight), I am willing to split them across multiple bins.
I have tried several approaches but haven't been able to find a suitable solution. I would appreciate any guidance or suggestions on how to modify the code to achieve this requirement. Specifically, I need help in adapting the constraints and the objective function.
Here is an excerpt of the relevant code:
def __variables__(self):
# Variables
# x[i, j] = 1 if item i is packed in bin j.
x = {}
for i in self.model['data']:
for j in self.model['bins']:
x[(i, j)] = self.solver.IntVar(0, 1, 'x_%i_%i' % (i, j))
# y[j] = 1 if bin j is used.
y = {}
for j in self.model['bins']:
y[j] = self.solver.IntVar(0, 1, 'y[%i]' % j)
self.variables = [x, y]
def __constraints__(self):
if not self.variables or not self.solver:
return
x = self.variables[0]
y = self.variables[1]
# Constraints
# Each item must be in exactly one bin.
for i in self.model['data']:
self.solver.Add(sum(x[i, j] for j in self.model['bins']) == 1)
# The amount packed in each bin cannot exceed its capacity.
for j in self.model['bins']:
self.solver.Add(
sum(x[(i, j)] * self.model['cbms'][i] for i in self.model['data']) <= y[j] *
self.model['bin_capacity_cbm'])
self.solver.Add(
sum(x[(i, j)] * self.model['weights'][i] for i in self.model['data']) <= y[j] *
self.model['bin_capacity_weight'])
# Objective: minimize the number of bins used.
self.solver.Minimize(self.solver.Sum(
[y[j] for j in self.model['bins']]))
# solver.Minimize(solver.Sum([ model['cbms'][j] for j in model['bins'] for i in model['suppliers'] if z[(j, i)] in model['bins'][i])])
def create_model(self) -> Dict[str, List]:
model = {'data': [], 'cbms': [], 'weights': [],
'items': [], 'suppliers': []}
# Iterate through each item
for item in self.items:
model['weights'].append(item[WEIGHT])
model['cbms'].append(item[CBM])
model['items'].append(item)
model['suppliers'].append(item[SUPPLIER])
# Set the 'items' list as a range of indices based on the length of 'cbms'
model['data'] = list(range(len(model['cbms'])))
model['bins'] = model['data']
model['bin_capacity_cbm'] = MAX_CBM
model['bin_capacity_weight'] = MAX_WEIGHT
self.model = model
Here is my input list of items:
data = [
{
'asin': '...',
'cbm': 0.728,
'how_many_cartons': ...,
'how_many_to_ship': '...',
'optional': '',
'port': 'Tianjin',
'product_name': '...',
'ready_date': '6/30/2023',
'sku': '...',
'supplier': 'HEBEI HOUDE HANFANG MEDICAL DEVICES GROUP CO.,LTD',
'weight': 163.8
},
{
'asin': '...',
'cbm': 11.392,
'how_many_cartons': ...,
'how_many_to_ship': '...',
'optional': '',
'port': 'Shenzhen',
'product_name': '...',
'ready_date': 'Ready',
'sku': '...',
'supplier': 'HEBEI HOUDE HANFANG MEDICAL DEVICES GROUP CO.,LTD',
'weight': 7048.8
},
{
'asin': '...',
'cbm': 5.6,
'how_many_cartons': ...,
'how_many_to_ship': '...',
'optional': '',
'port': 'Shenzhen',
'product_name': '...',
'ready_date': 'Ready',
'sku': '...',
'supplier': 'HongTaiDingYe',
'weight': 1666.0
},
{
'asin': '...',
'cbm': 0.08,
'how_many_cartons': ...,
'how_many_to_ship': '...',
'optional': '',
'port': 'Shenzhen',
'product_name': '...',
'ready_date': '6/30/2023',
'sku': '...',
'supplier': 'HongTaiDingYe',
'weight': 35.6
}
]
So, for each supplier and each bin, you need a Boolean variable that will be True if the supplier is present in the bin.
So, we will use the standard encoding for this:
Now you can use the newly created
supplier_presentvariables in your objective, or in dedicated constraints.