SetObjective() function problems
AnsweredDear community,
For a project I am modelling an MILP problem to solve routing of trucks via milk runs along multiple suppliers. I have built models in Gurobi before although they were always a lot less complicated. When building this model I find that the model.setObjective() takes for ever to complete.

Above you can find my paper or mathematical model, below is the way I wrote the objective in Python. I must admit I am not an expert in programming at all, so it might be completely wrong to write it like this, however it would be very helpful if someone could point me in the right direction.
Side note: The distance function reads a distance matrix with all locations, the price function looks up a certain country-country relationship in a data sheet and comes with a price per kilometer based on distance and weight
model.setObjective(grb.quicksum(x[c,i,j]*Distance(df['Collection Town'][c], df['Delivery Town'][c])*Price(df['Collection Country'][c], df['Delivery Country'][c], Distance(df['Collection Town'][c], df['Delivery Town'][c]), float(df['Payable Weight Act'][c])) for c in df.index for i in Suppliers for j in Plants)
+ grb.quicksum(alpha[c,i,j,m,h]*Distance(df['Collection Town'][c], h)*Price(df['Collection Country'][c], df['Delivery Country'][c], Distance(df['Collection Town'][c], h), MaxPW) for c in df.index for i in Suppliers for j in Plants for m in MilkRuns for h in Nodes)
+ grb.quicksum(f[c,i,j,m]*ExtraStop for c in df.index for i in Suppliers for j in Plants for m in MilkRuns)
+ grb.quicksum(g[c,i,j,m]*ExtraStop for c in df.index for i in Suppliers for j in Plants for m in MilkRuns))
-
Official comment
This post is more than three years old. Some information may not be up to date. For current information, please check the Gurobi Documentation or Knowledge Base. If you need more help, please create a new post in the community forum. Or why not try our AI Gurobot?. -
Hi Thomas,
What are the dimensions of
df.index
Suppliers
Plants
MilkRuns
Nodes?
You should try to avoid executing the same loops multiple times. In your case, all sum terms have the 3 common sub-sums over the sets \(C,S,\) and \(P\) and an additional common sub-sum over the set \(M\). You could try first constructing your objective function using the LinExpr object and then set it as the objective. An example code (which might already help) would be
obj = LinExpr(0)
for c in df.index:
for i in Suppliers:
for j in Plants:
obj.add(x[c,i,j],Distance(df['Collection Town'][c], df['Delivery Town'][c])*Price(df['Collection Country'][c], df['Delivery Country'][c], Distance(df['Collection Town'][c], df['Delivery Town'][c])
for m in MilkRuns:
obj.add(f[c,i,j,m], ExtraStop)
obj.add(g[c,i,j,m], ExtraStop)
for h in Nodes:
obj.add(alpha[c,i,j,m,h],Distance(df['Collection Town'][c], h)*Price(df['Collection Country'][c], df['Delivery Country'][c], Distance(df['Collection Town'][c], h), MaxPW))
model.setObjective(obj)This way, you have one loop of depth 5 instead of 4 loops of depths 3, 4, 4, and 5.
Best regards,
Jaromił1 -
Dear Jaromil
Thank you for the response, your advice already helps a lot!
I have a test example set of data for building the model which is relatively small in terms of dimensions (4 plants, 13 suppliers and 23 shipments (df.index) in total). In the real shipment data eventually there will be a lot more rows, however this can be brought down easily by running the model for every week seperately in stead of for a whole dataset for example, since combining shipments into milk runs that are not in the same week is pretty uncommon anyway.
Thank you again for this advice it has helped me towards solving the case!
Kind regards,
Thomas
0
Post is closed for comments.
Comments
3 comments