Berth Operation Simulation

Program Listing:

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 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225

# -*- coding: utf-8 -*-import sysimport codecsimport jsonimport randomimport simpy# Simulation Configurationclass CONFIGURATION(): # Defaults def __init__(self): self.params = { 'PT_MEAN': 50, # Service Average Time (Minutes) 'PT_SIGMA': 8, # Service Time Standard Deviation (Minutes) 'MTTF': 240, # Mean time to failure in minutes 'REPAIR_TEAM': 2, # Number of Repair Teams 'REPAIR_TIME': 30, # Repair Time (Minutes) 'SUPPORT_DURATION': 12, # Duration of Support Jobs (Minutes) 'NUM_BERTHS': 10, # Number of Berths 'WEEKS': 4 # Simulation Time (Weeks) } self.__derived__() # Derived Parameters def __derived__(self): # self.params['RANDOM_SEED'] = random.randint(20, 80) # Param. for expovariate distribution self.params['BREAK_MEAN'] = 1 / self.params['MTTF'] # Simulation time in minutes self.params['SIM_TIME'] = self.params['WEEKS'] * 7 * 24 * 60 # Read External Configuration File (JSON) def loadFromFile(self, sim_configFile): with codecs.open(sim_configFile, 'r', encoding='utf8') as jsonF: self.params = json.load(jsonF) self.__derived__() # Get Parameter Value by Name def getConfig(self, paramName): return self.params[paramName] # Define Ship Servicing Time def time_per_ship(self, vesselType=1): vesselTypeWeight = 1 / vesselType return random.normalvariate( vesselTypeWeight * self.params['PT_MEAN'], vesselTypeWeight * self.params['PT_SIGMA']) # Define Berth Survival Time def time_to_failure(self): return random.expovariate(self.params['BREAK_MEAN']) # Berth Operationclass Berth(object): # Instantiate def __init__(self, env, sim_config, name, repairTeam): self.env = env self.sim_config = sim_config self.name = name self.ships_served = {} self.berth_repaired = {} self.broken = False # Initiate Berth Operation Simulation self.process = env.process(self.servicing(repairTeam)) # Initiate Berth Repair Simulation self.env.process(self.break_berth()) # Service Ship Berth Operation def servicing(self, repairTeam): while True: # Dynamic Vessel Type vesselType = random.randint(1, self.sim_config.getConfig('VESSEL_TYPE')) # Ship Arrive to Berth done_in = self.sim_config.time_per_ship(vesselType) while done_in: try: # Service Start Time start = self.env.now yield self.env.timeout(done_in) done_in = 0 except simpy.Interrupt: self.broken = True # Calculate the Remaining Servicing Time done_in -= self.env.now - start # Request Berth Repair with High Priority with repairTeam.request(priority=1) as req: yield req # Wait for Repair Job Done yield self.env.timeout(self.sim_config.getConfig('REPAIR_TIME')) self.broken = False # Ship Completes Berth Operation if str(vesselType) in self.ships_served: self.ships_served[str(vesselType)] += 1 else: self.ships_served[str(vesselType)] = 1 # Berth Maintenance def break_berth(self): while True: # Awaiting Berth Broke _now_ = self.env.now # When Berth Broke if self.name in self.berth_repaired: self.berth_repaired[self.name].append(_now_) else: self.berth_repaired[self.name] = [_now_] yield self.env.timeout(self.sim_config.time_to_failure()) # Busy Berth if not self.broken: # Stop Berth Operation Servicing self.process.interrupt() # Ship Other Service Requestsdef support_jobs(env, sim_config, repairTeam): while True: # Ship Arrive to Berth done_in = sim_config.getConfig('SUPPORT_DURATION') while done_in: # Request Support Job with Low Priority with repairTeam.request(priority=2) as req: yield req try: # Support Job Start Time start = env.now yield env.timeout(done_in) done_in = 0 except simpy.Interrupt: # Calculate the Remaining Support Job Time done_in -= env.now - start # Berth Service/Repair Analysisdef service_statistics(sim_config, berths): print('Berth Operation: %s W (%d)' % ( sim_config.getConfig('WEEKS'), sim_config.getConfig('RANDOM_SEED'))) ship_type_served = {} for vesselType in range(sim_config.getConfig('VESSEL_TYPE')): ship_type_served[str(vesselType + 1)] = 0 # Berth Service Statistics for berth in berths: print('%s:' % (berth.name)) print(' Vessel Type:', end='\t') total_ship_served = 0 for vesselType in range(sim_config.getConfig('VESSEL_TYPE')): total_ship_served += berth.ships_served[str(vesselType + 1)] ship_type_served[str(vesselType + 1)] += berth.ships_served[str(vesselType + 1)] print('%6d' % (berth.ships_served[str(vesselType + 1)]), end='\t') print('%-6d' % total_ship_served) print(' Repair Time:') count = -1 for repair in berth.berth_repaired[berth.name]: print('\t\t%6d' % repair, end='\t') count += 1 if count % 3 == 2: print() print() # Vessel Type Served Statistics print('Vessel Type Statistics:', end='\t') ship_type_total_served = 0 for vesselType in range(sim_config.getConfig('VESSEL_TYPE')): ship_type_total_served += ship_type_served[str(vesselType + 1)] print('%6d' % (ship_type_served[str(vesselType + 1)]), end='\t') print('%6d' % ship_type_total_served) # Mainif __name__ == '__main__': # Configuration for Simulation sim_config = CONFIGURATION() # Giving Configuration File if len(sys.argv) > 0: sim_config.loadFromFile(sys.argv[1]) # Make the Result Changed Everytime random.seed(sim_config.getConfig('RANDOM_SEED')) # Simulation Initiation env = simpy.Environment() # Setup the Berth Repair Teams as Resource repairTeam = simpy.PreemptiveResource( env, capacity=sim_config.getConfig('REPAIR_TEAM')) # Setup the Berth Operation Consuming the Resource berths = [Berth(env, sim_config, 'Berth %d' % i, repairTeam) for i in range(sim_config.getConfig('NUM_BERTHS'))] # Setup the Berth Support Operation Consuming the Resource env.process(support_jobs(env, sim_config, repairTeam)) # Simulation Begin env.run(until=sim_config.getConfig('SIM_TIME')) # Berth Service/Repair Analyis service_statistics(sim_config, berths)

Result:

Berth 9: Vessel Type: 91 89 76 89 345 Repair Time: 0 786 1219 2104 2556 2634 2861 3181 3611 3629 3670 3846 4157 5179 5351 5972 6258 6303 6427 6734 6741 7011 7474 7795 8414 8480 8797 8912 9165 9345 9521 9753 10050 Vessel Type Statistics: 877 872 850 923 3522

Configuration:

1 2 3 4 5 6 7 8 9 10 11

{ "VESSEL_TYPE": 4, "PT_MEAN": 50, "PT_SIGMA": 10, "MTTF": 300, "REPAIR_TIME": 30, "SUPPORT_DURATION": 10, "NUM_BERTHS": 10, "REPAIR_TEAM": 3, "WEEKS": 1 }