/
edf.py
190 lines (138 loc) · 7.46 KB
/
edf.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
import common
import csvGen
import chargePorts
import chargeEvent
from operator import attrgetter
edfQueue = []
# ------ EDF ------
earliestDLIndex = -1;
# the main function for Earliest Deadline First Algorithm
# takes in an array of vehicle interval arrays
def simulate( arrayOfVehicleArrivals ):
# reset global variables such as time, done/failed lots
common.updateGlobals( arrayOfVehicleArrivals )
global currentTime
global earliestDLIndex
# initialize a CSV document for storing all data
csvGen.generateCSV( "edf" )
# iterate through each vehicle in each minute
for minute, numVehiclesPerMin in enumerate( arrayOfVehicleArrivals ):
for vehicle in numVehiclesPerMin:
port = chargePorts.openChargePort()
# check if it actually needs to be charged
if vehicle.currentCharge > vehicle.chargeNeeded:
csvGen.exportVehicleToCSV( vehicle, "Charge Not Needed" )
common.cantChargeLot.append( vehicle )
continue
# a port is open so start charging the vehicle
if port is not None:
# add to chargePort
chargePorts.chargePorts[ port ] = vehicle
# initialize a listener object for its charging activity
chargePorts.chargePortListeners[ port ].insert( 0 , chargeEvent.ChargeEvent( vehicle, common.currentTime ) )
# no ports available so put in queue
else:
edfQueue.append( vehicle )
if earliestDLIndex == -1 or vehicle.depTime < edfQueue[ earliestDLIndex ].depTime:
earliestDLIndex = len( edfQueue ) - 1
updateVehiclesEDF()
common.currentTime += 1
# vehicles done arriving, now continue with the simulation
while chargePorts.chargePortsEmpty() == False or not len( edfQueue ) == 0:
updateVehiclesEDF()
common.currentTime += 1
# print "EDF: total number of cars: ", common.numberOfVehiclesInSimulation , \
# " elapsed time: " , common.currentTime , \
# " done charging lot: " , len( common.doneChargingLot ) , \
# " failed charging lot: " , len( common.failedLot ) , \
# " cant charge lot: " , len( common.cantChargeLot ) , \
# " edfQueue size: " , len( edfQueue ) , \
# " chargePort " , chargePorts.toString()
# write a CSV with all the chargePort logs
csvGen.exportChargePortsToCSV( "edf" )
output = [common.calcProfit(), len(common.doneChargingLot), len(common.failedLot), len(common.declinedLot), common.numberOfVehiclesInSimulation, common.currentTime]
return output
# called to update the vehicles for each minute of simulation
def updateVehiclesEDF():
global earliestDLIndex
global latestChargePortDLIndex
# cheack each chargePort
for index, vehicle in enumerate( chargePorts.chargePorts ):
# add one minute of charge
if vehicle is not None:
vehicle.currentCharge += ( vehicle.chargeRate ) / 60.0
removed = False
#check if done charging
if vehicle.currentCharge >= vehicle.chargeNeeded:
# finish up the listener for this vehicle
chargePorts.chargePortListeners[ index ][ 0 ].terminateCharge( vehicle , common.currentTime )
# remove finished vehicle from grid and document it
csvGen.exportVehicleToCSV( vehicle, "SUCCESS" )
common.doneChargingLot.append( vehicle )
if len( edfQueue ) > 0:
# get next vehicle and throw in chargePort
nextVehicle = edfQueue[ earliestDLIndex ]
chargePorts.chargePorts[ index ] = nextVehicle
# make it a listener
chargePorts.chargePortListeners[ index ].insert( 0 , chargeEvent.ChargeEvent( nextVehicle , common.currentTime ) )
# update queue
del edfQueue[ earliestDLIndex ]
earliestDLIndex = earliestDL()
else:
chargePorts.chargePorts[ index ] = None
removed = True
# check if deadline reached
if common.currentTime >= vehicle.depTime and not removed:
# this vehicle is on the out, so wrap up its listener
chargePorts.chargePortListeners[ index ][ 0 ].terminateCharge( vehicle , common.currentTime )
# remove finished vehicle and document it
csvGen.exportVehicleToCSV( vehicle, "FAILURE" )
common.failedLot.append( vehicle )
if len( edfQueue ) > 0:
# get nextVehicle
nextVehicle = edfQueue[ earliestDLIndex ]
chargePorts.chargePorts[ index ] = nextVehicle
# make new listener
chargePorts.chargePortListeners[ index ].insert( 0 , chargeEvent.ChargeEvent( nextVehicle , common.currentTime ) )
# update queue
del edfQueue[ earliestDLIndex ]
earliestDLIndex = earliestDL()
else:
chargePorts.chargePorts[ index ] = None
# now we want to make sure that all the cars in the chargePorts are the best choices
# we want to know the index of the worst car charging and compare that to the index of the best in the queue
# also need to be able to cycle the queue so that it will put ALL the cars in the queue that are better into the chargePorts
# edge cases to worry about: queue is empty, earliestDLIndex = -1
# start out by grabbing the latest chargePort
latestChargePortDLIndex = latestChargePortDL()
# prioritize edge cases, loop until swap the top DL are all in the queue
while len( edfQueue ) > 0 and latestChargePortDLIndex != -1 and edfQueue[ earliestDLIndex ].depTime < chargePorts.chargePorts[ latestChargePortDLIndex ].depTime:
swappingOut = chargePorts.chargePorts[ latestChargePortDLIndex ]
swappingIn = edfQueue[ earliestDLIndex ]
# close the listener for swappingOut
chargePorts.chargePortListeners[ latestChargePortDLIndex ][ 0 ].terminateCharge( swappingOut , common.currentTime )
# swap occurs in the chargePorts
chargePorts.chargePorts[ latestChargePortDLIndex ] = swappingIn
# create a new listener for the vehicle that just got swapped in
chargePorts.chargePortListeners[ latestChargePortDLIndex ].insert( 0 , chargeEvent.ChargeEvent( swappingIn , common.currentTime ) )
# swap finishes in the queue
edfQueue[ earliestDLIndex ] = swappingOut
# now update values for comparison
earliestDLIndex = earliestDL()
latestChargePortDLIndex = latestChargePortDL()
# NOTE: we are explicitly choosing to grab a clean version of each index because accuracy cannot be guaranteed
# gets the index of earliest deadline of all the vehicles in edfQueue
def earliestDL():
if len( edfQueue ) == 0:
return -1
return edfQueue.index( min( edfQueue, key = attrgetter( 'depTime' ) ) )
# gets the index of the vehicle in chargePorts with the latest deadline
def latestChargePortDL():
latestIndex = -1
latestTime = -1
for index, port in enumerate( chargePorts.chargePorts ):
if port is not None:
if port.depTime > latestTime:
latestTime = port.depTime
latestIndex = index
return latestIndex