simulation_classes.port
This module defines the port resources and their initialization for a port simulation. It includes classes for containers, cranes, berths, pipelines, conveyors, and their respective initialization methods. This module is part of a larger port simulation system that models the operations of a port, including handling of containers, liquid bulk, and dry bulk cargo.
1""" 2This module defines the port resources and their initialization for a port simulation. 3It includes classes for containers, cranes, berths, pipelines, conveyors, and their respective initialization methods. 4This module is part of a larger port simulation system that models the operations of a port, including handling of containers, liquid bulk, and dry bulk cargo. 5""" 6import simpy 7import random 8import pandas as pd 9import constants 10 11from simulation_handler.helpers import get_value_by_terminal, get_values_by_terminal_random_sample, normal_random_with_limit, get_value_from_terminal_tuple 12 13# initial terminal storage levels set as 50% 14prefill_yard_per = 0.5 15prefill_tank_per = 0.5 16prefill_silo_per = 0.5 17NUM_PILOTS_DAY = constants.NUM_PILOTS_DAY 18NUM_PILOTS_NIGHT = constants.NUM_PILOTS_NIGHT 19NUM_TUGBOATS = constants.NUM_TUGBOATS 20 21 22class Container: 23 """Class representing a container in the port yard. 24 Args: 25 id (str): Unique identifier for the container. 26 width (int): Width of the container. 27 """ 28 29 def __init__(self, id, width): 30 self.id = id 31 self.width = width 32 33 34class Crane: 35 """Class representing a crane in a container berth. 36 Args: 37 id (str): Unique identifier for the crane. 38 width (int): Width of the crane. 39 crane_transfer_rate (float): Rate at which the crane can transfer containers. 40 """ 41 42 def __init__(self, id, width, crane_transfer_rate): 43 self.id = id 44 self.width = width 45 self.crane_transfer_rate = crane_transfer_rate 46 47 48class Berth_Ctr: 49 """Class representing a container berth with multiple cranes. 50 Args: 51 env (simpy.Environment): The simulation environment. 52 id (str): Unique identifier for the berth. 53 cranes_per_berth (int): Number of cranes in the berth. 54 crane_transfer_rate (float): Rate at which each crane can transfer containers. 55 """ 56 57 def __init__(self, env, id, cranes_per_berth, crane_transfer_rate): 58 self.id = id 59 self.cranes = simpy.Store(env, capacity=cranes_per_berth) 60 self.crane_transfer_rate = crane_transfer_rate 61 for i in range(cranes_per_berth): 62 self.cranes.put( 63 Crane(id=f"{id}.{i}", width="width", crane_transfer_rate=crane_transfer_rate)) 64 65 66class Pipeline: 67 """Class representing a pipeline in a liquid berth. 68 Args: 69 env (simpy.Environment): The simulation environment. 70 id (str): Unique identifier for the pipeline. 71 pump_rate_per_pipeline (float): Rate at which the pipeline can pump liquid. 72 """ 73 74 def __init__(self, env, id, pump_rate_per_pipeline): 75 self.env = env 76 self.id = id 77 self.pump_rate_per_pipeline = pump_rate_per_pipeline 78 79 80class Berth_Liq: 81 """Class representing a liquid berth with multiple pipelines. 82 Args: 83 env (simpy.Environment): The simulation environment. 84 id (str): Unique identifier for the berth. 85 piplines_per_berth (int): Number of pipelines in the berth. 86 pump_rate_per_pipeline (float): Rate at which each pipeline can pump liquid. 87 """ 88 89 def __init__(self, env, id, piplines_per_berth, pump_rate_per_pipeline): 90 self.id = id 91 self.pipelines = simpy.Store(env, capacity=piplines_per_berth) 92 for i in range(piplines_per_berth): 93 self.pipelines.put(Pipeline( 94 env=env, id=f"{id}.{i}", pump_rate_per_pipeline=pump_rate_per_pipeline)) 95 96 97class Conveyor: 98 """ 99 Class representing a conveyor in a dry bulk berth. 100 Args: 101 env (simpy.Environment): The simulation environment. 102 id (str): Unique identifier for the conveyor. 103 conveyor_rate_per_conveyor (float): Rate at which the conveyor can transfer dry bulk. 104 """ 105 106 def __init__(self, env, id, conveyor_rate_per_conveyor): 107 self.env = env 108 self.id = id 109 self.conveyor_rate_per_conveyor = conveyor_rate_per_conveyor 110 111 112class Berth_DryBulk: 113 """Class representing a dry bulk berth with multiple conveyors. 114 Args: 115 env (simpy.Environment): The simulation environment. 116 id (str): Unique identifier for the berth. 117 conveyors_per_berth (int): Number of conveyors in the berth. 118 conveyor_rate_per_conveyor (float): Rate at which each conveyor can transfer dry bulk. 119 """ 120 121 def __init__(self, env, id, conveyors_per_berth, conveyor_rate_per_conveyor): 122 self.id = id 123 self.conveyors = simpy.Store(env, capacity=conveyors_per_berth) 124 for i in range(conveyors_per_berth): 125 self.conveyors.put(Conveyor( 126 env=env, id=f"{id}.{i}", conveyor_rate_per_conveyor=conveyor_rate_per_conveyor)) 127 128 129def create_resources(terminal_data, run_id, terminal_data_df, num_terminals, env, seed): 130 """ 131 Create and initialize resources for the port simulation based on terminal data. 132 This function sets up yards, berths, tanks, silos, loading bays, truck gates, train loading racks, 133 and pilot/tugboat resources for each terminal type (Container, Liquid, DryBulk). 134 Args: 135 terminal_data (dict): Dictionary containing terminal data. 136 run_id (str): Unique identifier for the simulation run. 137 terminal_data_df (pd.DataFrame): DataFrame containing terminal data. 138 num_terminals (tuple): Tuple containing the number of terminals for each cargo type (Container, Liquid, DryBulk). 139 env (simpy.Environment): The simulation environment. 140 seed (int): Random seed for reproducibility. 141 Returns: 142 terminal_resouces (list): List of resources created for each terminal type. This includes yards, berths, tanks, silos, loading bays, truck gates, train loading racks, pilots, tugboats, and channel scheduler. 143 """ 144 num_container_terminals, num_liquid_terminals, num_drybulk_terminals = num_terminals 145 146 ############################# 147 # Container terminal resources 148 ############################# 149 150 random.seed(seed) 151 # Yard 152 port_yard_container_terminals = [ 153 simpy.Store(env, capacity=get_value_by_terminal( 154 terminal_data, 'Container', idx + 1, 'storage volume')) 155 for idx in range(num_container_terminals) 156 ] 157 for idx in range(num_container_terminals): 158 initial_capacity = int(prefill_yard_per * get_value_by_terminal( 159 terminal_data, 'Container', idx + 1, 'storage volume')) 160 for i in range(initial_capacity): 161 port_yard_container_terminals[idx].put( 162 Container(id=f"initial_{i}", width=0)) 163 164 port_chassis_container_terminals = [ 165 simpy.Store(env, capacity=get_value_by_terminal(terminal_data, 'Container', idx + 166 1, 'truck bays/chassis')) # Setting capacity to infinity or a large value 167 for _ in range(num_container_terminals) 168 ] 169 170 # Initialize each store with the desired number of items 171 for idx, store in enumerate(port_chassis_container_terminals): 172 init_items = get_value_by_terminal( 173 terminal_data, 'Container', idx + 1, 'truck bays/chassis') 174 for _ in range(init_items): 175 store.put(1) 176 177 # Berths 178 port_berths_container_terminals = [ 179 simpy.Store(env, capacity=get_value_by_terminal( 180 terminal_data, 'Container', idx + 1, 'Berths')) 181 for idx in range(num_container_terminals) 182 ] 183 184 # Add cranes to the container berths 185 for idx, terminal in enumerate(port_berths_container_terminals): 186 num_cranes_list = get_values_by_terminal_random_sample( 187 terminal_data_df, 'Container', idx+1, 'transfer units per berth', num_samples=get_value_by_terminal(terminal_data, 'Container', idx + 1, 'Berths'), seed=seed) 188 189 for i in range(get_value_by_terminal(terminal_data, 'Container', idx + 1, 'Berths')): 190 terminal.put(Berth_Ctr(env=env, id=i, cranes_per_berth=num_cranes_list[i], crane_transfer_rate=get_value_by_terminal( 191 terminal_data, 'Container', idx + 1, 'transfer rate per unit'))) 192 # print(f"Container Terminal {idx+1} Berth {i} has {num_cranes_list[i]} cranes") 193 194 ############################# 195 # Liquid bulk terminal resources 196 ############################# 197 198 # Tanks 199 tank_capacity = [get_value_by_terminal( 200 terminal_data, 'Liquid', idx + 1, 'storage volume') for idx in range(num_liquid_terminals)] 201 port_tanks_liquid_terminals = [simpy.Container(env, capacity=capacity, init=int( 202 prefill_tank_per*capacity)) for capacity in tank_capacity] 203 204 # Loading bays 205 port_loading_bays_liquid_terminals = [simpy.Resource(env, capacity=get_value_by_terminal( 206 terminal_data, 'Liquid', idx + 1, 'truck bays/chassis')) for idx in range(num_liquid_terminals)] 207 208 # Berths 209 port_berth_liquid_terminals = [ 210 simpy.Store(env, capacity=get_value_by_terminal( 211 terminal_data, 'Liquid', idx + 1, 'Berths')) 212 for idx in range(num_liquid_terminals) 213 ] 214 215 # Add pipelines to the liquid berths 216 for idx, terminal in enumerate(port_berth_liquid_terminals): 217 num_pipelines_list = get_values_by_terminal_random_sample( 218 terminal_data_df, 'Liquid', idx+1, 'transfer units per berth', num_samples=get_value_by_terminal(terminal_data, 'Liquid', idx + 1, 'Berths'), seed=seed) 219 for i in range(get_value_by_terminal(terminal_data, 'Liquid', idx + 1, 'Berths')): 220 terminal.put(Berth_Liq(env=env, id=i, piplines_per_berth=num_pipelines_list[i], pump_rate_per_pipeline=get_value_by_terminal( 221 terminal_data, 'Liquid', idx + 1, 'transfer rate per unit'))) 222 # print(f"Liquid Terminal {idx+1} Berth {i} has {num_pipelines_list[i]} pipelines") 223 224 ############################# 225 # Dry bulk terminal resources 226 ############################# 227 228 # Silos 229 silo_capacity = [get_value_by_terminal( 230 terminal_data, 'DryBulk', idx + 1, 'storage volume') for idx in range(num_drybulk_terminals)] 231 port_silos_drybulk_terminals = [simpy.Container(env, capacity=capacity, init=int( 232 prefill_silo_per*capacity)) for capacity in silo_capacity] 233 234 # Drybulk bays 235 port_drybulk_bays_drybulk_terminals = [simpy.Resource(env, capacity=get_value_by_terminal( 236 terminal_data, 'DryBulk', idx + 1, 'truck bays/chassis')) for idx in range(num_drybulk_terminals)] 237 238 # Berths 239 port_berth_drybulk_terminals = [ 240 simpy.Store(env, capacity=get_value_by_terminal( 241 terminal_data, 'DryBulk', idx + 1, 'Berths')) 242 for idx in range(num_drybulk_terminals) 243 ] 244 245 # Conveyors 246 for idx, terminal in enumerate(port_berth_drybulk_terminals): 247 num_conveyors_list = get_values_by_terminal_random_sample( 248 terminal_data_df, 'DryBulk', idx+1, 'transfer units per berth', num_samples=get_value_by_terminal(terminal_data, 'DryBulk', idx + 1, 'Berths'), seed=seed) 249 for i in range(get_value_by_terminal(terminal_data, 'DryBulk', idx + 1, 'Berths')): 250 terminal.put(Berth_DryBulk(env=env, id=i, conveyors_per_berth=num_conveyors_list[i], conveyor_rate_per_conveyor=get_value_by_terminal( 251 terminal_data, 'DryBulk', idx + 1, 'transfer rate per unit'))) 252 # print(f"Drybulk Terminal {idx+1} Berth {i} has {num_conveyors_list[i]} conveyors") 253 254 ############################# 255 # Truck gates 256 ############################# 257 258 truck_gates_ctr = [simpy.Resource(env, capacity=get_value_by_terminal( 259 terminal_data, 'Container', idx + 1, 'truck gates')) for idx in range(num_container_terminals)] 260 truck_gates_liquid = [simpy.Resource(env, capacity=get_value_by_terminal( 261 terminal_data, 'Liquid', idx + 1, 'truck gates')) for idx in range(num_liquid_terminals)] 262 truck_gates_dk = [simpy.Resource(env, capacity=get_value_by_terminal( 263 terminal_data, 'DryBulk', idx + 1, 'truck gates')) for idx in range(num_drybulk_terminals)] 264 265 ############################# 266 # Train resources 267 ############################# 268 269 # Loading racks (for loading operations) 270 train_loading_racks_ctr = [ 271 simpy.Resource(env, capacity=get_value_by_terminal( 272 terminal_data, 'Container', idx + 1, 'train car loading bays')) 273 for idx in range(num_container_terminals) 274 ] 275 train_loading_racks_liquid = [ 276 simpy.Resource(env, capacity=get_value_by_terminal( 277 terminal_data, 'Liquid', idx + 1, 'train car loading bays')) 278 for idx in range(num_liquid_terminals) 279 ] 280 train_loading_racks_dk = [ 281 simpy.Resource(env, capacity=get_value_by_terminal( 282 terminal_data, 'DryBulk', idx + 1, 'train car loading bays')) 283 for idx in range(num_drybulk_terminals) 284 ] 285 286 ############################# 287 # Pilot and tugboat resources 288 ############################# 289 290 num_pilots_day = int(normal_random_with_limit( 291 NUM_PILOTS_DAY[0], NUM_PILOTS_DAY[1], seed)) 292 num_pilots_night = int(normal_random_with_limit( 293 NUM_PILOTS_NIGHT[0], NUM_PILOTS_NIGHT[1], seed)) 294 num_tugboats = int(normal_random_with_limit( 295 NUM_TUGBOATS[0], NUM_TUGBOATS[1], seed)) 296 297 report_path = f".{run_id}/logs/final_report.txt" 298 with open(report_path, 'a') as f: 299 f.write(f"Num pilots in day shift: {num_pilots_day}\n") 300 f.write(f"Num pilots in night shift: {num_pilots_night}\n") 301 f.write(f"Num tugboats: {num_tugboats}\n\n") 302 303 day_pilots = simpy.Container( 304 env, init=num_pilots_day, capacity=num_pilots_day) 305 night_pilots = simpy.Container( 306 env, init=num_pilots_night, capacity=num_pilots_night) 307 tugboats = simpy.Container(env, init=num_tugboats, capacity=num_tugboats) 308 309 ############################# 310 # Channel scheduler 311 ############################# 312 313 # Only one ship can be scheduled at a time 314 channel_scheduer = simpy.Resource(env, capacity=1) 315 316 ############################# 317 # Combines and returns all terminal resources for all cargo types 318 ############################# 319 320 terminal_resouces = [port_berths_container_terminals, port_yard_container_terminals, port_berth_liquid_terminals, 321 port_tanks_liquid_terminals, port_berth_drybulk_terminals, port_silos_drybulk_terminals, 322 port_loading_bays_liquid_terminals, port_drybulk_bays_drybulk_terminals, port_chassis_container_terminals, 323 truck_gates_ctr, truck_gates_liquid, truck_gates_dk, train_loading_racks_ctr, train_loading_racks_liquid, 324 train_loading_racks_dk, day_pilots, night_pilots, tugboats, channel_scheduer] 325 return terminal_resouces
23class Container: 24 """Class representing a container in the port yard. 25 Args: 26 id (str): Unique identifier for the container. 27 width (int): Width of the container. 28 """ 29 30 def __init__(self, id, width): 31 self.id = id 32 self.width = width
Class representing a container in the port yard.
Arguments:
- id (str): Unique identifier for the container.
- width (int): Width of the container.
35class Crane: 36 """Class representing a crane in a container berth. 37 Args: 38 id (str): Unique identifier for the crane. 39 width (int): Width of the crane. 40 crane_transfer_rate (float): Rate at which the crane can transfer containers. 41 """ 42 43 def __init__(self, id, width, crane_transfer_rate): 44 self.id = id 45 self.width = width 46 self.crane_transfer_rate = crane_transfer_rate
Class representing a crane in a container berth.
Arguments:
- id (str): Unique identifier for the crane.
- width (int): Width of the crane.
- crane_transfer_rate (float): Rate at which the crane can transfer containers.
49class Berth_Ctr: 50 """Class representing a container berth with multiple cranes. 51 Args: 52 env (simpy.Environment): The simulation environment. 53 id (str): Unique identifier for the berth. 54 cranes_per_berth (int): Number of cranes in the berth. 55 crane_transfer_rate (float): Rate at which each crane can transfer containers. 56 """ 57 58 def __init__(self, env, id, cranes_per_berth, crane_transfer_rate): 59 self.id = id 60 self.cranes = simpy.Store(env, capacity=cranes_per_berth) 61 self.crane_transfer_rate = crane_transfer_rate 62 for i in range(cranes_per_berth): 63 self.cranes.put( 64 Crane(id=f"{id}.{i}", width="width", crane_transfer_rate=crane_transfer_rate))
Class representing a container berth with multiple cranes.
Arguments:
- env (simpy.Environment): The simulation environment.
- id (str): Unique identifier for the berth.
- cranes_per_berth (int): Number of cranes in the berth.
- crane_transfer_rate (float): Rate at which each crane can transfer containers.
67class Pipeline: 68 """Class representing a pipeline in a liquid berth. 69 Args: 70 env (simpy.Environment): The simulation environment. 71 id (str): Unique identifier for the pipeline. 72 pump_rate_per_pipeline (float): Rate at which the pipeline can pump liquid. 73 """ 74 75 def __init__(self, env, id, pump_rate_per_pipeline): 76 self.env = env 77 self.id = id 78 self.pump_rate_per_pipeline = pump_rate_per_pipeline
Class representing a pipeline in a liquid berth.
Arguments:
- env (simpy.Environment): The simulation environment.
- id (str): Unique identifier for the pipeline.
- pump_rate_per_pipeline (float): Rate at which the pipeline can pump liquid.
81class Berth_Liq: 82 """Class representing a liquid berth with multiple pipelines. 83 Args: 84 env (simpy.Environment): The simulation environment. 85 id (str): Unique identifier for the berth. 86 piplines_per_berth (int): Number of pipelines in the berth. 87 pump_rate_per_pipeline (float): Rate at which each pipeline can pump liquid. 88 """ 89 90 def __init__(self, env, id, piplines_per_berth, pump_rate_per_pipeline): 91 self.id = id 92 self.pipelines = simpy.Store(env, capacity=piplines_per_berth) 93 for i in range(piplines_per_berth): 94 self.pipelines.put(Pipeline( 95 env=env, id=f"{id}.{i}", pump_rate_per_pipeline=pump_rate_per_pipeline))
Class representing a liquid berth with multiple pipelines.
Arguments:
- env (simpy.Environment): The simulation environment.
- id (str): Unique identifier for the berth.
- piplines_per_berth (int): Number of pipelines in the berth.
- pump_rate_per_pipeline (float): Rate at which each pipeline can pump liquid.
98class Conveyor: 99 """ 100 Class representing a conveyor in a dry bulk berth. 101 Args: 102 env (simpy.Environment): The simulation environment. 103 id (str): Unique identifier for the conveyor. 104 conveyor_rate_per_conveyor (float): Rate at which the conveyor can transfer dry bulk. 105 """ 106 107 def __init__(self, env, id, conveyor_rate_per_conveyor): 108 self.env = env 109 self.id = id 110 self.conveyor_rate_per_conveyor = conveyor_rate_per_conveyor
Class representing a conveyor in a dry bulk berth. Args: env (simpy.Environment): The simulation environment. id (str): Unique identifier for the conveyor. conveyor_rate_per_conveyor (float): Rate at which the conveyor can transfer dry bulk.
113class Berth_DryBulk: 114 """Class representing a dry bulk berth with multiple conveyors. 115 Args: 116 env (simpy.Environment): The simulation environment. 117 id (str): Unique identifier for the berth. 118 conveyors_per_berth (int): Number of conveyors in the berth. 119 conveyor_rate_per_conveyor (float): Rate at which each conveyor can transfer dry bulk. 120 """ 121 122 def __init__(self, env, id, conveyors_per_berth, conveyor_rate_per_conveyor): 123 self.id = id 124 self.conveyors = simpy.Store(env, capacity=conveyors_per_berth) 125 for i in range(conveyors_per_berth): 126 self.conveyors.put(Conveyor( 127 env=env, id=f"{id}.{i}", conveyor_rate_per_conveyor=conveyor_rate_per_conveyor))
Class representing a dry bulk berth with multiple conveyors.
Arguments:
- env (simpy.Environment): The simulation environment.
- id (str): Unique identifier for the berth.
- conveyors_per_berth (int): Number of conveyors in the berth.
- conveyor_rate_per_conveyor (float): Rate at which each conveyor can transfer dry bulk.
130def create_resources(terminal_data, run_id, terminal_data_df, num_terminals, env, seed): 131 """ 132 Create and initialize resources for the port simulation based on terminal data. 133 This function sets up yards, berths, tanks, silos, loading bays, truck gates, train loading racks, 134 and pilot/tugboat resources for each terminal type (Container, Liquid, DryBulk). 135 Args: 136 terminal_data (dict): Dictionary containing terminal data. 137 run_id (str): Unique identifier for the simulation run. 138 terminal_data_df (pd.DataFrame): DataFrame containing terminal data. 139 num_terminals (tuple): Tuple containing the number of terminals for each cargo type (Container, Liquid, DryBulk). 140 env (simpy.Environment): The simulation environment. 141 seed (int): Random seed for reproducibility. 142 Returns: 143 terminal_resouces (list): List of resources created for each terminal type. This includes yards, berths, tanks, silos, loading bays, truck gates, train loading racks, pilots, tugboats, and channel scheduler. 144 """ 145 num_container_terminals, num_liquid_terminals, num_drybulk_terminals = num_terminals 146 147 ############################# 148 # Container terminal resources 149 ############################# 150 151 random.seed(seed) 152 # Yard 153 port_yard_container_terminals = [ 154 simpy.Store(env, capacity=get_value_by_terminal( 155 terminal_data, 'Container', idx + 1, 'storage volume')) 156 for idx in range(num_container_terminals) 157 ] 158 for idx in range(num_container_terminals): 159 initial_capacity = int(prefill_yard_per * get_value_by_terminal( 160 terminal_data, 'Container', idx + 1, 'storage volume')) 161 for i in range(initial_capacity): 162 port_yard_container_terminals[idx].put( 163 Container(id=f"initial_{i}", width=0)) 164 165 port_chassis_container_terminals = [ 166 simpy.Store(env, capacity=get_value_by_terminal(terminal_data, 'Container', idx + 167 1, 'truck bays/chassis')) # Setting capacity to infinity or a large value 168 for _ in range(num_container_terminals) 169 ] 170 171 # Initialize each store with the desired number of items 172 for idx, store in enumerate(port_chassis_container_terminals): 173 init_items = get_value_by_terminal( 174 terminal_data, 'Container', idx + 1, 'truck bays/chassis') 175 for _ in range(init_items): 176 store.put(1) 177 178 # Berths 179 port_berths_container_terminals = [ 180 simpy.Store(env, capacity=get_value_by_terminal( 181 terminal_data, 'Container', idx + 1, 'Berths')) 182 for idx in range(num_container_terminals) 183 ] 184 185 # Add cranes to the container berths 186 for idx, terminal in enumerate(port_berths_container_terminals): 187 num_cranes_list = get_values_by_terminal_random_sample( 188 terminal_data_df, 'Container', idx+1, 'transfer units per berth', num_samples=get_value_by_terminal(terminal_data, 'Container', idx + 1, 'Berths'), seed=seed) 189 190 for i in range(get_value_by_terminal(terminal_data, 'Container', idx + 1, 'Berths')): 191 terminal.put(Berth_Ctr(env=env, id=i, cranes_per_berth=num_cranes_list[i], crane_transfer_rate=get_value_by_terminal( 192 terminal_data, 'Container', idx + 1, 'transfer rate per unit'))) 193 # print(f"Container Terminal {idx+1} Berth {i} has {num_cranes_list[i]} cranes") 194 195 ############################# 196 # Liquid bulk terminal resources 197 ############################# 198 199 # Tanks 200 tank_capacity = [get_value_by_terminal( 201 terminal_data, 'Liquid', idx + 1, 'storage volume') for idx in range(num_liquid_terminals)] 202 port_tanks_liquid_terminals = [simpy.Container(env, capacity=capacity, init=int( 203 prefill_tank_per*capacity)) for capacity in tank_capacity] 204 205 # Loading bays 206 port_loading_bays_liquid_terminals = [simpy.Resource(env, capacity=get_value_by_terminal( 207 terminal_data, 'Liquid', idx + 1, 'truck bays/chassis')) for idx in range(num_liquid_terminals)] 208 209 # Berths 210 port_berth_liquid_terminals = [ 211 simpy.Store(env, capacity=get_value_by_terminal( 212 terminal_data, 'Liquid', idx + 1, 'Berths')) 213 for idx in range(num_liquid_terminals) 214 ] 215 216 # Add pipelines to the liquid berths 217 for idx, terminal in enumerate(port_berth_liquid_terminals): 218 num_pipelines_list = get_values_by_terminal_random_sample( 219 terminal_data_df, 'Liquid', idx+1, 'transfer units per berth', num_samples=get_value_by_terminal(terminal_data, 'Liquid', idx + 1, 'Berths'), seed=seed) 220 for i in range(get_value_by_terminal(terminal_data, 'Liquid', idx + 1, 'Berths')): 221 terminal.put(Berth_Liq(env=env, id=i, piplines_per_berth=num_pipelines_list[i], pump_rate_per_pipeline=get_value_by_terminal( 222 terminal_data, 'Liquid', idx + 1, 'transfer rate per unit'))) 223 # print(f"Liquid Terminal {idx+1} Berth {i} has {num_pipelines_list[i]} pipelines") 224 225 ############################# 226 # Dry bulk terminal resources 227 ############################# 228 229 # Silos 230 silo_capacity = [get_value_by_terminal( 231 terminal_data, 'DryBulk', idx + 1, 'storage volume') for idx in range(num_drybulk_terminals)] 232 port_silos_drybulk_terminals = [simpy.Container(env, capacity=capacity, init=int( 233 prefill_silo_per*capacity)) for capacity in silo_capacity] 234 235 # Drybulk bays 236 port_drybulk_bays_drybulk_terminals = [simpy.Resource(env, capacity=get_value_by_terminal( 237 terminal_data, 'DryBulk', idx + 1, 'truck bays/chassis')) for idx in range(num_drybulk_terminals)] 238 239 # Berths 240 port_berth_drybulk_terminals = [ 241 simpy.Store(env, capacity=get_value_by_terminal( 242 terminal_data, 'DryBulk', idx + 1, 'Berths')) 243 for idx in range(num_drybulk_terminals) 244 ] 245 246 # Conveyors 247 for idx, terminal in enumerate(port_berth_drybulk_terminals): 248 num_conveyors_list = get_values_by_terminal_random_sample( 249 terminal_data_df, 'DryBulk', idx+1, 'transfer units per berth', num_samples=get_value_by_terminal(terminal_data, 'DryBulk', idx + 1, 'Berths'), seed=seed) 250 for i in range(get_value_by_terminal(terminal_data, 'DryBulk', idx + 1, 'Berths')): 251 terminal.put(Berth_DryBulk(env=env, id=i, conveyors_per_berth=num_conveyors_list[i], conveyor_rate_per_conveyor=get_value_by_terminal( 252 terminal_data, 'DryBulk', idx + 1, 'transfer rate per unit'))) 253 # print(f"Drybulk Terminal {idx+1} Berth {i} has {num_conveyors_list[i]} conveyors") 254 255 ############################# 256 # Truck gates 257 ############################# 258 259 truck_gates_ctr = [simpy.Resource(env, capacity=get_value_by_terminal( 260 terminal_data, 'Container', idx + 1, 'truck gates')) for idx in range(num_container_terminals)] 261 truck_gates_liquid = [simpy.Resource(env, capacity=get_value_by_terminal( 262 terminal_data, 'Liquid', idx + 1, 'truck gates')) for idx in range(num_liquid_terminals)] 263 truck_gates_dk = [simpy.Resource(env, capacity=get_value_by_terminal( 264 terminal_data, 'DryBulk', idx + 1, 'truck gates')) for idx in range(num_drybulk_terminals)] 265 266 ############################# 267 # Train resources 268 ############################# 269 270 # Loading racks (for loading operations) 271 train_loading_racks_ctr = [ 272 simpy.Resource(env, capacity=get_value_by_terminal( 273 terminal_data, 'Container', idx + 1, 'train car loading bays')) 274 for idx in range(num_container_terminals) 275 ] 276 train_loading_racks_liquid = [ 277 simpy.Resource(env, capacity=get_value_by_terminal( 278 terminal_data, 'Liquid', idx + 1, 'train car loading bays')) 279 for idx in range(num_liquid_terminals) 280 ] 281 train_loading_racks_dk = [ 282 simpy.Resource(env, capacity=get_value_by_terminal( 283 terminal_data, 'DryBulk', idx + 1, 'train car loading bays')) 284 for idx in range(num_drybulk_terminals) 285 ] 286 287 ############################# 288 # Pilot and tugboat resources 289 ############################# 290 291 num_pilots_day = int(normal_random_with_limit( 292 NUM_PILOTS_DAY[0], NUM_PILOTS_DAY[1], seed)) 293 num_pilots_night = int(normal_random_with_limit( 294 NUM_PILOTS_NIGHT[0], NUM_PILOTS_NIGHT[1], seed)) 295 num_tugboats = int(normal_random_with_limit( 296 NUM_TUGBOATS[0], NUM_TUGBOATS[1], seed)) 297 298 report_path = f".{run_id}/logs/final_report.txt" 299 with open(report_path, 'a') as f: 300 f.write(f"Num pilots in day shift: {num_pilots_day}\n") 301 f.write(f"Num pilots in night shift: {num_pilots_night}\n") 302 f.write(f"Num tugboats: {num_tugboats}\n\n") 303 304 day_pilots = simpy.Container( 305 env, init=num_pilots_day, capacity=num_pilots_day) 306 night_pilots = simpy.Container( 307 env, init=num_pilots_night, capacity=num_pilots_night) 308 tugboats = simpy.Container(env, init=num_tugboats, capacity=num_tugboats) 309 310 ############################# 311 # Channel scheduler 312 ############################# 313 314 # Only one ship can be scheduled at a time 315 channel_scheduer = simpy.Resource(env, capacity=1) 316 317 ############################# 318 # Combines and returns all terminal resources for all cargo types 319 ############################# 320 321 terminal_resouces = [port_berths_container_terminals, port_yard_container_terminals, port_berth_liquid_terminals, 322 port_tanks_liquid_terminals, port_berth_drybulk_terminals, port_silos_drybulk_terminals, 323 port_loading_bays_liquid_terminals, port_drybulk_bays_drybulk_terminals, port_chassis_container_terminals, 324 truck_gates_ctr, truck_gates_liquid, truck_gates_dk, train_loading_racks_ctr, train_loading_racks_liquid, 325 train_loading_racks_dk, day_pilots, night_pilots, tugboats, channel_scheduer] 326 return terminal_resouces
Create and initialize resources for the port simulation based on terminal data. This function sets up yards, berths, tanks, silos, loading bays, truck gates, train loading racks, and pilot/tugboat resources for each terminal type (Container, Liquid, DryBulk).
Arguments:
- terminal_data (dict): Dictionary containing terminal data.
- run_id (str): Unique identifier for the simulation run.
- terminal_data_df (pd.DataFrame): DataFrame containing terminal data.
- num_terminals (tuple): Tuple containing the number of terminals for each cargo type (Container, Liquid, DryBulk).
- env (simpy.Environment): The simulation environment.
- seed (int): Random seed for reproducibility.
Returns:
terminal_resouces (list): List of resources created for each terminal type. This includes yards, berths, tanks, silos, loading bays, truck gates, train loading racks, pilots, tugboats, and channel scheduler.