Commit 5b1dffa9 authored by Georgios Dagkakis's avatar Georgios Dagkakis

Allocation scripts removed from GUI

parent 43bc660c
'''
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):
G.CurrentCapacityDict=G.CapacityDict
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)
k=0
print 'excess future', [i.orderID for i in G.ExcessFutureBuffer[k]], [i.qty for i in G.ExcessFutureBuffer[k]]
'''
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):
sufficient=True #flag that shows if we have sufficient capacity
# read the capacity that the MA requires
requiredCapacity={}
for x in G.RouteDict[MA.MAid]['route']:
requiredCapacity[x]=G.RouteDict[MA.MAid]['route'][x]*MA.qty
print '-'*100
print 'MA',MA.MAid,'week',self.week
print 'Quantity to allocate=', MA.qty
print 'required',requiredCapacity
print 'available', G.CurrentCapacityDict
# read the remaining capacity for thegiven week and subtract the required from it
remainingCapacity={}
for bottleneck in G.CurrentCapacityDict:
remainingCapacity[bottleneck]=G.CurrentCapacityDict[bottleneck][self.week]-requiredCapacity[bottleneck]
# if we dropped below zero then the capacity is not sufficient
if remainingCapacity[bottleneck]<0:
sufficient=False
#remainingCapacity = numpy.array(G.currentCapacity[self.week]) - numpy.array(requiredCapacity)
#remainingCapacity = remainingCapacity.tolist()
print 'remaining',remainingCapacity
print sufficient
# check if there is sufficient capacity to process the order
if sufficient:
# update remaining capacity
allocableQty = MA.qty
if MA.qty >= G.minPackingSize:
for bottleneck in G.CurrentCapacityDict:
G.CurrentCapacityDict[bottleneck][self.week]=remainingCapacity[bottleneck]
print 'allocation performed fully! remaining:'
print G.CurrentCapacityDict
# 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))]
excessUnits={}
excess=0
for bottleneck in remainingCapacity:
if requiredCapacity[bottleneck]>0 and remainingCapacity[bottleneck]<0:
excessUnits= remainingCapacity[bottleneck]/G.RouteDict[MA.MAid]['route'][bottleneck]
if math.ceil(math.fabs(excessUnits))>excess:
excess = math.ceil(math.fabs(excessUnits))
print 'excess', excess
# 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
print 'MA quantity', MA.qty
print 'allocableQty', allocableQty
if allocableQty >= G.minPackingSize:
#rCap = numpy.array(G.currentCapacity[self.week]) - numpy.multiply(allocableQty,G.route[MA.MAid])
for bottleneck in G.CurrentCapacityDict:
G.CurrentCapacityDict[bottleneck][self.week]-=allocableQty*G.RouteDict[MA.MAid]['route'][bottleneck]
print 'allocation performed partially! remaining:'
print G.CurrentCapacityDict
# 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
print '-'*100
def alternativeRoutes(self, MA):
sufficient=False #flag that shows if we have sufficient capacity
print '='*100
print 'MA',MA.MAid,'week',self.week
print 'Quantity to allocate=', MA.qty
# identify MAs with the same SP as the MA investigated
alternativeMADict={} #FIXME: the PPOS attribute can be used instead for the current MA
# loop through the MAinfo
for alernativeMA in G.RouteDict:
# if it is the same MA do not consider it
if alernativeMA==MA.MAid:
continue
# if the alternative MA is of the same SP add it to the list
PPOS=G.RouteDict[alernativeMA]['PPOS']
SP=G.RouteDict[alernativeMA]['SP']
if PPOS==MA.PPOSid and SP==MA.SPid:
alternativeMADict[alernativeMA]=G.RouteDict[alernativeMA]
print 'alternativeRoutes',alternativeMADict
print 'available',G.CurrentCapacityDict
# calculate max number of units for each alternative MA
maxUnits = {}
for alternativeMA in alternativeMADict:
MAunits=[]
for routeElement in alternativeMADict[alternativeMA]['route']:
units=alternativeMADict[alternativeMA]['route'][routeElement]
if units!= 0:
MAunits.append(G.CurrentCapacityDict[routeElement][self.week]/units)
sufficient=True
maxUnits[alternativeMA]=math.floor(min(MAunits))
print 'print units that can be allocated in alternative routes:', maxUnits
# choose MA with max number of units
if maxUnits and sufficient:
maxU=0
maxID=[]
for MAid in maxUnits:
if maxUnits[MAid]>maxU:
maxU=maxUnits[MAid]
maxID = [MAid]
if maxUnits[MAid]==maxU:
maxID.append(MAid)
# choose MA randomly among those with max number of units
chosenMAId = random.choice(maxID)
print 'chose to allocate in MA with id =', chosenMAId
allocableQty = min([maxU, MA.qty])
print 'in this route we can allocate ',allocableQty
if allocableQty >= G.minPackingSize:
for bottleneck in G.CurrentCapacityDict:
G.CurrentCapacityDict[bottleneck][self.week]-=allocableQty*G.RouteDict[chosenMAId]['route'][bottleneck]
print 'allocation performed in the alternative route! remaining:'
print G.CurrentCapacityDict
# 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, chosenMAId, 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, chosenMAId, 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
print '='*100
\ 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 JobMA
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 = JobMA(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
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