def gen_initial_solution(data_points, offices, customers, n_offices): tot_iteration = 100 [cluster_label, new_centroids] = k_means(data_points, n_offices, tot_iteration) new_solution = list() clusters = list() for i in range(len(new_centroids)): clusters.append(list()) for label in cluster_label: clusters[label[0]].append(label) office = None for cluster in clusters: customers_id = list() for elem in cluster: cust = NodeUtils.closest_node( Node(None, elem[1][0], elem[1][1], None), customers) customers_id.append(cust.index) office = NodeUtils.closest_node( Node(None, elem[2][0], elem[2][1], None), offices) office_sol = InitialSolution() office_sol.office = office office_sol.customers_id = customers_id new_solution.append(office_sol) return new_solution
def path_to_charging(sourcedId): min = -1 targetId = -1 chargings = DataOperate.get_chargings() for charging in chargings: dist = NodeUtils.get_dist(sourcedId, charging) if min == -1 or min < dist: min = dist targetId = charging return NodeUtils.get_path(sourcedId, targetId), min
def get_first_path(Gj, request_Ls, request_Ld): first_path = [] # 1.获取Gj到request_Ls的路径规划 pathj_Ls = NodeUtils.get_path(Gj, request_Ls) # 2.获取request_Ls到request_Ld的路径规划 pathLs_Ld = NodeUtils.get_path(request_Ls, request_Ld) first_path.extend(pathj_Ls) if first_path: first_path.extend(pathLs_Ld[1:]) else: first_path.extend(pathLs_Ld) return first_path
def others_to_cur_dist_sort(size=1426): print('开始计算其他节点到本节点的距离的排序,共有%s个节点' % size) for cur in range(size): print('开始计算其他节点到第%s个节点的距离的排序' % cur) others_to_cur_dists = [] for other in range(size): dist = NodeUtils.get_dist(other, cur) others_to_cur_dists.append(dist) new_others_to_cur_dists = sorted(others_to_cur_dists) res = [] exist = np.zeros(1426, dtype='int16') for others_to_cur_dist in new_others_to_cur_dists: index = others_to_cur_dists.index(others_to_cur_dist) while exist[index] == 1: index = others_to_cur_dists.index(others_to_cur_dist, index + 1) exist[index] = 1 res.append(index) print('开始写入第%s个节点的距离的排序' % cur) # print('res = %s' %res[:20]) #将res写入到文件中 with open('sortdistances/sortdistance' + str(cur) + '.txt', 'w') as f: f.write(str(res) + '\n')
def optimal_solution(car_end, request): # print('开始寻找最优解') max_detour_dist = None car_best = None min_dist_Gj_Ls = None for car_e in car_end: car = car_e[0] #判断车辆状态信息是否已经改变了 if is_carstate_change(car, DataOperate.get_car(car.id)): continue Gj = car_e[1] arrive_Gj_datetime = car_e[2] situation = car_e[3] # 1.算出从Gj节点到请求出发地request.Ls节点的距离distj_Ls distj_Ls = NodeUtils.get_dist(Gj, request.Ls) # 2.判断是否是第一批乘客,是的话没有拼车这一说,如果可以拼车的话,优先拼车 if situation == 0: if max_detour_dist == None and (min_dist_Gj_Ls == None or min_dist_Gj_Ls > distj_Ls): min_dist_Gj_Ls = distj_Ls car_best = [car, Gj, arrive_Gj_datetime, 0, distj_Ls + NodeUtils.get_dist(request.Ls, request.Ld)] continue # TODO 考虑是否还需要 1.获取每辆车从Gj节点到它当前目的地car.Ld节点的距离distj_Ld # distj_Ld = NodeUtils.get_dist(Gj, car[4]) # 3.分别算出从request.Ls节点到request.Ld节点的距离distLs_Ld1和car.Ld节点的距离distLs_Ld2 distLs_Ld1 = NodeUtils.get_dist(request.Ls, request.Ld) distLs_Ld2 = NodeUtils.get_dist(request.Ls, car.Ld) # 4.算出request.Ls节点到request.Ld(car.Ld)节点再到car.Ld(request.Ld)节点的距离distLs_Ld # distLs_Ld = None if situation == 1: # 4.1 先送拼车乘客去目的地 distLs_Ld = get_sharedist(request.Ls, request.Ld, car.Ld) else: # 4.2先送原始乘客去目的地 distLs_Ld = get_sharedist(request.Ls, car.Ld, request.Ld) # 5.算出绕路的距离 detour_dist = (distLs_Ld1 + distLs_Ld2) - distLs_Ld + distj_Ls detour_dist = (distLs_Ld1 + distLs_Ld2) - distLs_Ld + distj_Ls detour_dist = (distLs_Ld1 + distLs_Ld2) - distLs_Ld - distj_Ls # 6.找到最小的绕路距离车辆 if max_detour_dist == None or max_detour_dist > detour_dist: max_detour_dist = detour_dist car_best = [car, Gj, arrive_Gj_datetime, situation, distj_Ls + distLs_Ld] # print('car_best = %s' % car_best) return car_best
def origin_match(request): # print('开始进行出发地匹配') #结果集 car_start = [] #标记一辆车是否已经访问过 vis = np.zeros(1200, dtype="int16") #1.获取请求的出发地和目的地 request_Ls = request.Ls can_endure_datetime = str(DatetimeUtils.datetime_add(request.Tp, 10)) # 2.获取距离request.Ls节点由近到远的节点list结合 sort_node = DataOperate.get_sort_node(request_Ls) # 3.对于其中的每个可达节点,选出能在用户要求时间内接到用户的车辆: for i in sort_node: # 节点i到节点Ls的最短距离 单位:m dist = NodeUtils.get_dist(i, request_Ls) #判断i节点是否能到达request.Ls节点,即用户的出发节点, and 两个节点的距离小于等于 5000m if dist > 5000: break #拿到i节点的车辆状态表[[车辆编号, 预计到达该节点时间,该节点是否为目的地(0:否,1:是)], ...] carstate = DataOperate.get_carstate(i) for state in carstate: carid = state[0] arrive_datetime = state[1] # is_target = state[2] #不同节点间肯定有重复的车辆信息,如果一辆车在G1节点不能到当前节点,那么在G2节点也不能到达 if vis[carid] == 1: continue #标记车辆为已访问 vis[carid] = 1 #获取车辆信息 car = DataOperate.get_car(carid) #判断车辆是否正在充电 if car.is_recharge == 1: continue # 车辆从节点i到节点Ls所需行驶时间 假设速度恒定为:60km/h -> 1000m/min ti_Ls = dist / 1000 #车辆到达request.Ls节点的时间 arrive_Ls_datetime = str(DatetimeUtils.datetime_add(arrive_datetime, ti_Ls)) #如果车辆当前的乘客批数为0,即没有乘客的话,那么只需判断能否按时到达请求出发地,不需要进行其他的判断了 if car.batch_numbers == 0: # 判断能否在规定时间到达request.Ls节点 if arrive_Ls_datetime <= can_endure_datetime: car_start.append([car, i, DatetimeUtils.cur_datetime()]) continue #如果车辆已有两批乘客在拼车,则不考虑 if car.batch_numbers > 1: continue #如果车辆的座位数不能满足乘客的要求 if car.Pc + request.Pr > 3: continue #判断车辆carid到i节点的时间 + 车辆从节点i到节点Ls所需的行驶时间 <= 用户请求的出发时间Tp + 用户可以容忍的等待时间Ts(定值 10min) if arrive_Ls_datetime <= can_endure_datetime: car_start.append([car, i, arrive_datetime]) # print('car_start = %s' % car_start) return car_start
def evaluate_sol(offices_id, offices, customers): tot_dist = 0 tot_reward = 0 offices_sol = list() for index in offices_id: offices_sol.append(offices[index]) built_offices = list() for customer in customers: office = NodeUtils.closest_node(customer, offices_sol) tot_dist += NodeUtils.euclidean_dist(office, customer) + offices[index].value tot_reward += customer.value if office not in built_offices: built_offices.append(office) return tot_reward - int(tot_dist), len(built_offices)
def get_rand_neighbor(sol, offices, area=10): swap_id = r.randrange(len(sol)) new_x = offices[swap_id].x + r.uniform(-area, area) new_y = offices[swap_id].y + r.uniform(-area, area) new_office = NodeUtils.closest_node(Node(None, new_x, new_y, None), offices) sol[swap_id] = new_office.index return sol
def get_share_path(Gj, request_Ls, Ld1, Ld2): share_path = [] #1.获取从Gj到request_Ls的路径pathj_Ls pathj_Ls = NodeUtils.get_path(Gj, request_Ls) #2.获取从request_Ls到Ld1的路径pathLs_Ld1 pathLs_Ld1 = NodeUtils.get_path(request_Ls, Ld1) #3.获取从Ld1到Ld2的路径pathLs_Ld2 pathLs_Ld2 = NodeUtils.get_path(Ld1, Ld2) #4.合并三个路径 share_path.extend(pathj_Ls) if share_path: share_path.extend(pathLs_Ld1[1:]) else: share_path.extend(pathLs_Ld1) if share_path: share_path.extend(pathLs_Ld2[1:]) else: share_path.extend(pathLs_Ld2) return share_path
def after_match(car_best, request): # print('匹配成功后相关处理') car = car_best[0] #判断车辆状态信息是否已经改变了 if is_carstate_change(car, DataOperate.get_car(car.id)): return False Gj = car_best[1] arrive_Gj_datetime = car_best[2] situation = car_best[3] distGj_Ld1_Ld2 = car_best[4] #1.修改乘客批数 car.batch_numbers += 1 car.Pc += request.Pr #移除Gj节点到car.Ld节点路径上的节点的车辆状态表 if situation != 0: # 拿到车辆从Gj节点到car.Ld节点的路径,修改路径上节点的车辆状态表 pathj_Ld = NodeUtils.get_path(Gj, car.Ld) NodeUtils.remove_carstate(pathj_Ld, car.id) #拿到Gj节点->request.Ls节点->request.Ld节点的路径 if situation == 0: share_path = get_first_path(Gj, request.Ls, request.Ld) car.Ld = request.Ld # 拿到车辆从Gj到request.Ls再到request.Ld(car.Ld)再到car.Ld(request.Ld)节点的路径规划,修改路径上节点的车辆状态表,修改车辆的当前目的地 elif situation == 1: share_path = get_share_path(Gj, request.Ls, request.Ld, car.Ld) elif situation == 2: share_path = get_share_path(Gj, request.Ls, car.Ld, request.Ld) #修改车辆目的地 car.Ld = request.Ld #在新的路径上的节点的车辆状态表上加上一行新的行车记录 NodeUtils.add_carstate(share_path, car.id, Gj, arrive_Gj_datetime) #获取车辆出发地car.Ls到Gj节点的距离distLs_Gj distLs_Gj = NodeUtils.get_dist(car.Ls, Gj) #算出car.Ls -> 新的目的地的距离 distLs_Ld distLs_Ld = distLs_Gj + distGj_Ld1_Ld2 #计算到达目的地的时间 arrive_target_datetime = str(DatetimeUtils.datetime_add(arrive_Gj_datetime, distGj_Ld1_Ld2 / 1000)) # 更新车辆信息,特别是batch_numbers DataOperate.update_car(car) #更新请求为已匹配成功 request.is_match_successful = 1 DataOperate.update_request(request) #提交定时任务,在车辆到达新目的地的时候执行 ApschedulerClient.arrival_job(arrive_target_datetime, car.id, distLs_Ld) return True
def fastest_charging_datetime(sourcedId, soc): #获取充电站所有的节点位置id,为list类型 chargings = DataOperate.get_chargings() # print('chargings = ', chargings) ''' 获取每个充电站的状态信息 chargings_state_donedatetime:每个充电站什么时间完成对当前充电站最后一辆车的充电 ''' chargings_state_donedatetime = DataOperate.get_chargings_state() # print('chargings_state_donedatetime = ', chargings_state_donedatetime) # print('typeof chargings_state_donedatetime is ', type(chargings_state_donedatetime)) fastest_charging_datetime = None target_index = -1 i = 0 for charging in chargings: #获取起始地到充电站的距离 dist = NodeUtils.get_dist(sourcedId, charging) #判断是否能够到达充电站 if not enough_battery_to_target(dist, soc): continue # print('charging = ', charging) # print('chargings_state_donedatetime[%s] is %s' % (i, chargings_state_donedatetime[i])) # print('typeof chargings_state_donedatetime[%s] is %s' % (i, type(chargings_state_donedatetime[i]))) #计算出 若到该充电站充电的话,完成充电的时间 cd = charging_datetime(dist, soc, chargings_state_donedatetime[i]) # print('cd = ', cd) # print('type of cd is', cd) #如果最少时间为None或者比cd大的话,更新最小时间 if fastest_charging_datetime == None or fastest_charging_datetime > cd: fastest_charging_datetime = cd target_index = i i += 1 #修改充电站状态信息 chargings_state_donedatetime[target_index] = fastest_charging_datetime DataOperate.update_chargings_state(chargings_state_donedatetime) return fastest_charging_datetime,chargings[target_index]
import datetime as dt import DataOperate import NodeUtils def test(): test = 1 print(test) if __name__ == "__main__": pass for sour in range(1426): for targ in range(1426): path = NodeUtils.get_path(sour, targ) dist = NodeUtils.get_dist(sour, targ) cur_dist = 0 pre = path[0] for Gc in path[1:]: cur_dist += NodeUtils.get_dist(pre, Gc) pre = Gc # print(path) # print(dist) # print(cur_dist) if (cur_dist != dist): print('%s -> %s' % (sour, targ)) #测试cars修改是否起作用
def target_match(request, car_start): # print('开始进行目的地匹配') #结果集 car_end = [] for car_s in car_start: car = car_s[0] #判断车辆状态信息是否已经改变了 if is_carstate_change(car, DataOperate.get_car(car.id)): continue Gj = car_s[1] arrive_Gj_datetime = car_s[2] #如果为空车状态,不用进行目的地匹配 if car.batch_numbers == 0: car_end.append([car, Gj, arrive_Gj_datetime, 0]) continue ''' 在进行匹配时,有以下两种情况下可以认为匹配是成功的: 1.拼车乘客所要去的目的地离车辆当前行驶路径上的某一点距离不远 2.车辆当前的目的地离拼车乘客所要行驶的路径上的某一点不远 分别对应了: 1.车辆先将拼车乘客送达目的地,再将原始乘客送达目的地 2.车辆先将原始乘客送达目的地,再将拼车乘客送达目的地 ''' ''' 对于第一种情况,遍历Rc路径上的所有节点Gc,检查Gc节点到request.Ld节点的所需时间tc_Ld * 2 <= 10 ''' min = None situation = None # 获取请求的起点request.Ls到车辆当前的目的地car.Ld的路径Rc = [request.Ls, ..., car.Ld] Rc = NodeUtils.get_path(request.Ls, car.Ld) for Gc in Rc: #判断min是否小于等于300m,若是,直接退出循环 if min != None and min <= 300: break #Rc路径上每个节点Gc到请求的目的地request.Ld的距离 dist = NodeUtils.get_dist(Gc, request.Ld) #考虑用户可忍受的时间为10min,那么这个距离最远不能超过5000m if dist >= 0 and dist <= 5000: if min == None or dist < min: min = dist situation = 1 ''' 对于第二种情况,对于请求的起始位置request.Ls,和目的地request.Ld的路径规划Rp<Ls,...,Ld>,遍历Rp路径上的所有节点Gc, 检查节点Gc到车辆当前目的地Ci.Ld节点所需的时间tc_carLd * 2 <= 10 ''' Rp = NodeUtils.get_path(request.Ls, request.Ld) for Gc in Rp: # 判断min是否小于等于300m,若是,直接退出循环 if min != None and min <= 300: break # Rp路径上每个节点Gc到车辆当前的目的地car.Ld的距离 dist = NodeUtils.get_dist(Gc, car.Ld) if dist >= 0 and dist <= 5000: if min == None or dist < min: min = dist # Gi = Gc situation = 2 if min != None: #[[车辆对象,在Gj节点去接拼车乘客,到达Gj节点的时间,先送原始乘客或先送拼车乘客(1:先送拼车乘客,2:先送原始乘客)], ...] car_end.append([car, Gj, arrive_Gj_datetime, situation]) # print('car_end = %s' % car_end) return car_end
def get_sharedist(request_Ls, Ld1, Ld2): return NodeUtils.get_dist(request_Ls, Ld1) + NodeUtils.get_dist(Ld1, Ld2)