def __init__(self, wait_dict, serve_dict, finish_dict, cancel_dict): self.__logger = Logger("RiderStatusTracker") self.__wait_dict = wait_dict self.__serve_dict = serve_dict self.__finish_dict = finish_dict self.__cancel_dict = cancel_dict
def __init__(self, readings_conn): # get to the ip address of the single base unit try: ip_addr = SysWideConfig.prop_val('deployment', 'wbu_ip') except: Logger.err( f"Failed to determine the ip addr of the base unit. Aborting." ) sys.exit() try: port = SysWideConfig.prop_val('deployment', 'wbu_port') except: Logger.err( f"Failed to determine the port of the base unit. Aborting.") sys.exit() # make the base unit connection object. the connection handle will reside with it. self.wbu_conn = WBUConn(wbu_ip=ip_addr, wbu_port=port) self.readings_conn = readings_conn # prep the sensors self.sensors = [] self._prep_sensors()
def __init__(self, uID, sT, sZ, dZ, dP, pat, srcX, srcY, destX, destY): # logger in Dispatcher self.__logger = Logger('Rider') #self.__logger.setLevel(logging.DEBUG) self.__logger.info(Rider.timestamp, "__INIT__", None, None, "Create A Rider Object") self.__id = uID self.__request_timestamp = sT self.__srcZone = sZ self.__destZone = dZ self.__default_price = dP self.__price = math.inf self.__patience = pat self.__dirID = self.__assignDirID(srcX, srcY, destX, destY) self.__shortest_time = Graph.queryTravelCost(sZ, dZ) self.__arrival_timestamp = None self.__groupID = None self.__status = WAITING self.__wait_time = 0 self.__detour_time = -1 self.__sat = 0 if self.__default_price > 100: self.__logger.warning(Rider.timestamp, "__INIT__", None, self.getID(), str(self))
def connect(self): if self.wbu_conn_handle is not None: try: self.wbu_conn_handle = self.wbu_conn.open() return True except: Logger.err(f"failed to open the connection") return False
def __init__(self, wbu_ip, wbu_port): self.wbu_ip = wbu_ip self.wbu_conn_handle = None # the handle made within the connection upon making the connection try: self.wbu_conn = ModbusClient(host=wbu_ip, port=502) except Exception as e: Logger.err(f"unable to make the connection to WBU: {e}") sys.exit()
def connect(self): # make the connection to the db try: self.handle = sqlite3.connect(self.db_file) except sqlite3.Error as e: Logger.err( f'Failed to make the connection to the SQLite3 db: {e}. Aborting.' ) sys.exit()
def __init__(self): self.__logger = Logger('Simulation') #self.__logger.setLevel(logging.DEBUG) self.__logger.info(-1, "__INIT__", None, None, "Create Simulation Object.") self.__driver_list = RequestList() self.__rider_list = RequestList() self.__dispatcher = Dispatcher() self.__cycle = 0 self.__sim_time = []
def __init__(self): #logger in Dispatcher self.__logger = Logger('Dispatcher') self.__logger.setLevel(logging.DEBUG) self.__logger.info(Dispatcher.timestamp, "__INIT__", None, None, "Create A Dispatcher Object") #Storage for drivers and riders self.__driver_dict = {} self.__rider_wait_dict = {} self.__rider_serve_dict = {} self.__rider_finish_dict = {} self.__rider_cancel_dict = {} #Performance of driver and rider self.wait_rider={} self.no_work_driver={} self.idle_driver_before_match={} self.grp_in_4=0 self.grp_in_3=0 self.grp_in_2=0 self.grp_in_1=0 #Cluser Strategy self.__cluster_strategy = ClusteringByDir(self.__rider_wait_dict) #Matching Strategy self.__match_strategy = MatchingInQueue(self.__driver_dict, self.__rider_wait_dict, self.__rider_serve_dict) #Driver Status Tracker self.__driver_tracker = DriverStatusTracker(self.__driver_dict) #Rider Status tracker self.__rider_tracker = RiderStatusTracker(self.__rider_wait_dict, self.__rider_serve_dict, self.__rider_finish_dict, self.__rider_cancel_dict) #Driver Dict for zone_id in range(1,78): self.__driver_dict[zone_id] = {} #Rider Dict for zone_id in range(1,78): self.__rider_wait_dict[zone_id] = {} for dir_id in range(-1, 12): self.__rider_wait_dict[zone_id][dir_id] = defaultdict(dict) # for cycle in range(SIMULATION_CYCLE_START, SIMULATION_CYCLE_END): self.wait_rider[cycle] = [] self.no_work_driver[cycle] = [] for zone_id in range(0,78): self.wait_rider[cycle].append(0) self.no_work_driver[cycle].append(0)
def __init__(self, rider_waiting_dict): self.logger = Logger('ClusteringStrategy') # self.logger.setLevel(logging.DEBUG) self.logger.info(ClusteringStrategy.timestamp, "__INIT__", None, None, "Initialize ClusteringStrategy") self.__assign_gid_dict = {} self.__rider_dict = rider_waiting_dict # Assign Group ID for zone_id in range(1, 78): self.__assign_gid_dict[zone_id] = {} for dir_id in range(-1, 12): self.__assign_gid_dict[zone_id][dir_id] = 1
def execute(self): # Current working directory for project Logger.info(f'Current directory: {os.getcwd()}') while True: # acquire and store the readings of all sensors self.acquirer.execute() # generate and publish the output. self.outputter.execute(self.acquirer.sensors) time.sleep(self.sleep_secs)
def __init__(self, sleep_secs): # make the connection to the sqlite3 db try: readings_db_path = SysWideConfig.prop_val('readings_db', 'sqlite_path') except: Logger.err(f"Failed to determine the path of the readings db. Aborting.") sys.exit() self.readings_conn = SQLiteConn(db_path=readings_db_path) self.acquirer = Acquirer(readings_conn=self.readings_conn) self.outputter = Outputter(sensors=self.acquirer.sensors, readings_conn=self.readings_conn) self.sleep_secs = sleep_secs
def __init__(self, id, pCurr): # logger in Dispatcher self.__logger = Logger('Driver') #self.__logger.setLevel(logging.DEBUG) self.__logger.info(Driver.timestamp, "__INIT__", None, None, "Create A Driver Object") self.__id = id self.__pos = pCurr self.__status = IDLE self.__riders = {} self.__trip_route = [] self.__trip_effort = 0 self.__trip_profit = 0 self.__idle_time = 0 self.__finish_trip_time = -1
class DriverStatusTracker: timestamp = -1 def __init__(self, driver_dict): self.__logger = Logger("DriverStatusTracker") self.__driver_dict = driver_dict def updateDriverStatusAfterMatching(self, driver): driver.setStatus(INSERVICE) driver.calcTripRoute() driver.calcTripEffort() driver.notifyRiderPrice() driver.calcTripProfit() def updateDriverStatusWhenInService(self, driver, rider_tracker): for elem in driver.getTripRoute().copy(): if elem.getEventTime() <= DriverStatusTracker.timestamp: #handle rider on board curr_elem = driver.popTripRoute() if curr_elem.getEvent() == DROPOFF: rider = driver.getRider(curr_elem.getRiderID()) rider_tracker.notifyRiderToFinishTrip(rider) driver.removeRider(curr_elem.getRiderID()) #handle driver del self.__driver_dict[driver.getPos()][driver.getID()] self.__driver_dict[curr_elem.getZoneID()][driver.getID()] = driver driver.setPos(curr_elem.getZoneID()) if len(driver.getTripRoute()) == 0: driver.setStatus(IDLE) driver.setFinishTripTime(DriverStatusTracker.timestamp) def updateDriverStatusWhenIdle(self, driver, no_work_dict): if driver.getStatus() == IDLE: if driver.getFinishTripTime() != DriverStatusTracker.timestamp: driver.tickIdleTime() no_work_dict[DriverStatusTracker.timestamp][driver.getPos()] += 1 else: self.__logger.error(DriverStatusTracker.timestamp, "updateDriverStatusWhenIdle", driver.getID(), None, "Driver Status is Wrong.") raise Exception("The driver status and dict not match.")
def acquire_readings(self): # acquire and record (locally) readings from this sensor no_of_regs_to_read = 1 # what does the wbu say is the time of the last reading of ? try: self.time_of_last_update = self.wbu_conn.wbu_conn_handle.read_input_registers(self.reg_last_updated, no_of_regs_to_read) except Exception as e: Logger.err(f"Unable to access Modbus {e}") status = False # record the time of latest acquisition from the wbu self.time_last_acquired = datetime.now() if self.time_of_last_update is None: # TODO: this is just strange. self.co2_reading = 99 else: self.co2_reading = self.wbu_conn.wbu_conn_handle.read_input_registers(self.reg_co2, no_of_regs_to_read) self._assess_sensor_status()
def _prep_sensors(self): # prep the sensors from the sensors config # get hold of the locations info from the global config if 'locations' in SysWideConfig.loaded_config: locations_config = SysWideConfig.loaded_config('locations') else: Logger.err( f"Failed to find the locations within the site configuration. Aborting." ) sys.exit() Logger.info(f"Creating and adding the sensors") for location, config in locations_config: # exclude inactive sensors state = config['state'] if not state: continue # TODO: add try-excepts are all of these calls as we cannot assume that the config is correct. sensor_id = config['sensor_id'] reg_temp = config['reg_temp'] reg_humidity = config['reg_humidity'] reg_co2 = config['reg_co2'] reg_last_updated = config['reg_last_updated'] # make and record the sensor sensor = Sensor(wbu_conn=self.wbu_conn, location=location, sensor_id=sensor_id, reg_temp=reg_temp, reg_humidity=reg_humidity, reg_co2=reg_co2, reg_last_updated=reg_last_updated) self.sensors.append(sensor)
class RiderStatusTracker: timestamp = -1 def __init__(self, wait_dict, serve_dict, finish_dict, cancel_dict): self.__logger = Logger("RiderStatusTracker") self.__wait_dict = wait_dict self.__serve_dict = serve_dict self.__finish_dict = finish_dict self.__cancel_dict = cancel_dict def checkRiderStatusIfTimeOut(self, rider): if RiderStatusTracker.timestamp - rider.getRequestTimeStamp( ) >= rider.getPatience(): rider.setStatus(CANCEL) self.__cancel_dict[rider.getID()] = rider zone_id = rider.getSrcZone() dir = rider.getDirID() group_id = rider.getGroupID() del self.__wait_dict[zone_id][dir][group_id][rider.getID()] if len(self.__wait_dict[zone_id][dir][group_id]) == 0: del self.__wait_dict[zone_id][dir][group_id] #cancel_dict[RiderStatusTracker.timestamp][rider.getSrcZone()] += 1 else: self.__logger.debug( RiderStatusTracker.timestamp, "updateRiderStatusWhenTimeOut", None, rider.getID(), "Cancel Time Should be: ", str(rider.getRequestTimeStamp() + rider.getPatience())) def updateRiderStatusAfterMatching(self, rider): rider.calcSat() rider.setStatus(SERVING) self.__serve_dict[rider.getID()] = rider def notifyRiderToFinishTrip(self, rider): if rider.getStatus() == SERVING: self.__finish_dict[rider.getID()] = rider rider.setStatus(FINISHED) del self.__serve_dict[rider.getID()] else: self.__logger.error(RiderStatusTracker.timestamp, "updateRiderStatusWhenInService", None, rider.getID(), "The status and dict not match.") raise Exception("The rider status and dict not match.") def updateRiderStatusWhenWait(self, rider, wait_rider_dict): if rider.getStatus() == WAITING: rider.tickWaitTime() wait_rider_dict[RiderStatusTracker.timestamp][ rider.getSrcZone()] += 1 else: self.__logger.error(RiderStatusTracker.timestamp, "updateDriverStatusWhenIdle", None, rider.getID(), "Rider Status is Wrong.") raise Exception("The rider status and dict not match.")
class RequestList: timestamp = -1 def __init__(self): self.__logger = Logger("RequestList") #self.__logger.setLevel(logging.INFO) self.__logger.info(RequestList.timestamp, "__INIT__", None, None, "Create RequestList Object.") self.__items = [] def __str__(self): ret = "[" for i in range(0, len(self.__items)): ret = ret + str(self.__items[i]) + ", " ret = ret + "]" return ret def first_element(self): if self.is_empty(): self.__logger.error(RequestList.timestamp, "__INIT__", None, None, "No First element exists.") raise Exception("No First element exists.") return self.__items[0] def remove(self): item = self.__items.pop(0) self.__logger.info(RequestList.timestamp, "remove", None, None, str(item)) return item def is_empty(self): return len(self.__items) == 0 def __len__(self): return len(self.__items) def add(self, item): self.__logger.info(RequestList.timestamp, "add", None, None, str(item)) self.__items.append(item)
class Rider: timestamp = -1 def __init__(self, uID, sT, sZ, dZ, dP, pat, srcX, srcY, destX, destY): # logger in Dispatcher self.__logger = Logger('Rider') #self.__logger.setLevel(logging.DEBUG) self.__logger.info(Rider.timestamp, "__INIT__", None, None, "Create A Rider Object") self.__id = uID self.__request_timestamp = sT self.__srcZone = sZ self.__destZone = dZ self.__default_price = dP self.__price = math.inf self.__patience = pat self.__dirID = self.__assignDirID(srcX, srcY, destX, destY) self.__shortest_time = Graph.queryTravelCost(sZ, dZ) self.__arrival_timestamp = None self.__groupID = None self.__status = WAITING self.__wait_time = 0 self.__detour_time = -1 self.__sat = 0 if self.__default_price > 100: self.__logger.warning(Rider.timestamp, "__INIT__", None, self.getID(), str(self)) def __str__(self): ret = "{" + str(self.__id) + ', ' + str(self.__request_timestamp) + ", " + str(self.__srcZone) + ", " + str(self.__destZone) + ", " + \ str(self.__default_price) + ", " + str(self.__price) + ", " + str(self.__patience) + ", " + str(self.__dirID) +", " + \ str(self.__shortest_time) + ", " + str(self.__arrival_timestamp) + ", " + str(self.__groupID) + ", " +\ str(self.__status) + ", " + str(self.__wait_time) + ", " + str(self.__detour_time) + ", " + str(self.__sat) + "}" return ret #https://stackoverflow.com/questions/13226038/calculating-angle-between-two-vectors-in-python #The range is [-180, 180) def __calcDirection(self, srcX, srcY, destX, destY): p1 = [srcX, srcY] p0 = [destX, destY] p2 = p1 + np.array([1, 0]) v0 = np.array(p0) - np.array(p1) v1 = np.array(p2) - np.array(p1) angle = np.math.atan2(np.linalg.det([v0, v1]), np.dot(v0, v1)) return np.degrees(angle)*(-1) #Tansfer from [-180,180) to [0,360). #calculate DirID by dividing the DIR_THRESHOLD def __assignDirID(self, srcX, srcY, destX, destY): dir = self.__calcDirection(srcX, srcY, destX, destY) return int((dir+180)/DIR_THRESHOLD) def setDirID(self, dir): self.__dirID = dir def getDirID(self): return self.__dirID def setGroupID(self, grpID): self.__groupID = grpID def getGroupID(self): return self.__groupID def tickWaitTime(self): self.__wait_time += 1 def getWaitTime(self): return self.__wait_time def getShortestTime(self): return self.__shortest_time def calcDetourTime(self, time): self.__detour_time = time - self.__shortest_time def getDetourTime(self): return self.__detour_time def setArrivalTimestamp(self, time): self.__arrival_timestamp = time def getArrivalTimestamp(self): return self.__arrival_timestamp #prerequest: calc detour time first def calcPrice(self, n_shared): if self.__detour_time < 0: self.__logger.error(Rider.timestamp, "calcPrice", None, self.getID(), "Detour time is unreasonable.") raise Exception("Detour time is unreasonable.") self.__price = self.__default_price * math.exp(DETOUR_WEIGH * -self.__detour_time) if n_shared == 1: self.__price = self.__price * DISCOUNT_1 elif n_shared == 2: self.__price = self.__price * DISCOUNT_2 elif n_shared == 3: self.__price = self.__price * DISCOUNT_3 elif n_shared == 4: self.__price = self.__price * DISCOUNT_4 else: self.__logger.error(Rider.timestamp, "calcPrice", None, self.getID(), "Shared number is incorret.") raise Exception("Shared number is incorret.") def getPrice(self): return self.__price def getDefaultPrice(self): return self.__default_price def calcSat(self): if self.__detour_time < 0: self.__logger.error(Rider.timestamp, "calcSat", None, self.getID(), "Detour time is unreasonable.") raise Exception("Detour time is unreasonable.") elif self.__price > self.__default_price: self.__logger.error(Rider.timestamp, "calcSat", None, self.getID(), "Price is unreasonable.") raise Exception("Price is unreasonable.") else: self.__sat = (self.__default_price-self.__price)*SAT_PRICE - math.expm1(self.__detour_time) if self.__sat > 10000000: self.__logger.warning(Rider.timestamp, "calcPrice", None, self.getID(), "SAT is too large", str(self)) def getSat(self): return self.__sat def getID(self): return self.__id def getRequestTimeStamp(self): return self.__request_timestamp def getSrcZone(self): return self.__srcZone def getDestZone(self): return self.__destZone def getPatience(self): return self.__patience def setStatus(self, status): self.__status = status def getStatus(self): return self.__status
class Simulation: def __init__(self): self.__logger = Logger('Simulation') #self.__logger.setLevel(logging.DEBUG) self.__logger.info(-1, "__INIT__", None, None, "Create Simulation Object.") self.__driver_list = RequestList() self.__rider_list = RequestList() self.__dispatcher = Dispatcher() self.__cycle = 0 self.__sim_time = [] def importData(self, ): ImportData.importDriverData(FILENAME_D, self.__driver_list) ImportData.importRiderData(FILENAME_R, self.__rider_list) def run(self): #Run simulation cycle for self.__cycle in range(SIMULATION_CYCLE_START, SIMULATION_CYCLE_END): # Synchronization the time with Modules(Driver, Dispatcher, Rider, and so on) self.__logger.info(self.__cycle, "RUN", None, None, "1. Synchronizing Time With Each Module.") #Dispatcher Module Dispatcher.timestamp = self.__cycle ClusteringStrategy.timestamp = self.__cycle MatchingStrategy.timestamp = self.__cycle DriverStatusTracker.timestamp = self.__cycle RiderStatusTracker.timestamp = self.__cycle #Driver Module Driver.timestamp = self.__cycle RoutingStrategy.timestamp = self.__cycle #Rider Module Rider.timestamp = self.__cycle #Import Module RequestList.timestamp = self.__cycle ImportDemandEvaluation.timestamp = self.__cycle # Start simulation time of this cycle print("The Cycle Number: ", self.__cycle) #print("Time: ", ImportDemandEvaluation.time) # Put the driver requests to dispatcher (The Driver List) self.__logger.info( self.__cycle, "RUN", None, None, "2. Put Drivers' Requests To Dispatcher From RequestList.") while not self.__driver_list.is_empty(): curr_driver = self.__driver_list.remove() self.__logger.debug( self.__cycle, "RUN", None, None, "Current Driver Moved into Dict of Dispatcher: ", str(curr_driver)) self.__dispatcher.handleDriverIntoDict(curr_driver) self.__dispatcher.countDriverNumberEachZone( ) #count idle driver number before match # Put the rider requests to dispatcher (The Rider List) self.__logger.info( self.__cycle, "RUN", None, None, "3. Put Rider' Requests To Dispatcher From RequestList.") while not self.__rider_list.is_empty( ) and self.__rider_list.first_element().getRequestTimeStamp( ) == self.__cycle: curr_rider = self.__rider_list.remove() self.__logger.debug( self.__cycle, "RUN", None, None, "Current Rider Moved into Dict of Dispatcher: ", str(curr_rider)) self.__dispatcher.handleRiderIntoDict(curr_rider) #Show dispatch dicts print("waiting, serving, finished, canceled: ", self.__dispatcher.countRiderNumberInWaitDict(), self.__dispatcher.countRiderNumberInServeDict(), self.__dispatcher.countRiderNumberInFinishDict(), self.__dispatcher.countRiderNumberInCancelDict()) #match driver and rider by dispatcher self.__logger.info( self.__cycle, "RUN", None, None, "4. Match Riders' Request to AN Appropriate Driver.") self.__dispatcher.matchRidertoDriver() # Update simulator's states self.__logger.info(self.__cycle, "RUN", None, None, "5. Update State of Simulator.") self.__dispatcher.updateDriverInDict() self.__dispatcher.updateRidersInWaitDict() #Show up results self.__logger.info(self.__cycle, "RUN", None, None, "6. Show Up All Results of this Cycle.") #print(self.__dispatcher.cancel_rider) #print(self.__dispatcher.no_work_driver) #if self.__cycle % SHOWN_INTERVAL == 0 and self.__cycle != SIMULATION_CYCLE_START: # self.showPerformanceMetrics() #print("\n") self.showPerformanceMetrics() print("Simulation Terminated.\n") #self.drawMonitorDict(self.__dispatcher.wait_rider, self.__dispatcher.no_work_driver) def drawMonitorDict(self, monitor_dict1, monitor_dict2): for time1, item1 in monitor_dict1.items(): for time2, item2 in monitor_dict2.items(): if time1 == time2: #plt.figure(figsize=(30, 20)) fig, (ax1, ax2) = plt.subplots(2, figsize=(30, 20)) fig.suptitle(str(time1)) ax1.plot(item1[0:78], label='Wait Rider# after match', color='r') ax1.plot(item2[0:78], label='Idle Driver# after match', color='b') ax1.set_xticks(np.arange(0, 78, step=1)) ax1.set_yticks(np.arange(0, 300, step=20)) ax1.set_ylabel("driver#") ax1.legend() ax2.plot(self.__dispatcher.idle_driver_before_match[time1], label='Idle Driver# before match', color='b') ax2.set_xticks(np.arange(0, 78, step=1)) ax2.set_yticks(np.arange(0, 300, step=20)) ax2.set_xlabel("zones") ax2.set_ylabel("driver#") ax2.legend() plt.savefig(SAVE_PATH.format(time1)) plt.close() def showPerformanceMetrics(self): print("\n") print("The Number of Riders occured so far: ", self.__dispatcher.countCurrentTotalRiderNumber()) print("The Number of Drivers: ", self.__dispatcher.countTotalDriverNumber()) print("The Number of Cycles: ", self.__cycle) print( "***************************************************************") print("Driver Performace Metrics:") print("Average Revenue: ", round(self.__dispatcher.calcAverageProfitOfDrivers(), 2)) print("Average Trip Effort: ", round(self.__dispatcher.calcAverageTripEffortOfDrivers(), 2)) print( "Average Profit: ", round( self.__dispatcher.calcAverageProfitOfDrivers() - COST_PER_CYCLE * self.__dispatcher.calcAverageTripEffortOfDrivers(), 2)) print( "Average Utilization: ", round( (260 - self.__dispatcher.calcAverageIdleTimeOfDrivers()) / 260, 2)) print( "***************************************************************") print("Rider Performace Metrics:") print("Average Waiting Time (Cycles): ", round(self.__dispatcher.calcAverageWaitTimeOfRiders(), 2)) print("Average Detour Time (Cycles): ", round(self.__dispatcher.calcAverageDetourTimeOfRiders(), 2)) print("Average Fare: ", round(self.__dispatcher.calcAverageFareOfRiders(), 2)) print("Average Default Fare: ", round(self.__dispatcher.calcAverageDefaultFareRiders(), 2)) print( "***************************************************************") print("System Performace Metrics:") print( "Serving Rate: ", round( 1 - self.__dispatcher.countRiderNumberInCancelDict() / self.__dispatcher.countCurrentTotalRiderNumber(), 2)) total = self.__dispatcher.countRiderNumberInServeDict( ) + self.__dispatcher.countRiderNumberInFinishDict() print("Pooling Rate in 4: ", round(self.__dispatcher.grp_in_4 * 4 / total, 3)) print("Pooling Rate in 3: ", round(self.__dispatcher.grp_in_3 * 3 / total, 3)) print("Pooling Rate in 2: ", round(self.__dispatcher.grp_in_2 * 2 / total, 3)) print("Pooling Rate in 1: ", round(self.__dispatcher.grp_in_1 / total, 3)) print( "***************************************************************")
def __init__(self): self.logger = Logger('MatchingStrategy')
class Dispatcher: # Sync timestamp for logging timestamp = -1 def __init__(self): #logger in Dispatcher self.__logger = Logger('Dispatcher') self.__logger.setLevel(logging.DEBUG) self.__logger.info(Dispatcher.timestamp, "__INIT__", None, None, "Create A Dispatcher Object") #Storage for drivers and riders self.__driver_dict = {} self.__rider_wait_dict = {} self.__rider_serve_dict = {} self.__rider_finish_dict = {} self.__rider_cancel_dict = {} #Performance of driver and rider self.wait_rider={} self.no_work_driver={} self.idle_driver_before_match={} self.grp_in_4=0 self.grp_in_3=0 self.grp_in_2=0 self.grp_in_1=0 #Cluser Strategy self.__cluster_strategy = ClusteringByDir(self.__rider_wait_dict) #Matching Strategy self.__match_strategy = MatchingInQueue(self.__driver_dict, self.__rider_wait_dict, self.__rider_serve_dict) #Driver Status Tracker self.__driver_tracker = DriverStatusTracker(self.__driver_dict) #Rider Status tracker self.__rider_tracker = RiderStatusTracker(self.__rider_wait_dict, self.__rider_serve_dict, self.__rider_finish_dict, self.__rider_cancel_dict) #Driver Dict for zone_id in range(1,78): self.__driver_dict[zone_id] = {} #Rider Dict for zone_id in range(1,78): self.__rider_wait_dict[zone_id] = {} for dir_id in range(-1, 12): self.__rider_wait_dict[zone_id][dir_id] = defaultdict(dict) # for cycle in range(SIMULATION_CYCLE_START, SIMULATION_CYCLE_END): self.wait_rider[cycle] = [] self.no_work_driver[cycle] = [] for zone_id in range(0,78): self.wait_rider[cycle].append(0) self.no_work_driver[cycle].append(0) def showDriverDict(self, zone_id): ret = str(zone_id) + ": {" for driver_id in OrderedDict(sorted(self.__driver_dict[zone_id].items(), key=lambda t: t[0])).keys(): ret = ret + driver_id + ", " ret = ret + "}" return ret def getDriverFromDriverDict(self, zone_id, driver_id): for id, driver in self.__driver_dict[zone_id].items(): if id == driver_id: return driver return None def getDriverNumberOfZone(self, zone_id): return len(self.__driver_dict[zone_id]) def showRiderWaitDict(self, zone_id): ret = str(zone_id) + ": {" for dir_id in self.__rider_wait_dict[zone_id].keys(): ret = ret + str(dir_id) + ": {" for group_id in self.__rider_wait_dict[zone_id][dir_id].keys(): ret = ret + str(group_id) + ": [" for rider_id in OrderedDict(sorted(self.__rider_wait_dict[zone_id][dir_id][group_id].items(), key=lambda t: t[0])).keys(): ret = ret + str(rider_id) + ", " ret = ret + "], " ret = ret + "}, " ret = ret + "}" return ret def getRiderFromWaitDict(self, zone_id, dir_id, group_id, rider_id): for id, rider in self.__rider_wait_dict[zone_id][dir_id][group_id].items(): if id == rider_id: return rider return None def getGroupFromWaitDict(self, zone_id, dir_id, group_id): for id, group in self.__rider_wait_dict[zone_id][dir_id].items(): if id == group_id: return group return None def getRequestNumberOfZone(self, zone_id): total_num = 0 for dir_id in self.__rider_wait_dict[zone_id].keys(): for group_id in self.__rider_wait_dict[zone_id][dir_id].keys(): total_num += len(self.__rider_wait_dict[zone_id][dir_id][group_id]) return total_num def showRiderServedDict(self): ret = "{" for rider_id in OrderedDict(sorted(self.__rider_serve_dict.items(), key=lambda t: t[0])).keys(): ret=ret+str(rider_id)+", " ret=ret+"}" return ret def getRiderFromServedDict(self, rider_id): for id, rider in self.__rider_serve_dict.items(): if id == rider_id: return rider return None def showRiderFinishedDict(self): ret = "{" for rider_id in OrderedDict(sorted(self.__rider_finish_dict.items(), key=lambda t: t[0])).keys(): ret = ret + str(rider_id) + ", " ret = ret + "}" return ret def getRiderFromFinishedDict(self, rider_id): for id, rider in self.__rider_finish_dict.items(): if id == rider_id: return rider return None def showRiderCanceledDict(self): ret = "{" for rider_id in OrderedDict(sorted(self.__rider_cancel_dict.items(), key=lambda t: t[0])).keys(): ret = ret + str(rider_id) + ", " ret = ret + "}" return ret def getRiderFromCanceledDict(self, rider_id): for id, rider in self.__rider_cancel_dict.items(): if id == rider_id: return rider return None #put driver into Driver Dict at start def handleDriverIntoDict(self, driver): if isinstance(driver, Driver): if driver.getID() not in self.__driver_dict[driver.getPos()].keys(): self.__driver_dict[driver.getPos()][driver.getID()] = driver else: self.__logger.error(Dispatcher.timestamp, "handleDriverRequest", driver.getID(), None, "Driver has been in the Pool.") raise Exception("Driver has been in the Pool.") else: self.__logger.error(Dispatcher.timestamp, "handleDriverRequest", None, None, "Driver's type is wrong.") raise Exception("Driver's type is wrong.") def handleRiderIntoDict(self, rider): if isinstance(rider, Rider): self.__cluster_strategy.cluster(rider) else: self.__logger.error(Dispatcher.timestamp, "handleRiderRequest", None, None, "Rider's type is wrong.") raise Exception("Rider's type is wrong.") def matchRidertoDriver(self): for zone_id in self.__rider_wait_dict.keys(): for dir_id in self.__rider_wait_dict[zone_id].keys(): for group_id in self.__rider_wait_dict[zone_id][dir_id].copy().keys(): driver = self.__match_strategy.match(zone_id) if driver is not None: self.__logger.info(Dispatcher.timestamp, "matchRidertoDriver", driver.getID(), None, "Driver be Chosen to Serve Riders.") self.__logger.debug(Dispatcher.timestamp, "matchRidertoDriver", None, None, "Driver Zone ===> Rider Zone: ", str(driver.getPos()) + "===>" + str(zone_id)) # update driver status driver.setRiders(self.__rider_wait_dict[zone_id][dir_id][group_id]) self.__driver_tracker.updateDriverStatusAfterMatching(driver) self.__logger.debug(Dispatcher.timestamp, "matchRidertoDriver", driver.getID(), None, str(driver)) #update rider status if len(self.__rider_wait_dict[zone_id][dir_id][group_id]) == 4: self.grp_in_4 += 1 elif len(self.__rider_wait_dict[zone_id][dir_id][group_id]) == 3: self.grp_in_3 += 1 elif len(self.__rider_wait_dict[zone_id][dir_id][group_id]) == 2: self.grp_in_2 += 1 elif len(self.__rider_wait_dict[zone_id][dir_id][group_id]) == 1: self.grp_in_1 += 1 else: self.__logger.warning(Dispatcher.timestamp, "calcPoolingPerformanceInWaitDict", None, None, "Grp len is 0.") for rider in self.__rider_wait_dict[zone_id][dir_id][group_id].values(): self.__rider_tracker.updateRiderStatusAfterMatching(rider) self.__logger.debug(Dispatcher.timestamp, "matchRidertoDriver", driver.getID(), rider.getID(), str(rider)) del self.__rider_wait_dict[zone_id][dir_id][group_id] else: self.__logger.info(Dispatcher.timestamp, "matchRidertoDriver", None, None, "No Driver is available.") break def updateDriverInDict(self): for zone_id in self.__driver_dict.keys(): for driver in self.__driver_dict[zone_id].copy().values(): if driver.getStatus() == IDLE: self.__logger.info(Dispatcher.timestamp, "updateDriverStatus", driver.getID(), None, "Update Driver when IDLE.") self.__driver_tracker.updateDriverStatusWhenIdle(driver, self.no_work_driver) elif driver.getStatus() == INSERVICE: self.__logger.info(Dispatcher.timestamp, "updateDriverStatus", driver.getID(), None, "Update Driver Who is INSERVICE.") self.__driver_tracker.updateDriverStatusWhenInService(driver, self.__rider_tracker) self.__logger.debug(Dispatcher.timestamp, "updateDriverStatus", driver.getID(), None, str(driver)) else: self.__logger.error(Dispatcher.timestamp, "updateDriverStatus", driver.getID(), None, "Driver Status is Wrong.") raise Exception("Driver Status is Wrong.") def updateRidersInWaitDict(self): for zone_id in self.__rider_wait_dict.keys(): for dir_id in self.__rider_wait_dict[zone_id].keys(): for group_id in self.__rider_wait_dict[zone_id][dir_id].copy().keys(): for rider in self.__rider_wait_dict[zone_id][dir_id][group_id].copy().values(): if rider.getStatus() == WAITING: self.__rider_tracker.updateRiderStatusWhenWait(rider, self.wait_rider) self.__rider_tracker.checkRiderStatusIfTimeOut(rider) def countTotalDriverNumber(self): total_len = 0 for zone_id in self.__driver_dict.keys(): total_len = total_len + len(self.__driver_dict[zone_id]) return total_len def countDriverNumberEachZone(self): self.idle_driver_before_match[Dispatcher.timestamp] = [0] for zone_id in self.__driver_dict.keys(): cnt=0 for driver in self.__driver_dict[zone_id].values(): if driver.getStatus() == IDLE: cnt+=1 self.idle_driver_before_match[Dispatcher.timestamp].append(cnt) def countRiderNumberInWaitDict(self): total_len = 0 for zone_id in self.__rider_wait_dict.keys(): for dir_id in self.__rider_wait_dict[zone_id].keys(): for group_id in self.__rider_wait_dict[zone_id][dir_id].keys(): total_len = total_len + len(self.__rider_wait_dict[zone_id][dir_id][group_id]) return total_len def countRiderNumberInServeDict(self): return len(self.__rider_serve_dict) def countRiderNumberInFinishDict(self): return len(self.__rider_finish_dict) def countRiderNumberInCancelDict(self): return len(self.__rider_cancel_dict) def countCurrentTotalRiderNumber(self): return self.countRiderNumberInWaitDict() + self.countRiderNumberInServeDict() + self.countRiderNumberInFinishDict() + self.countRiderNumberInCancelDict() def calcAverageProfitOfDrivers(self): totalProfit = 0 for zone_id in self.__driver_dict.keys(): for driver in self.__driver_dict[zone_id].values(): totalProfit += driver.getTripProfit() return totalProfit / self.countTotalDriverNumber() def calcAverageIdleTimeOfDrivers(self): totalIdleTime = 0 for zone_id in self.__driver_dict.keys(): for driver in self.__driver_dict[zone_id].values(): totalIdleTime += driver.getIdleTime() return totalIdleTime / self.countTotalDriverNumber() def calcAverageTripEffortOfDrivers(self): totalTripEffort = 0 for zone_id in self.__driver_dict.keys(): for driver in self.__driver_dict[zone_id].values(): totalTripEffort += driver.getTripEffort() return totalTripEffort / self.countTotalDriverNumber() def calcAverageWaitTimeOfRiders(self): totalWaitTime = 0 riders = {**self.__rider_serve_dict, **self.__rider_finish_dict, **self.__rider_cancel_dict} for rider in riders.values(): totalWaitTime +=rider.getWaitTime() return totalWaitTime/(self.countRiderNumberInFinishDict()+self.countRiderNumberInServeDict()+self.countRiderNumberInCancelDict()) def calcAverageDetourTimeOfRiders(self): totalDetourTime = 0 riders = {**self.__rider_serve_dict, **self.__rider_finish_dict} for rider in riders.values(): totalDetourTime += rider.getDetourTime() return totalDetourTime/(self.countRiderNumberInFinishDict()+self.countRiderNumberInServeDict()) def calcAverageFareOfRiders(self): totalFare = 0 riders = {**self.__rider_serve_dict, **self.__rider_finish_dict} for rider in riders.values(): totalFare += rider.getPrice() return totalFare/(self.countRiderNumberInFinishDict()+self.countRiderNumberInServeDict()) def calcAverageDefaultFareRiders(self): totalDefaultFare = 0 riders = {**self.__rider_serve_dict, **self.__rider_finish_dict} for rider in riders.values(): totalDefaultFare += rider.getDefaultPrice() return totalDefaultFare/(self.countRiderNumberInFinishDict()+self.countRiderNumberInServeDict()) def calcAverageSatOfRiders(self): totalSat = 0 riders = {**self.__rider_serve_dict, **self.__rider_finish_dict, **self.__rider_cancel_dict} for rider in riders.values(): totalSat += rider.getSat() return totalSat/(self.countRiderNumberInFinishDict()+self.countRiderNumberInServeDict()+self.countRiderNumberInCancelDict())
def __init__(self, riders, route): self.logger = Logger('RoutingStrategy') self.riders = riders self.route = route
def __init__(self): self.__logger = Logger("RequestList") #self.__logger.setLevel(logging.INFO) self.__logger.info(RequestList.timestamp, "__INIT__", None, None, "Create RequestList Object.") self.__items = []
class ClusteringStrategy(ABC): timestamp = -1 def __init__(self, rider_waiting_dict): self.logger = Logger('ClusteringStrategy') # self.logger.setLevel(logging.DEBUG) self.logger.info(ClusteringStrategy.timestamp, "__INIT__", None, None, "Initialize ClusteringStrategy") self.__assign_gid_dict = {} self.__rider_dict = rider_waiting_dict # Assign Group ID for zone_id in range(1, 78): self.__assign_gid_dict[zone_id] = {} for dir_id in range(-1, 12): self.__assign_gid_dict[zone_id][dir_id] = 1 def showAssignGidDict(self): ret = "{" for zone_id in self.__assign_gid_dict.keys(): ret = ret + str(zone_id) + ": {" for dir_id in self.__assign_gid_dict[zone_id].keys(): ret = ret + str(dir_id) + ": [" + str( self.__assign_gid_dict[zone_id][dir_id]) + "], " ret = ret + "}, \n" ret = ret + "}" return ret def getGroupID(self, zone_id, dir_id): return self.__assign_gid_dict[zone_id][dir_id] def tickGroupID(self, zone_id, dir_id): self.__assign_gid_dict[zone_id][dir_id] += 1 def groupRiderByDir(self, rider, group_vulumn): # Rider's zone ID and dir ID zone_id = rider.getSrcZone() dir_id = rider.getDirID() group_id = self.getGroupID(zone_id, dir_id) # self.__rider_waiting_dict[rider.getSrcZone()][rider.getDirID()] is defaultdict(dict) # group_num is the dict if rider.getID( ) not in self.__rider_dict[zone_id][dir_id][group_id].keys(): self.__rider_dict[zone_id][dir_id][group_id][rider.getID()] = rider rider.setGroupID(group_id) else: self.logger.error(ClusteringStrategy.timestamp, "groupRiderByDir", None, rider.getID(), "Rider has been in the Pool") # check how many riders in the zone&direction&group_num to determine group id rider_num = len(self.__rider_dict[zone_id][dir_id][group_id]) # When the number of rider in group up to VEHICLE_CAPACITY if rider_num == group_vulumn: self.tickGroupID(zone_id, dir_id) @abstractmethod def cluster(self, rider): pass
def sensor_status(self, value): if value in (Sensor.SENSOR_OK, Sensor.SENSOR_NOK): self._sensor_status = value else: Logger.err(f"Passed an unexpected value of sensor status: {value}. Aborting.") sys.exit()
def __init__(self, driver_dict): self.__logger = Logger("DriverStatusTracker") self.__driver_dict = driver_dict
class Driver: timestamp = -1 def __init__(self, id, pCurr): # logger in Dispatcher self.__logger = Logger('Driver') #self.__logger.setLevel(logging.DEBUG) self.__logger.info(Driver.timestamp, "__INIT__", None, None, "Create A Driver Object") self.__id = id self.__pos = pCurr self.__status = IDLE self.__riders = {} self.__trip_route = [] self.__trip_effort = 0 self.__trip_profit = 0 self.__idle_time = 0 self.__finish_trip_time = -1 def __str__(self): ret = "{" + str(self.__id) + ", " + str(self.__pos) + ", " + str( self.__status) + ", " + str(self.__trip_effort) + ", " ret = ret + str(self.__trip_profit) + ", " ret = ret + "Riders: " + self.showRidersOnBoard() + ", " ret = ret + "Route: " + self.showTripRoute() + "}" return ret def showRidersOnBoard(self): ret = "[" if len(self.__riders): for rider_id in OrderedDict( sorted(self.__riders.items(), key=lambda t: t[0])).keys(): ret = ret + rider_id + ", " ret = ret[0:len(ret) - 2] + "]" else: ret = ret + "]" return ret def showTripRoute(self): ret = "[" if len(self.__trip_route): for elem in self.__trip_route: ret = ret + str(elem.getZoneID()) + ", " ret = ret[0:len(ret) - 2] + "]" else: ret = ret + "]" return ret def getID(self): return self.__id def setRiders(self, riders): for rider_id, rider in riders.items(): self.__riders[rider_id] = rider def getRider(self, id): if id in self.__riders.keys(): return self.__riders[id] else: self.__logger.error(Driver.timestamp, "getRider", self.getID(), id, "Rider not in vehicle.") raise Exception("Rider not in vehicle.") def removeRider(self, id): if id in self.__riders.keys(): del self.__riders[id] else: self.__logger.error(Driver.timestamp, "removeRider", self.getID(), id, "Rider not in vehicle.") raise Exception("Rider not in vehicle.") def calcTripRoute(self): if len(self.__trip_route) == 0: route_strategy = RoutingInDistance(self.__riders, self.__trip_route) route_strategy.planRoute() else: self.__logger.error(Driver.timestamp, "calcTripRoute", self.getID(), None, "Trip route is empty.") raise Exception("Trip route is empty.") def popTripRoute(self): if len(self.__trip_route) > 0: return self.__trip_route.pop(0) else: self.__logger.error(Driver.timestamp, "popTripRoute", self.getID(), None, "Nothing to be poped.") raise Exception("Nothing to be poped.") def getTripRoute(self): return self.__trip_route #must calc route first def calcTripEffort(self): trip_time = 0 trip_effort = 0 pos = self.getPos() for elem in self.__trip_route: if Graph.queryTravelCost(pos, elem.getZoneID()) != 0: trip_effort = trip_effort + Graph.queryTravelCost( pos, elem.getZoneID()) else: trip_effort += 0.5 trip_time = trip_time + Graph.queryTravelCost( pos, elem.getZoneID()) elem.setEventTime(Driver.timestamp + trip_time) if elem.getEvent() == DROPOFF: rider = self.__riders[elem.getRiderID()] rider.setArrivalTimestamp(Driver.timestamp + trip_time) rider.calcDetourTime( trip_time ) #detour time is b/w the rerquest accepted and arrive at destination. pos = elem.getZoneID() if trip_effort < 0: self.__logger.warning(Driver.timestamp, "calcTripEffort", self.getID(), None, "Trip effort value is unresonable ") raise Exception("Trip effort value is unresonable ") else: self.__trip_effort += trip_effort def tickTripEffort(self): self.__trip_effort += 1 def getTripEffort(self): return self.__trip_effort def notifyRiderPrice(self): shared_number = len(self.__riders) for rider in self.__riders.values(): rider.calcPrice(shared_number) #must calc route effort and rider price first def calcTripProfit(self): trip_revenue = 0 if len(self.__riders) > 0: for rider in self.__riders.values(): if rider.getPrice() is not math.inf: trip_revenue += rider.getPrice() else: self.__logger.error(Driver.timestamp, "calcTripEffort", self.getID(), None, "Price value is unresonable ") raise Exception("Price value is unresonable ") self.__trip_profit += trip_revenue else: self.__logger.error(Driver.timestamp, "calcTripEffort", self.getID(), None, "No riders in vehicle.") raise Exception("No riders in vehicle.") def getTripProfit(self): return self.__trip_profit def setPos(self, zid): self.__pos = zid def getPos(self): return self.__pos def setStatus(self, status): self.__status = status def getStatus(self): return self.__status def tickIdleTime(self): self.__idle_time += 1 def getIdleTime(self): return self.__idle_time def setFinishTripTime(self, time): self.__finish_trip_time = time def getFinishTripTime(self): return self.__finish_trip_time