Commit 300a2574 authored by Georgios Dagkakis's avatar Georgios Dagkakis

allocation algorithms added

parent d9c699e3
'''
Created on 3 Oct 2013
@author: Anna
Basic implementation: runs the allocation routine for the future demand first (one week at a time for the whole planning horizon) and the
PPOS after
Equivalent to M2 in MATLAB functions
'''
from AllocationRoutine import AllocationRoutine
from dream.simulation.Globals import G
class AllocManagement():
def Run(self):
for kWeek in range(G.planningHorizon):
# activate allocation procedure for future items at target week
procedureFuture = AllocationRoutine(initialWeek=kWeek, itemType=1)
procedureFuture.Run()
# activate allocation procedure for PPOS items at target week
procedurePPOS = AllocationRoutine(initialWeek=G.TargetPPOSweek, itemType=0)
procedurePPOS.Run()
G.reCapacity.append(G.currentCapacity)
'''
Created on 21 Aug 2013
@author: Anna
'''
import math
import numpy
import random
from dream.simulation.Globals import G
class Allocation():
def __init__(self, itemList, week, altRoutes, excBuffer):
self.week = week
self.altRoutes = altRoutes
self.itemList = itemList
self.excBuffer = excBuffer
def Run(self):
for CurrentMA in self.itemList:
# call the allocation methods based on the step (e.g. allocation on same route or allocation on alternative routes)
if self.altRoutes == 1:
self.alternativeRoutes(CurrentMA)
else:
self.allocationStd(CurrentMA)
# put items in output buffer (temporary buffer for excess units to be allocated)
if CurrentMA.qty > 0:
self.excBuffer.append(CurrentMA)
# allocate item on its own route
def allocationStd(self, MA):
requiredCapacity = [x*MA.qty for x in G.route[MA.MAid]]
remainingCapacity = numpy.array(G.currentCapacity[self.week]) - numpy.array(requiredCapacity)
remainingCapacity = remainingCapacity.tolist()
# check if there is sufficient capacity to process the order
if min(remainingCapacity) >= 0:
# update remaining capacity
allocableQty = MA.qty
if MA.qty >= G.minPackingSize:
G.currentCapacity[self.week] = remainingCapacity
# if the capacity available is not sufficient, the max allocable qty is derived
else:
# calculate max qty allocable
excessUnits = [0 for i in range(len(requiredCapacity))]
for i in range(len(remainingCapacity)):
if requiredCapacity[i]>0 and remainingCapacity[i]<0:
excessUnits[i] = remainingCapacity[i]/G.route[MA.MAid][i]
excess = math.ceil(math.fabs(min(excessUnits)))
# update remaining capacity
assert(excess <= MA.qty or MA.qty < G.minPackingSize)
allocableQty = MA.qty - excess
if allocableQty >= G.minPackingSize:
rCap = numpy.array(G.currentCapacity[self.week]) - numpy.multiply(allocableQty,G.route[MA.MAid])
G.currentCapacity[self.week] = rCap.tolist()
# update attributes/variables affected by allocation
if allocableQty >= G.minPackingSize:
MA.qty -= allocableQty
MA.minQty = max([0, MA.minQty - allocableQty])
# update allocation output variable
# distinguish case of FutureDemand from PPOSdemand
if MA.future == 1:
G.AllocationFuture[G.replication].append([MA.orderID, MA.MAid, allocableQty, self.week+1])
G.FutureLateness[G.replication] += max([0, self.week - MA.originalWeek])*allocableQty
G.FutureEarliness[G.replication] += max([0, MA.originalWeek - self.week])*allocableQty
else:
G.AllocationPPOS[G.replication].append([MA.orderID, MA.MAid, allocableQty, self.week+1])
G.PPOSLateness[G.replication] += max([0, self.week - MA.originalWeek])*allocableQty
G.PPOSEarliness[G.replication] += max([0, MA.originalWeek - self.week])*allocableQty
def alternativeRoutes(self, MA):
# identify MAs with the same SP as the MA investigated
MAlist=[] #FIXME: the PPOS attribute can be used instead for the current MA
for i in G.PPOSlist:
if i != MA.MAid and G.PPOSlist[i]['SP'] == G.PPOSlist[MA.MAid]['SP']: # and G.PPOSlist[i][2] != G.PPOSlist[MA.MAid][2]:
MAlist.append(i)
# calculate max number of units for each alternative MA
maxUnits = []
for i in MAlist:
i=int(i)
MAunits=[]
for j in range(len(G.route[i])):
if G.route[i][j] != 0:
MAunits.append(G.currentCapacity[self.week][j]/G.route[i][j])
maxUnits.append(math.floor(min(MAunits)))
# choose MA with max number of units
if len(maxUnits) != 0 and max(maxUnits) != 0:
maxU = maxUnits[0]
maxID = [0]
if len(maxUnits) > 1:
for i in range(1,len(maxUnits)):
if maxUnits[i] > maxU:
maxU = maxUnits[i]
maxID = [i]
if maxUnits[i] == maxU:
maxID.append(i)
# choose MA randomly among those with max number of units
x = random.choice(maxID)
allocableQty = min([maxU, MA.qty])
if allocableQty >= G.minPackingSize:
# update remaining capacity
remCap = numpy.array(G.currentCapacity[self.week]) - allocableQty* numpy.array(G.route[MAlist[x]])
G.currentCapacity[self.week] = remCap.tolist()
# update attributes/variables affected by allocation
MA.qty -= allocableQty
MA.minQty = max([0, MA.minQty - allocableQty])
# update allocation output variable
# distinguish case of FutureDemand from PPOSdemand
if MA.future == 1:
G.AllocationFuture[G.replication].append([MA.orderID, MAlist[x], allocableQty, self.week+1])
G.FutureLateness[G.replication] += max([0, self.week - MA.originalWeek])*allocableQty
G.FutureEarliness[G.replication] += max([0, MA.originalWeek - self.week])*allocableQty
else:
G.AllocationPPOS[G.replication].append([MA.orderID, MAlist[x], allocableQty, self.week+1])
G.PPOSLateness[G.replication] += max([0, self.week - MA.originalWeek])*allocableQty
G.PPOSEarliness[G.replication] += max([0, MA.originalWeek - self.week])*allocableQty
\ No newline at end of file
'''
Created on 5 Sep 2013
@author: Anna
'''
from dream.simulation.Globals import G
from Allocation import Allocation
from dream.simulation.JobMA import Job
class AllocationRoutine():
def __init__(self, initialWeek, itemType):
self.initialWeek = initialWeek
self.itemType = itemType
self.week = self.initialWeek
self.internalBuffer = []
self.minBuffer = []
def Run(self):
#verify if there is any item to be allocated at self.weeek (originally)
noItems = self.checkNumberOfItems()
# if there are items of that week, start the allocation routine
if noItems:
#====================================
# step 1: same route, same week
#====================================
# get all the items of self.week and activate the allocation process
#G.filterItem = self.itemType
#G.filterWeek = self.week
#itemsToBeAssigned = filterWeek(G.Buffer[G.replication])
#itemsToBeAssigned = [x for x in G.Buffer[G.replication] if (x.originalWeek == self.week and x.future == self.itemType)]
itemsToBeAssigned = self.filterWeek(G.Buffer[G.replication])
assert len(itemsToBeAssigned) == noItems
sameRouteSameWeek = Allocation(itemList=itemsToBeAssigned, week=self.week, altRoutes=0, excBuffer=self.internalBuffer)
sameRouteSameWeek.Run()
#==========================================
# step 2: same route, previous weeks
#==========================================
# proceed only if there are excess items
self.week -= 1
while self.week >= 0 and (self.initialWeek - self.week) <= G.maxEarliness and len(self.internalBuffer):
itemsToBeAssigned = self.internalBuffer
self.internalBuffer = []
sameRoutePreviousWeeks = Allocation(itemList=itemsToBeAssigned, week=self.week, altRoutes=0, excBuffer=self.internalBuffer)
sameRoutePreviousWeeks.Run()
self.week -= 1
#===============================================================
# step 3: separate min quantity of excess demand from unconstrained qty
#===============================================================
# proceed only if there are excess items
if len(self.internalBuffer):
for item in self.internalBuffer:
# if the item presents min qty then create a new item and store it into minBuffer
if item.minQty:
newJob = Job(item.orderID, item.MAid, item.SPid, item.PPOSid, item.minQty, item.minQty, item.originalWeek, item.future)
self.minBuffer.append(newJob)
item.qty = item.qty - item.minQty
item.minQty = 0
if item.qty == 0:
self.internalBuffer.remove(item)
#============================================
# step 4: allocate min qty to later weeks
#============================================
self.week = self.initialWeek + 1
while self.week < G.planningHorizon and (self.week - self.initialWeek) <= G.maxLateness and len(self.minBuffer):
itemsToBeAssigned = self.minBuffer
self.minBuffer = []
sameRouteLaterWeeks = Allocation(itemList=itemsToBeAssigned, week=self.week, altRoutes=0, excBuffer=self.minBuffer)
sameRouteLaterWeeks.Run()
self.week += 1
# any excess items left in the minBuffer should be transferred into the global minBuffer
if len(self.minBuffer):
if self.itemType == 1:
G.ExcessFutureMinBuffer[G.replication] = self.minBuffer
else:
G.ExcessPPOSminBuffer[G.replication] = self.minBuffer
self.minBuffer = []
#========================================
# step 5: alternative route, same week
#========================================
self.week = self.initialWeek
if len(self.internalBuffer):
itemsToBeAssigned = self.internalBuffer
self.internalBuffer = []
altRouteSameWeek = Allocation(itemList=itemsToBeAssigned, week=self.week, altRoutes=1, excBuffer=self.internalBuffer)
altRouteSameWeek.Run()
#==============================================
# step 6: alternative route, previous weeks
#==============================================
self.week = self.initialWeek - 1
while self.week >= 0 and (self.initialWeek - self.week) <= G.maxEarliness and len(self.internalBuffer):
itemsToBeAssigned = self.internalBuffer
self.internalBuffer = []
altRoutePreviousWeeks = Allocation(itemList=itemsToBeAssigned, week=self.week, altRoutes=1, excBuffer=self.internalBuffer)
altRoutePreviousWeeks.Run()
self.week -= 1
#===================================================
# step 7: later weeks, same and alternative routes
#===================================================
self.week = self.initialWeek + 1
while self.week < G.planningHorizon and (self.week - self.initialWeek) <= G.maxLateness and len(self.internalBuffer):
# same route
itemsToBeAssigned = self.internalBuffer
self.internalBuffer = []
sameRouteLaterWeeks = Allocation(itemList=itemsToBeAssigned, week=self.week, altRoutes=0, excBuffer=self.internalBuffer)
sameRouteLaterWeeks.Run()
if len(self.internalBuffer):
itemsToBeAssigned = self.internalBuffer
self.internalBuffer = []
sameRouteLaterWeeks = Allocation(itemList=itemsToBeAssigned, week=self.week, altRoutes=1, excBuffer=self.internalBuffer)
sameRouteLaterWeeks.Run()
self.week += 1
#================================================
# transfer excess items into global buffers
#================================================
if len(self.internalBuffer):
if self.itemType == 1:
G.ExcessFutureBuffer[G.replication] = self.internalBuffer
print 'end allocation routine - excessBuffer', [i.orderID for i in G.ExcessFutureBuffer[G.replication]], [i.qty for i in G.ExcessFutureBuffer[G.replication]]
else:
G.ExcessPPOSBuffer[G.replication] = self.internalBuffer
self.internalBuffer = []
# go through the initial buffer and counts the number of items to be assigned at self.week
def checkNumberOfItems(self):
counter = 0
for item in G.Buffer[G.replication]:
if item.originalWeek == self.week and item.future == self.itemType:
counter += 1
return counter
def filterWeek(self,buf):
result = [x for x in buf if (x.originalWeek == self.week and self.itemType == x.future)]
return result
# filter function to get items of a specific week (self.week) from the initial buffer
#def filterWeek(buf):
#
# result = [x for x in buf if (x.originalWeek == G.filterWeek and G.filterItem == x.future)]
# return result
\ No newline at end of file
......@@ -28,9 +28,11 @@ test script to convert the static excels to JSON. It does not communicate with G
import xlwt
import xlrd
import json
from AllocManagement import AllocManagement
from dream.simulation.Globals import G
from dream.simulation.FutureDemandCreator import FutureDemandCreator
def createGlobals():
G.TargetPPOS = 0
G.TargetPPOSqty = 0
......@@ -150,8 +152,13 @@ def main():
G.argumentDictString=json.dumps(argumentDict, indent=5)
argumentDictFile.write(G.argumentDictString)
# create the future demand
FDC=FutureDemandCreator()
FDC.run()
#call the AllocManagement routine
AM = AllocManagement()
AM.Run()
if __name__ == '__main__':
main()
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