def assign_transporter(self, container): # """the function 'find closest transporter' is called and the closest and available transporter is matched to # the container""" closest_transporter = self.find_closest_transporter(container) if closest_transporter is not None: for transporter in self.transporters: if transporter == closest_transporter: # the status of the entities is updated transporter.state = TransporterState.PICKUP transporter.transport_contract.append(container) transporter.route_length = \ route_euclidean_distance(self.env,container.location, transporter.location) if container.state == ContainerState.NEEDING_TRANSPORT: container.state = ContainerState.AWAITING_TRANSPORT elif container.state == ContainerState.RELOCATION_NEED: container.state = ContainerState.AWAITING_RELOCATION if self.env.config.debug is True: print("Transporter %s is assigned to pickup " "container %s that is in need of relocation" %(transporter.id, container.id)) return
def reached_shipment_pickup(self): # UPDATE TRANSPORTER INFO # location and state info with shipment info from container contract self.region = self.load.shipment_contracts[0].region self.location = self.load.shipment_contracts[0].location self.route_length += route_euclidean_distance( self.env, self.location, self.load.shipment_contracts[0].destination) # UPDATE CONTAINER INFO (= self.load) # location and state info update with updated transporter info (above) self.load.region = self.region self.load.location = self.location self.load.state = ContainerState.DELIVERING # add shipment to container load self.load.load = self.load.shipment_contracts[0] # UPDATE SHIPMENT INFO (= container.load, therefore self.load.load) self.load.load.state = ShipmentState.ON_ROUTE # UPDATE PRODUCER INFO # remove picked up shipment from producer's storage self.env.producers[self.load.load.producer_id].storage = \ [shipment for shipment in self.env.producers[self.load.load.producer_id].storage if shipment.id != self.load.load.id] if self.env.config.debug is True: print("Transporter %s reached shipment %s pickup location" "and has an updated route length of: %s" % (self.id, self.load.shipment_contracts[0].id, self.route_length))
def find_closest_transporter(self, container): #each transporter's status from the list in the init is checked available_transporters = [transporter for transporter in self.transporters if transporter.state == TransporterState.EMPTY] if len(available_transporters) > 0: closest_distance_to_pickup = \ [route_euclidean_distance(self.env, container.location, available_transporters[0].location), available_transporters[0]] for transporter in available_transporters: distance_to_pickup = \ route_euclidean_distance(self.env, container.location, transporter.location) if distance_to_pickup < closest_distance_to_pickup[0]: closest_distance_to_pickup = \ [distance_to_pickup,transporter] return closest_distance_to_pickup[1] return
def bid(self, registrationkey, item: Shipment): ''' Minimum shipment biddingvalue consists of: 1) transport costs from hub to pickup location 2) transport costs from pickup location to destination''' producerbid = namedtuple('producerbid', 'registration_key biddingvalue') hub_coords = find_hub_coordinates(self.region) transport_cost_from_hub = self.env.config.transport_cost * \ route_euclidean_distance(self.env, hub_coords, item.location) transport_cost_to_destination = self.env.config.transport_cost * \ route_euclidean_distance(self.env, item.location, item.destination) #TODO improve biddingvalue based on shipping urgency storage_utilisation = len(self.storage) / self.storage_capacity # using steps of 10% for urgency storage_utilisation = ceil(storage_utilisation * 10) urgency = storage_utilisation / 10 # urgency cost based on region size shipping_urgency_cost = urgency * \ self.env.config.region_size * \ self.env.config.transport_cost #TODO add standard fees for container functionalties total_value = transport_cost_from_hub + transport_cost_to_destination \ + shipping_urgency_cost producerbid = producerbid(registration_key=registrationkey, biddingvalue=total_value) if self.env.config.debug is True and self.region.id < 1: print("producer %s in region: %s enters bid: %s " "for shipment with id: %s" % (self.id, self.region.id, producerbid, item.id)) return producerbid
def create_bids(self, best_shipments, registrationkey): """ creates the list with bids. The return function leaves the current function call with the list with bids as return value """ containerbid = namedtuple( 'containerbid', 'container_registration_key shipment_registration_key biddingvalue' ) containerbids = [] for entry in best_shipments: shipment_registration_key = entry[0] shipment = entry[2] transport_cost_empty = route_euclidean_distance( self.env, self.location, shipment.location) transport_cost_shipment = route_euclidean_distance( self.env, shipment.location, shipment.destination) biddingvalue = transport_cost_empty + transport_cost_shipment #TODO add additional profit margin for container or decrease of biddingvalue based on urgency container_bid = containerbid( container_registration_key=registrationkey, shipment_registration_key=shipment_registration_key, biddingvalue=biddingvalue) containerbids.append(container_bid) return containerbids
def reached_relocating_container(self): # UPDATE TRANSPORTER INFO # update location and state info from transport contract self.region = self.transport_contract[0].region self.location = self.transport_contract[0].location self.state = TransporterState.TRANSPORTING # Add container to load from contract self.load = self.transport_contract[0] # new route is from container location to region hub self.route_length += route_euclidean_distance( self.env, self.location, find_hub_coordinates(self.region)) # UPDATE CONTAINER INFO self.transport_contract[0].state = ContainerState.RELOCATING if self.env.config.debug is True: print("Container % is picked up and will be relocated" % (self.load.id))
def reached_empty_container(self): # UPDATE TRANSPORTER INFO # location and state info self.region = self.transport_contract[0].region self.location = self.transport_contract[0].location self.state = TransporterState.TRANSPORTING # assign container to load self.load = self.transport_contract[0] # new route is from container pick up location to shipment # pick up location self.route_length += route_euclidean_distance( self.env, self.location, self.load.shipment_contracts[0].location) # UPDATE CONTAINER INFO self.transport_contract[0].state = ContainerState.PICKUP if self.env.config.debug is True: print("Transporter %s reached container %s and " "has an updated route length of: %s" % (self.id, self.transport_contract[0].id, self.route_length))
def select_best_shipments(self, available_shipments): ''' In the final model, the container should make transport reservations for each shipment it bids on, therefore the container places a limited number of bids. The container makes a selection based on the distance to the shipments. The closer a container is to a shipment, the lower it can bid.''' distance_to_shipments = [] for key in available_shipments.keys(): shipment = self.region.auctioneer.entities[ EntityTypes.SHIPMENT][key] distance = route_euclidean_distance(self.env, self.location, shipment.location) registrationkey = key distance_to_shipments.append([registrationkey, distance, shipment]) distance_to_shipments.sort(key=lambda item: item[1]) best_shipments = distance_to_shipments[:self.env.config.number_of_bids] if self.env.config.debug and self.id < 1: print("\n", distance_to_shipments) print("from this list, the container should select the %s " "closest shipments" % (self.env.config.number_of_bids)) print(best_shipments, "\n") return best_shipments
def calculate_matching_distance(matches, auctioneer, matching_distances: list, day): if matches is None: return if day < Config.warmup_period: return for match in matches: # first determine container location for key in auctioneer.entities[EntityTypes.CONTAINER]: if match.container_registration_key == key: container_location = \ auctioneer.entities[EntityTypes.CONTAINER][key].location # determine shipment location for key in auctioneer.entities[EntityTypes.SHIPMENT]: if match.shipment_registration_key == key: shipment_location = \ auctioneer.entities[EntityTypes.SHIPMENT][key].location match_distance = route_euclidean_distance(auctioneer.env, container_location, shipment_location) matching_distances.append(match_distance) return matching_distances