Commit ea65fe98 authored by Georgios Dagkakis's avatar Georgios Dagkakis

progression to new LP

parent 08f6c5f7
...@@ -173,7 +173,7 @@ class SkilledRouter(Router): ...@@ -173,7 +173,7 @@ class SkilledRouter(Router):
#=================================================================== #===================================================================
self.availableStationsDict={} self.availableStationsDict={}
for station in self.availableStations: for station in self.availableStations:
self.availableStationsDict[str(station.id)]={'stationID':str(station.id),'WIP':station.wip} self.availableStationsDict[str(station.id)]={'stationID':str(station.id),'WIP':station.wip, 'lastAssignment':self.env.now}
#=================================================================== #===================================================================
# # operators and their skills set # # operators and their skills set
#=================================================================== #===================================================================
......
...@@ -4,7 +4,7 @@ Created on 2 Jul 2014 ...@@ -4,7 +4,7 @@ Created on 2 Jul 2014
@author: Anna @author: Anna
''' '''
def opAss_LP(machineList, PBlist, PBskills, previousAssignment={}): def opAss_LP(machineList, PBlist, PBskills, previousAssignment={}, weightFactors = [2, 1, 0.5, 2, 1, 1], Tool={}):
from pulp import LpProblem, LpMaximize, LpVariable, LpBinary, lpSum, LpStatus from pulp import LpProblem, LpMaximize, LpVariable, LpBinary, lpSum, LpStatus
import pulp import pulp
...@@ -14,129 +14,142 @@ def opAss_LP(machineList, PBlist, PBskills, previousAssignment={}): ...@@ -14,129 +14,142 @@ def opAss_LP(machineList, PBlist, PBskills, previousAssignment={}):
machines = machineList.keys() machines = machineList.keys()
sumWIP = float(sum([machineList[mach]['WIP'] for mach in machines ])) sumWIP = float(sum([machineList[mach]['WIP'] for mach in machines ]))
weightFactors = [2, 1, 0.5, 1.5]
# define LP problem # define LP problem
prob = LpProblem("PBassignment", LpMaximize) prob = LpProblem("PBassignment", LpMaximize)
obj = []
# declare variables...binary assignment variables (operator i to machine j) # declare variables...binary assignment variables (operator i to machine j)
PB_ass = LpVariable.dicts('PB', [(oper,mach) for oper in PBlist for mach in machines if machineList[mach]['stationID'] in PBskills[oper]] , 0, 1, cat=pulp.LpBinary) PB_ass = LpVariable.dicts('PB', [(oper,mach) for oper in PBlist for mach in machines if machineList[mach]['stationID'] in PBskills[oper]] , 0, 1, cat=pulp.LpBinary)
# objective...assignment of PBs to stations with higher WIP...sum of WIP associated with stations where PB is assigned # objective...assignment of PBs to stations with higher WIP...sum of WIP associated with stations where PB is assigned
obj = [machineList[mach]['WIP']*PB_ass[(oper,mach)]*weightFactors[0]/float(sumWIP) for oper in PBlist for mach in machines if machineList[mach]['stationID'] in PBskills[oper]] if weightFactors[0]>0 and sumWIP>0:
obj.append([machineList[mach]['WIP']*PB_ass[(oper,mach)]*weightFactors[0]/float(sumWIP) for oper in PBlist for mach in machines if machineList[mach]['stationID'] in PBskills[oper]])
# second set of variables (delta assignment between stations) to facilitate the distribution of PBs across different stations # second set of variables (delta assignment between stations) to facilitate the distribution of PBs across different stations
stationGroup = {} if weightFactors[1]>0:
for mach in machines: stationGroup = {}
if machineList[mach]['stationID'] not in stationGroup: for mach in machines:
stationGroup[machineList[mach]['stationID']] = [] if machineList[mach]['stationID'] not in stationGroup:
stationGroup[machineList[mach]['stationID']].append(mach) stationGroup[machineList[mach]['stationID']] = []
Delta_Station = LpVariable.dicts("D_station",[(st1,st2) for i1, st1 in enumerate(stationGroup.keys()) for st2 in stationGroup.keys()[i1+1:]]) stationGroup[machineList[mach]['stationID']].append(mach)
Delta_Station = LpVariable.dicts("D_station", [(st1, st2) for i1, st1 in enumerate(stationGroup.keys()) for st2 in stationGroup.keys()[i1 + 1:]])
# calculate global max number of machines within a station that will be used as dividers for Delta_Station
maxNoMachines = 0 # calculate global max number of machines within a station that will be used as dividers for Delta_Station
for st in stationGroup: maxNoMachines = 0
if len(stationGroup[st]) > maxNoMachines: for st in stationGroup:
maxNoMachines = len(stationGroup[st]) if len(stationGroup[st]) > maxNoMachines:
maxNoMachines = len(stationGroup[st])
# calculation of DeltaStation values
for i, st1 in enumerate(stationGroup.keys()): # calculation of DeltaStation values
tempList = [] for i, st1 in enumerate(stationGroup.keys()):
for mach1 in stationGroup[st1]: tempList = []
for oper1 in PBlist: for mach1 in stationGroup[st1]:
if st1 in PBskills[oper1]: for oper1 in PBlist:
tempList.append(PB_ass[(oper1,mach1)]/float(maxNoMachines)) if st1 in PBskills[oper1]:
tempList.append(PB_ass[(oper1,mach1)]/float(maxNoMachines))
for st2 in stationGroup.keys()[i+1:]: for st2 in stationGroup.keys()[i+1:]:
finalList = copy.copy(tempList) finalList = copy.copy(tempList)
for mach2 in stationGroup[st2]: for mach2 in stationGroup[st2]:
for oper2 in PBlist: for oper2 in PBlist:
if st2 in PBskills[oper2]: if st2 in PBskills[oper2]:
finalList.append(PB_ass[(oper2,mach2)]*-1/float(maxNoMachines)) finalList.append(PB_ass[(oper2,mach2)]*-1/float(maxNoMachines))
prob += lpSum(finalList)>= Delta_Station[(st1,st2)] prob += lpSum(finalList)>= Delta_Station[(st1,st2)]
prob += lpSum([i*-1 for i in finalList])>= Delta_Station[(st1,st2)] prob += lpSum([i*-1 for i in finalList])>= Delta_Station[(st1,st2)]
# integration of second obj # integration of second obj
normalisingFactorDeltaStation = 0 normalisingFactorDeltaStation = 0
for i in range(len(stationGroup)): for i in range(len(stationGroup)):
normalisingFactorDeltaStation += i normalisingFactorDeltaStation += i
for i1, st1 in enumerate(stationGroup.keys()): for i1, st1 in enumerate(stationGroup.keys()):
for st2 in stationGroup.keys()[i1+1:]: for st2 in stationGroup.keys()[i1+1:]:
obj.append(Delta_Station[(st1,st2)]*weightFactors[1]/float(normalisingFactorDeltaStation) ) obj.append(Delta_Station[(st1,st2)]*weightFactors[1]/float(normalisingFactorDeltaStation) )
# min variation in PB assignment # min variation in PB assignment
Delta_Assignment = [] if weightFactors[2]>0:
OldAss = {} Delta_Assignment = []
for pb in previousAssignment: OldAss = {}
if pb in PBlist: for pb in previousAssignment:
for station in PBskills[pb]: if pb in PBlist:
for mach in machineList: for station in PBskills[pb]:
if machineList[mach]['stationID'] == station: for mach in machineList:
Delta_Assignment.append([pb, mach]) if machineList[mach]['stationID'] == station:
if previousAssignment[pb] == mach: Delta_Assignment.append([pb, mach])
OldAss[(pb,mach)] = 1 if previousAssignment[pb] == mach:
else: OldAss[(pb,mach)] = 1
OldAss[(pb,mach)] = 0 else:
OldAss[(pb,mach)] = 0
# create delta assignment variables # create delta assignment variables
Delta_Ass = LpVariable.dicts("D_Ass",[(d[0],d[1]) for d in Delta_Assignment]) Delta_Ass = LpVariable.dicts("D_Ass",[(d[0],d[1]) for d in Delta_Assignment])
# integration of third objective # integration of third objective
for d in Delta_Assignment: for d in Delta_Assignment:
obj.append(Delta_Ass[(d[0], d[1])]*(-1.0*weightFactors[2]/(2*len(previousAssignment))) ) obj.append(Delta_Ass[(d[0], d[1])]*(-1.0*weightFactors[2]/(2*len(previousAssignment))) )
# calculation of Delta_Ass # calculation of Delta_Ass
for d in Delta_Assignment: for d in Delta_Assignment:
if OldAss[(d[0],d[1])] == 1: if OldAss[(d[0],d[1])] == 1:
prob += lpSum(OldAss[(d[0],d[1])] - PB_ass[(d[0],d[1])]) <= Delta_Ass[(d[0],d[1])] prob += lpSum(OldAss[(d[0],d[1])] - PB_ass[(d[0],d[1])]) <= Delta_Ass[(d[0],d[1])]
else: else:
prob += lpSum(PB_ass[(d[0],d[1])] - OldAss[(d[0],d[1])]) <= Delta_Ass[(d[0],d[1])] prob += lpSum(PB_ass[(d[0],d[1])] - OldAss[(d[0],d[1])]) <= Delta_Ass[(d[0],d[1])]
# 4th obj = fill a subline # 4th obj = fill a subline
# verify whether there are machines active in the sublines if weightFactors[3]>0:
subline={0:{'noMach':0, 'WIP':0}, 1:{'noMach':0, 'WIP':0}} # verify whether there are machines active in the sublines
for mach in machineList: subline={0:{'noMach':0, 'WIP':0}, 1:{'noMach':0, 'WIP':0}}
if machineList[mach]['stationID'] in [0,1,2]: for mach in machineList:
subline[machineList[mach]['machineID']]['noMach'] += 1 if machineList[mach]['stationID'] in [0,1,2]:
subline[machineList[mach]['machineID']]['WIP'] += machineList[mach]['WIP'] subline[machineList[mach]['machineID']]['noMach'] += 1
subline[machineList[mach]['machineID']]['WIP'] += machineList[mach]['WIP']
chosenSubLine = False
chosenSubLine = False
# choose subline to be filled first
if subline[0]['noMach'] == 3: # choose subline to be filled first
# case when both sublines are fully active if subline[0]['noMach'] == 3:
if subline[1]['noMach'] == 3: # case when both sublines are fully active
if subline[0]['WIP'] >= subline [1]['WIP']: if subline[1]['noMach'] == 3:
chosenSubLine = 1 if subline[0]['WIP'] >= subline [1]['WIP']:
chosenSubLine = 1
else:
chosenSubLine = 2
else: else:
chosenSubLine = 2 chosenSubLine = 1
else:
chosenSubLine = 1 elif subline[1]['noMach'] == 3:
chosenSubLine = 2
elif subline[1]['noMach'] == 3:
chosenSubLine = 2 #create variable for the chosen subline
if chosenSubLine:
#create variable for the chosen subline chosenSubLine -= 1
if chosenSubLine: subLine = LpVariable('SubL', lowBound=0)
chosenSubLine -= 1 sub = []
subLine = LpVariable('SubL', lowBound=0) for station in range(3):
sub = [] mach = Tool[station][chosenSubLine].name #'St'+str(station)+'_M'+str(chosenSubLine)
for station in range(3): for oper in PBlist:
mach = G.Tool[station][chosenSubLine].name #'St'+str(station)+'_M'+str(chosenSubLine) if station in PBskills[oper]:
for oper in PBlist: sub.append(PB_ass[(oper,mach)])
if station in PBskills[oper]:
sub.append(PB_ass[(oper,mach)])
prob += lpSum(sub) >= subLine
chosenSubLine+=1
obj.append(subLine*weightFactors[3]/3.0)
prob += lpSum(sub) >= subLine
chosenSubLine+=1
obj.append(subLine*weightFactors[3]/3.0)
# 5th objective: prioritise machines with furthest in time last assignment
LastAssignmentSum = float(sum([machineList[mach]['lastAssignment'] for mach in machines ]))
if LastAssignmentSum > 0 and weightFactors[4]>0:
obj += [machineList[mach]['lastAssignment']*PB_ass[(oper,mach)]*weightFactors[4]/float(LastAssignmentSum) for oper in PBlist for mach in machines if machineList[mach]['stationID'] in PBskills[oper]]
# 6th objective: max the number of pb assigned
if weightFactors[5]>0:
obj += [PB_ass[(oper,mach)]*weightFactors[5]/float(len(PBlist)) for oper in PBlist for mach in machines if machineList[mach]['stationID'] in PBskills[oper]]
prob += lpSum(obj) prob += lpSum(obj)
...@@ -147,7 +160,11 @@ def opAss_LP(machineList, PBlist, PBskills, previousAssignment={}): ...@@ -147,7 +160,11 @@ def opAss_LP(machineList, PBlist, PBskills, previousAssignment={}):
# constraint 2: # machines assigned to an operator <= 1 # constraint 2: # machines assigned to an operator <= 1
for operator in PBlist: for operator in PBlist:
prob += lpSum([PB_ass[(operator,machine)] for machine in machines if machineList[machine]['stationID'] in PBskills[operator]]) <= 1 prob += lpSum([PB_ass[(operator,machine)] for machine in machines if machineList[machine]['stationID'] in PBskills[operator]]) <= 1
# write the problem data to an .lp file.
prob.writeLP("PBassignment.lp")
prob.solve() prob.solve()
if LpStatus[prob.status] != 'Optimal': if LpStatus[prob.status] != 'Optimal':
...@@ -160,7 +177,7 @@ def opAss_LP(machineList, PBlist, PBskills, previousAssignment={}): ...@@ -160,7 +177,7 @@ def opAss_LP(machineList, PBlist, PBskills, previousAssignment={}):
if machineList[mach]['stationID'] in PBskills[oper]: if machineList[mach]['stationID'] in PBskills[oper]:
if PB_ass[(oper,mach)].varValue > 0.00001: if PB_ass[(oper,mach)].varValue > 0.00001:
PBallocation[oper]=mach PBallocation[oper]=mach
files = glob.glob('*.mps') files = glob.glob('*.mps')
for f in files: for f in files:
os.remove(f) os.remove(f)
...@@ -170,7 +187,6 @@ def opAss_LP(machineList, PBlist, PBskills, previousAssignment={}): ...@@ -170,7 +187,6 @@ def opAss_LP(machineList, PBlist, PBskills, previousAssignment={}):
os.remove(f) os.remove(f)
return PBallocation return PBallocation
\ No newline at end of file
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment