[英]Google OR-Tools bin-packing problem: struggling to add constraint such that all items packed in bin MUST have same delivery destination
As the title suggests, I am using Google OR-Tools to tackle a bin-packing problem.正如标题所示,我正在使用 Google OR-Tools 来解决装箱问题。 I would like to require that all orders packed into a given truck have the same delivery destination.
我想要求装在给定卡车中的所有订单都具有相同的交货目的地。 The following is my attempt at implementing this, which doesn't seem to be working:
以下是我尝试实现这一点,但似乎没有用:
# x[i, j] = 1 if item i is packed in bin j
x = {}
for i in data['orders']:
for j in data['trucks']:
x[(i, j)] = solver.IntVar(0, 1, 'x_%i_%i' % (i, j))
data['trucks'] = [0, 1, 2, 3, ...]
data['orders'] = [0, 1, 2, 3, ...]
data['delivery_county_id'] = [8, 8, 8, 1, 3, 2, ...]
from itertools import groupby
# Checks if all elements of list are equal
def all_equal(iterable):
g = groupby(iterable)
return next(g, True) and not next(g, False)
for j in data['trucks']:
solver.Add( all_equal ( [ x[(i, j)] * data['delivery_county_id'][i] for i in data['orders'] if x[(i, j)] == 1 ] ) == True )
Strangely, I am not getting any errors when I execute the code, but my constraint is not being obeyed.奇怪的是,我在执行代码时没有收到任何错误,但我的约束没有得到遵守。 I'm not sure why that is.
我不确定为什么会这样。 Any assistance or suggestions would be profoundly appreciated!
任何帮助或建议将不胜感激!
I don't have a working Python installation, but this is how it could be done in c#:我没有有效的 Python 安装,但这是在 c# 中完成的方式:
public void initModel(CpModel model)
{
// Make up some data for the counties of the orders
deliveryCountyId = new int[nOrders];
for (int order = 0; order < nOrders; order++)
{
deliveryCountyId[order] = order % nCounties;
}
// Boolean variables for item shipped by truck
x = new IntVar[nOrders, nTrucks];
for (int order = 0; order < nOrders; order++)
{
for (int truck = 0; truck < nTrucks; truck++)
{
x[order, truck] = model.NewBoolVar($"Item {order} (county {deliveryCountyId[order]}) in truck {truck}");
}
}
// Boolean variables for truck carrying an item for county
y = new IntVar[nTrucks, nCounties];
for (int truck = 0; truck < nTrucks; truck++)
{
for (int county = 0; county < nCounties; county++)
{
y[truck, county] = model.NewBoolVar($"Truck {truck} has item for county {county}");
}
}
// Each item must be shipped by exactly one truck
for (int order = 0; order < nOrders; order++)
{
List<IntVar> trucksForThisItem = new List<IntVar>();
for (int truck = 0; truck < nTrucks; truck++)
{
trucksForThisItem.Add(x[order, truck]);
}
model.Add(LinearExpr.Sum(trucksForThisItem) == 1);
}
// Compute which counties are in each truck
for (int truck = 0; truck < nTrucks; truck++)
{
for (int county = 0; county < nCounties; county++)
{
List<IntVar> ordersForCountyAndTruck = new List<IntVar>();
{
for (int order = 0; order < nOrders; order++)
{
if (deliveryCountyId[order] == county)
{
ordersForCountyAndTruck.Add(x[order, truck]);
}
}
}
if (ordersForCountyAndTruck.Count > 0)
{
model.AddMaxEquality(y[truck, county], ordersForCountyAndTruck);
}
else
{
model.Add(y[truck, county] == 0);
}
}
}
// Each truck may carry items for only one county
for (int truck = 0; truck < nTrucks; truck++)
{
List<IntVar> countiesPerTruck = new List<IntVar>();
for (int county = 0; county < nCounties; county++)
{
countiesPerTruck.Add(y[truck, county]);
}
model.Add(LinearExpr.Sum(countiesPerTruck) <= 1);
}
}
}
You can easily express the equivalent method calls in Python.您可以在 Python 中轻松表达等效的方法调用。
I have used Google-ortool's CP-SAT solver (python).我使用了 Google-ortool 的 CP-SAT 求解器(python)。 Please see the code below, I have added the desired constraint
请看下面的代码,我添加了所需的约束
import random
from ortools.sat.python import cp_model as cp
trucks = list(range(1, 9))
orders = list(range(1, 51))
delivery_county_id = [random.randint(1, 8) for _ in orders]
order_country = list(zip(orders, delivery_county_id))
model = cp.CpModel()
dv_order_truck = {}
for ord_cntry in order_country:
for trck in trucks:
dv_order_truck[(ord_cntry, trck)] = model.NewBoolVar("")
# one order in one truck only
for ord_cntry in order_country:
model.Add(sum(dv_order_truck[(ord_cntry, trck)] for trck in trucks) == 1)
# all orders packed into a given truck have the same delivery destination
dv_truck_country = {}
for trck in trucks:
for cntry in set(delivery_county_id):
dv_truck_country[trck, cntry] = model.NewBoolVar("")
for trck in trucks:
for cntry in set(delivery_county_id):
orders_inTruck_cntry = [v for k,v in dv_order_truck.items() if k[1] == trck and k[0][1] == cntry]
model.AddMaxEquality(dv_truck_country[trck, cntry], orders_inTruck_cntry)
for trck in trucks:
model.Add(sum(dv_truck_country[trck, cntry] for cntry in set(delivery_county_id)) == 1)
solver = cp.CpSolver()
solver.Solve(model)
# inspect the solution
solution = [(ord_cntry, trck) for ord_cntry in order_country for trck in trucks if solver.Value(dv_order_truck[(ord_cntry, trck)]) > 0]
sorted(solution, key = lambda x : x[0][1],reverse=True)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.