How to add constraints for a 14 day cycle of production and delivery
回答済みDear all, I am trying to write a minimization model where a certain demand for a county needs to be met. There will be a list of factories and a list of centers to ship the product to in a 14-day period. The goals is to minimize excess such that the number of produced products in all time periods - (the number of shipped to center in all time periods- the number of consumed productsin all time periods) is minimised. Please can someone help me with the formatting of the constraints and the total objective function as I am not sure how to integrate the time period of 14 days.
shipping_cost = {(f,c): costPerMile*compute_distance(facilities[f], centers[c]) for f, c in cartesian_prod_fc}
#number of reactors at facility f at period t
rn = m.addVars(cartesian_prod_ft, vtype=GRB.CONTINUOUS, lb = 0, name="reactor_{}".format((f,t) for f,t in cartesian_prod_ft))
#number of doses at facility f at period t
d = m.addVars(cartesian_prod_ft, vtype=GRB.CONTINUOUS, lb = 0, name="doses_{}".format((f,t) for f,t in cartesian_prod_fct))
#DurationOfRunPerReacorInTimePeriod
rnt = m.addVars(cartesian_prod_ft, vtype = GRB.CONTINUOUS, lb = 1, name = "reactorRunTime_{}".format((f,t) for f,t in cartesian_prod_fct))
#rn*rnt*600 = total doses per day
#number of reactors * duration of run * 600
#number of allocated doses from facility f for center c at period t
alloc = m.addVars(cartesian_prod_fct, vtype=GRB.CONTINUOUS, name="allocated_{}".format((f,c,t) for f,c,t in cartesian_prod_fct))
#shipped doses
s = m.addVars(cartesian_prod_fct, vtype=GRB.CONTINUOUS, name="Shipped_{}".format((f,c,t) for f,c,t in cartesian_prod_fct))
#administrated doses
adm = m.addVars(cartesian_prod_ct, vtype=GRB.CONTINUOUS, name="administrated_{}".format((c,t) for c,t in cartesian_prod_ct))
#doses stored at facility f in period
fstored = m.addVars(cartesian_prod_ft, vtype=GRB.CONTINUOUS, name="fstored{}".format((f,t) for f,t in cartesian_prod_ft))
#doses stored at center c in period
cstored = m.addVars(cartesian_prod_ct, vtype=GRB.CONTINUOUS, name="cstored_{}".format((c,t) for c,t in cartesian_prod_ct))
#number of nurses at location c
nc = m.addVars(cartesian_prod_ct, vtype = GRB.CONTINUOUS, lb = 0, name = "numberofNurses_{}".format((c,t) for c,t in cartesian_prod_ct))
#number of deliveries from factory to center in period
nd = m.addVars(cartesian_prod_fct, vtype = GRB.CONTINUOUS, lb = 0, name = "deliveries_{}".format((f,c,t) for f,c,t in cartesian_prod_fct))
When I try to add the constraints I keep getting errors for tupledict if I try to caclulate the costofshipping per day which would be number of deliveries times shippingcost
-
正式なコメント
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 Nelly,
Could you provide a minimal working example showing the issue?
When starting off with a new model, it is often best to write down the formulation on a piece of paper (or anything similar) before coding it. This way, you can implement the variables and constraints one by one and additionally you can easily explain to others which constraints are causing you trouble.
Best regards,
Jaromił0 -
Hello Jaromił Najman, thank you for your response.
Here is my problem:
\[\begin{align} \ v = rate(in)t - rate(out)t + \textrm{what's generated} \end{align}\]
\[\begin{align} \ V_{excess} = N_{t}r_{t_{0}}t - (N_{s}r_{s} + N_{t_{i}}r_{t})t + N_{r}r_{r}t \\ \end{align}\]
\[\begin{align} \ Sum(V_{excess}) = Sum(N_{t}r_{t_{0}})t - Sum(N_{s}r_{s} + N_{t_{i}}r_{t})t + Sum(N_{r}r_{r}t) \\ \end{align}\]
What the problem is trying to do is minimize excess, meaning the difference between what was produced in a factory and allocated to each county minus what was used by the county during a course of 14 days period.
what's in = the rate of transportation in a site (shipped)
if the number of trucks coming in within a period t is N_{t} and each truck works at the rate of r then N r t is the volume per site
for all sites, we need to sum it up
what's out = dispensing by staff + transportation out
if each staff works at the rate pf r, in time t, N staffs will dispense N r t and if transportation out is N r at the same time t, then N in time t
N r t is again for all sites
what's produced is basically reactor rate r x number of reactors N in time t
N r t needs to be summed for all sites
Excess can't be less than zero but could be zero.
This is to solve vaccine delivery solution where a factory needs to make enough doses for each vaccination center keeping in mind what's left behind in each tier.
I have added my variables in the previous post... does this help?
0 -
Hi Nelly,
Yes, this certainly helps. Now, could you post the code snippet of the constraints which produces the error you mentioned in your first post? Moreover, one would need the definition of \(\texttt{cartesian_prod_fct}\) to reproduce the problem.
Best regards,
Jaromił0 -
Here is what I have written so far Jaromił Najman, please do let me know if there is any issues with the formatting of what I am intending to do. Thank you so much!
import itertools
from itertools import product
from math import sqrt
import pandas as pd
import gurobipy as gp
from gurobipy import GRB
from gurobipy import quicksum
m = gp.Model('VCStrategy')
#minimum amount of dose made by one reactor per day (one minute run per day)
minDosePerR = 600
#max number of hours every reactor can run for (8 hours a day)
maxRunTime = 8*60
#county population
CountyPopulation = 7000
centers = [(0,0), (0,1), (0,2), (1,0), (1,1), (1,2), (2,0), (2,1), (2,2)] #this needs to reflect the db
facilities = [(0,0), (0,1), (0,2)] #this needs to reflect the db
# Indices for the facilities
facilitiesIndex = [*range(1,3)] #this needs to reflect the count from db
# Indices for the counties / later to be post codes/ as in GPs
countiesIndex = [*range(1,9)] #this needs to reflect count the db
#time period - 14 days
period = [*range(0,13)]
#nurse number of admissions per day
nurse_ratePerDay = 28
#max number of nurses in each clinic to administrate vaccines
nurse_max = 8
#cost to set up one reactor + storage staff and the rest for 14 days
costPerFacilitySetup = [10000,10000,10000] #this needs to reflect the db for count of hospitals provided 10,000
#cost of travel per mile by vehicle
costPerMile = 10
#cost per day per nurse
costPerNurse = 105
capacityTOStorePerGP = 399
capacityTOStorePerHospital = 2000
storageCostPerDoseGP = 0.90
storageCostPerDoseHospital = 0.79
budget = 200000
# Cartesian product of counties and facilities
fc = []
for f in facilitiesIndex:
for c in countiesIndex:
tp = f,c
fc.append(tp)
# Cartesian product of facilites and centers and time period
fct = []
for f in facilitiesIndex:
for c in countiesIndex:
for t in period:
tp = f,c,t
fct.append(tp)
# Cartesian product of facilities and time
ft = []
for f in facilitiesIndex:
for t in period:
tp = f,t
ft.append(ft)
# Cartesian product of centers and time
ct = []
for c in countiesIndex:
for t in period:
tp = c,f
ct.append(tp)
# This function determines the Euclidean distance between a facility and customer sites.
def compute_distance(loc1, loc2):
dx = loc1[0] - loc2[0]
dy = loc1[1] - loc2[1]
return sqrt(dx*dx + dy*dy)
# Compute key parameters of MIP model formulation
num_facilities = len(facilities)
num_customers = len(centers)
cartesian_prod_fc = list(product(range(num_facilities), range(num_customers)))
cartesian_prod_fct = list(product(range(num_facilities), range(num_customers), (period)))
cartesian_prod_ct = list(product(range(num_customers), (period)))
cartesian_prod_ft = list(product(range(num_facilities), (period)))
select = m.addVars(num_facilities, vtype=GRB.BINARY, name='Select')
# Compute shipping costs
shipping_cost = {(f,c): costPerMile*compute_distance(facilities[f], centers[c]) for f, c in cartesian_prod_fc}
#number of reactors at facility f at period t
rn = m.addVars(cartesian_prod_ft, vtype=GRB.CONTINUOUS, lb = 0, name="reactor_{}".format((f,t) for f,t in cartesian_prod_ft))
#number of doses at facility f at period t
d = m.addVars(cartesian_prod_ft, vtype=GRB.CONTINUOUS, lb = 0, name="doses_{}".format((f,t) for f,t in cartesian_prod_ft))
#DurationOfRunPerReacorInTimePeriod - #minimum running time is 1 minute lower bound
rnt = m.addVars(cartesian_prod_ft, vtype = GRB.CONTINUOUS, lb = 1, name = "reactorRunTime_{}".format((f,t) for f,t in cartesian_prod_ft))
#rn*rnt*600 = total doses per day
#number of reactors * duration of run * 600
#number of allocated doses from facility f for center c at period t
alloc = m.addVars(cartesian_prod_fct, vtype=GRB.CONTINUOUS, name="allocated_{}".format((f,c,t) for f,c,t in cartesian_prod_fct))
#shipped doses
s = m.addVars(cartesian_prod_fct, vtype=GRB.CONTINUOUS, name="Shipped_{}".format((f,c,t) for f,c,t in cartesian_prod_fct))
#administrated doses
adm = m.addVars(cartesian_prod_ct, vtype=GRB.CONTINUOUS, name="administrated_{}".format((c,t) for c,t in cartesian_prod_ct))
#doses stored at facility f in period
fstored = m.addVars(cartesian_prod_ft, vtype=GRB.CONTINUOUS, name="fstored{}".format((f,t) for f,t in cartesian_prod_ft))
#doses stored at center c in period
cstored = m.addVars(cartesian_prod_ct, vtype=GRB.CONTINUOUS, name="cstored_{}".format((c,t) for c,t in cartesian_prod_ct))
#number of nurses at location c
nc = m.addVars(cartesian_prod_ct, vtype = GRB.CONTINUOUS, lb = 0, name = "numberofNurses_{}".format((c,t) for c,t in cartesian_prod_ct))
#number of deliveries from factory to center in period
nd = m.addVars(cartesian_prod_fct, vtype = GRB.CONTINUOUS, lb = 0, name = "deliveries_{}".format((f,c,t) for f,c,t in cartesian_prod_fct))
#List of Contraints
#total of doses made in 14 days need to equal demand in county
# m.addConstr(quicksum(d[f, t]) for f,t in cartesian_prod_ft == CountyPopulation)
m.addConstrs((d[f, t] == CountyPopulation for f,t in cartesian_prod_ft
if f != t), name='demandConstraints')
#max hour of operation per reactor per day is 480 minutes
m.addConstrs((rnt[f, t] <= maxRunTime for f,t in cartesian_prod_ft
if f != t), name='maxRunTimeConstraints')
#max number of nurses shouldn't be more than 8
m.addConstrs((nc[c, t] <= maxRunTime for c,t in cartesian_prod_ct
if c != t), name='maxNurseConstraints')
#minimum produceddosesin each period is 600 doses if the factory is selected - as in the hospital is the point of production
#if t=0, none of the centers have any excess doses
#total allocated doses from facility f to center c in time period t shouldn't be greater than center's capacity for the day which is 399
#if t!=0, centers have some remaining doses
#total allocated doses from facility f to center c in time period t shouldn't be greater than center's capacity - remaining doses
#total cost of setting the factories, shipping doses to all locations, administrating it and storing them in both factory and center shouldn't be greater than our budget for the total of 14 days
#calculate the total for setting up the factories, shipping the doses and administrating it
#total cost involves number of reactors time their fixed fee + numberofdeliveries * shippingcost + numberofstaff*theirdaily rate
#this needs to reflect all 14 period
#min excess = Total of produced in all periods - (total of all allocated per clinic - total of all dispenced)
# integrate variables and constraints
m.update()
# Objective function
totalPro = (gp.quicksum(d[f,t] for f,t in ft))
totalAllocated = (gp.quicksum(alloc[f,c,t] for f,c,t in fct))
totalAdm = (gp.quicksum(adm[c,t] for c,t in ct))
obj = (totalPro - (totalAllocated - totalAdm))
m.setObjective(obj,GRB.MINIMIZE)
# start optimization
m.optimize()And for the most part here is the error I keep getting. I am not sure what I am doing wrong..
# Objective function --> 185 totalPro = (gp.quicksum(d[f,t] for f,t in ft)) 186 totalAllocated = (gp.quicksum(alloc[f,c,t] for f,c,t in fct)) 187 totalAdm = (gp.quicksum(adm[c,t] for c,t in ct)) ValueError: too many values to unpack (expected 2)
I think the quick sum over all products produced, allocated and administrated is right, both in constraints and in objective function
0 -
Hi Nelly,
The error occurs because the \(\texttt{ft}\) list is not constructed properly. In line 77 it should read
ft.append(tp)
instead of
ft.append(ft)
The resulting model is found to be infeasible or unbounded. You could use the write() function to generate an LP file which you can analyze by hand. The InfUnbdInfo parameter provides additional information to determine whether the model is actually infeasible or unbounded. In the case of an infeasible model you might want to have a look at the Knowledge Base article How do I determine why my model is infeasible?
Best regards,
Jaromił0
投稿コメントは受け付けていません。
コメント
6件のコメント