Summing up over a set
Awaiting user inputHey,
I'm having trouble with coding the following constraint:
with T_pt being a set (cartesian product) which consists of all combinations (tau,q) or project start periods tau and project periods q of project p that lead to resource demand in calendar period t. [ES_p, LS_p] = Time window between earliest start time and latest start time of project p. q = 1,...,d_p are the project periods, with q=1 in the period (e.g. in t=3) the project is started. and q=d_p in the period it is finished. The constraint basically aims to ensure that all work packages (r_psq) of all projects are processed by either external resources (y_pts) or internal resources (x_ptsk; r for regular time, o for overtime, only difference is the cost function here) within the time horizon T. z_ptau is a binary decision variable that is 1 if the project has already been started (-> work packages are "available") and 0 otherwise. I tried to code the set T_pt and the constraint (error message in the constraint, the output of the cartesian product looks to be correct) the following way: #This is to create the cartesian product and convert into correct format: Output: [[5, 1], [6, 1], [7, 1]] #data set: Project 1 has ES_p=5 and LS_p=7 #This is to build T_pt: |
|
Output:
[[[[5, 1]], [[6, 1]], [[7, 1]]],... this array looks to be correct, all the earliest and latest starting times of each project are transfered correctly. ... and this is how I tried implementing it in the constraint: model.addConstrs( |
|
IndexError: list index out of range (Left-hand-side of the constraint)
Thanks for your help in advance!
Sebastian
-
Hi Sebastian,
Your Python code is not very well formatted making it pretty hard to read. Could you please try editing your question and fix the indentation? I already went ahead and formatted the constraint but I am not completely sure how the sets are supposed to be constructed.
The array you show also seems to be off. Shouldn't the first line just look like this:
[[[5, 1], [6, 1], [7, 1]],
You may be better off using dictionaries for more complex data structures.
And please always try posting an MRE so other people can actually reproduce your error. This makes it far more likely to get a helpful answer.
Cheers,
Matthias0 -
Hi Matthias,
thanks for responding quickly, I tried making the code cleaner and set up a small hard coded test instance so you can replicate the error:
# importing libraries
I agree, the brackets in the bigTau_pt array seem to be wrong. I am not sure how to write this as a dictionary, is there a way to rewrite it with gp.multidict?
import pandas as pd
import numpy as np
import gurobipy as gp
import itertools
from gurobipy import GRB
from builtins import dict
from itertools import combinations
# hard coded test instances
timeperiod = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12] # time horizon from t=1,...,12
timeWindow = [[5, 6, 7], [1, 2, 3], [5, 6, 7]] # [Es_p,...,LS_p]
proj_period = [1, 2, 3, 4, 5, 6] # project duration
# Cartesian product
cartesian_list = list(itertools.product(timeWindow, proj_period))
bigSet = []
for i in cartesian_list:
firstindex = i[0]
secondindex = i[1]
listC = []
listD = []
for a in range(0, len(firstindex)):
listC.append(firstindex[a])
listC.append(secondindex)
listD.append(listC)
listC = []
bigSet.append(listD)
print(bigSet[0])
# Building T_pt
def meetsCondition(tau, q, t):
return bool(t <= max(timeperiod))
bigTau_pt = []
for row in range(0, len(bigSet)):
outputList = []
filteredList = []
for set1 in bigSet[row]:
tau = set1[0]
q = set1[1]
t = tau + q - 1
if meetsCondition(tau, q, t):
outputList.append(set1)
filteredList.append(outputList)
outputList = []
bigTau_pt.append(filteredList)
print(bigTau_pt)
model = gp.Model("Baseline")
# hardcoded test instances
projects = [1, 2, 3] # 3 projects to be processed
skills = [1, 2, 3, 4] # total of 4 skills for the 3 projects required
resourcesK = [1, 2, 3, 4, 5] # 5 internal human resources
intResourceS = [
[2, 3],
[1, 4],
[3, 5],
[1, 2],
[4, 5],
] # skills of each internal resource (e.g. resource 1 has skills 2 and 3)
# amt of work internal resource k performs during regular hours t on the work packages of project p which require skill s
workIntReg = model.addVars(
projects, timeperiod, skills, resourcesK, vtype=GRB.CONTINUOUS, name="workIntReg"
)
# amt of work internal resource k performs during overtime hours t on the work packages of project p which require skill s
workIntOT = model.addVars(
projects, timeperiod, skills, resourcesK, vtype=GRB.CONTINUOUS, name="workIntOT"
)
# amt of work of project p requiring skill s performed by external resources in period t
workExt = model.addVars(
projects, timeperiod, skills, vtype=GRB.CONTINUOUS, name="workExt"
)
# binary decision variable for setting project start time
projStart = model.addVars(projects, timeperiod, vtype=GRB.BINARY, name="projectStart")
# hardcoded test instances
early_start = [
[1, 5],
[2, 1],
[3, 5],
] # e.g. project 1 can start earliest at t=5, project 2 earliest at t=1..
late_start = [[1, 7], [2, 3], [3, 7]] # e.g. project 1 must start latest at t=7...
# Building the constraint
model.addConstrs(
(
gp.quicksum(
workpackage[p][s][q] * projStart[p, tau] for tau, q in bigTau_pt[p][t]
)
<= (
workExt[p, t, s]
+ gp.quicksum(
(workIntReg[p, t, s, k] + workIntOT[p, t, s, k])
for k in intResourceS[s - 1]
)
)
for p in projects
for t in range(early_start[p - 1][1], late_start[p - 1][1] + 1)
for s in skills
),
name="workpackconstModified",
)Best,
Sebastian
0 -
Hi Sebastian,
Your code example is still not reproducible because you are referring to some undefined "workpackage" in the constraint formulation.
You should write out the LP file of the model and compare this to your mathematical formulation to figure out what might be off.
BTW: I used the black formatter to make your code readable: The uncompromising code formatter — Black 21.12b0 documentation
Cheers,
Matthias0
Please sign in to leave a comment.
Comments
3 comments