def func_dijkstraPP(mymap, mu, edge_index): edge_start = np.where(mymap.M[:, edge_index] == 1)[0].item() edge_end = np.where(mymap.M[:, edge_index] == -1)[0].item() path_1 = func.dijkstra(mymap.G, mymap.r_0, edge_start, mu)[2] path_2 = func.dijkstra(mymap.G, edge_end, mymap.r_s, mu)[2] path_dijkstraPP = (path_1 + path_2).reshape(-1) path_dijkstraPP[edge_index] = 1 return path_dijkstraPP
def func_max_flow(mymap, x_t, thres=0.01): path_element_set = [] mu_prime = mymap.mu.copy() while np.max( x_t ) > thres: # if there is remaining x_rsp_quadprog left, continue; print("rsp", np.sum(x_t)) # dynamic_x_rsp_quadprog = x_rsp_quadprog.copy() mask = x_t <= thres x_t[mask] = 0 mu_prime[mask] = 100000 _, path, path_onehot = func.dijkstra(mymap.G, mymap.r_0, mymap.r_s, mu_prime) if np.min(x_t[path]) == 0: break x_t[path] -= np.min(x_t[path]) path_element_set.append(path_onehot.reshape(-1)) # dynamic_x_rsp_quadprog[mask] = 100 # edge_value = np.min(dynamic_x_rsp_quadprog) # edge_index = np.argmin(dynamic_x_rsp_quadprog) # find the edge list with the smallest value of x_rsp_quadprog # path_dijkstraPP = func_dijkstraPP(mymap, dynamic_mu, edge_index) # 找到最短路径 # path_element_set.append(path_dijkstraPP) # x_rsp_quadprog -= edge_value * path_dijkstraPP # update x_rsp_quadprog # mask = x_rsp_quadprog < 0.01 # x_rsp_quadprog[mask] = 0 return path_element_set
def biGP4(mymap, T, N, S): print('current node: {}'.format(mymap.r_0 + 1)) value_max = 0 map_temp = Map(mymap.model, mymap.decom) for _, next_node, d in mymap.G.out_edges(mymap.r_0, data=True): if func.dijkstra(mymap.G, next_node, mymap.r_s)[0] == -1: continue link = d['index'] print('current link: {}'.format(link + 1)) if next_node == mymap.r_s: value1 = norm.cdf(T, mymap.mu[link].item(), np.sqrt(mymap.cov[link, link])) value2 = norm.cdf(T, mymap.mu2[link].item(), np.sqrt(mymap.cov2[link, link])) value = func.calc_bi_gauss(mymap.phi_bi, value1, value2) if value >= value_max: value_max = value selected_link = link else: v_hat = 0 G_temp = func.remove_graph_edge(mymap.G, link) mu1_sub, cov1_sub, cov1_con = func.update_param( mymap.mu, mymap.cov, link) mu2_sub, cov2_sub, cov2_con = func.update_param( mymap.mu2, mymap.cov2, link) for i in range(N): sample = func.generate_biGP_samples(mymap.phi_bi, mu1_sub[2], mu2_sub[2], cov1_sub[22], cov2_sub[22], 1).item() T_temp = T - sample if T_temp > 0: mu1_con = func.update_mu(mu1_sub, cov1_sub, sample) mu2_con = func.update_mu(mu2_sub, cov2_sub, sample) map_temp.make_map_with_G(mu=mu1_con, cov=cov1_con, OD_true=[next_node, mymap.r_s], G=G_temp, mu2=mu2_con, cov2=cov2_con, phi_bi=mymap.phi_bi) v_hat += PLM(mymap=map_temp, T=T_temp, S=S, model="bi")[0] value = v_hat / N if value >= value_max: value_max = value selected_link = link return selected_link, value_max
def logGP4(mymap, T, N, S): print('current node: {}'.format(mymap.r_0 + 1)) value_max = 0 map_temp = Map(mymap.model, mymap.decom) for _, next_node, d in mymap.G.out_edges(mymap.r_0, data=True): if func.dijkstra(mymap.G, next_node, mymap.r_s)[0] == -1: continue link = d['index'] print('current link: {}'.format(link + 1)) if next_node == mymap.r_s: value = norm.cdf(np.log(T), mymap.mu[link].item(), np.sqrt(mymap.cov[link, link])) if value >= value_max: value_max = value selected_link = link else: v_hat = 0 G_temp = func.remove_graph_edge(mymap.G, link) mu_sub, cov_sub, cov_con = func.update_param( mymap.mu, mymap.cov, link) for i in range(N): sample = np.random.normal(mu_sub[2], np.sqrt(cov_sub[22])) T_temp = T - np.exp(sample) if T_temp > 0: mu_con = func.update_mu(mu_sub, cov_sub, sample) map_temp.make_map_with_G( mu=mu_con, cov=cov_con, OD_true=[next_node, mymap.r_s], G=G_temp, ) v_hat += PLM(mymap=map_temp, T=T_temp, S=S)[0] value = v_hat / N if value >= value_max: value_max = value selected_link = link return selected_link, value_max
def GP3(mymap, zeta, gap): ## calculate t_min and t_max (lower bound and upper bound) # step 1: calculate the LET path: x_let; x_let = func.dijkstra(mymap.G, mymap.r_0, mymap.r_s)[2] # step 2: calculate the smallest variance path: x_var, and the variance # value (var_min) x_var = func_simplepathleastvar(mymap, x_let)[1] # step 3: calculate t_min and t_max t_min = np.dot( mymap.mu.T, x_let) + zeta * np.sqrt(x_var.T.dot( mymap.cov).dot(x_var)) # t_min is the sum of the two min values t_max = np.dot(mymap.mu.T, x_let) + zeta * np.sqrt( x_let.T.dot(mymap.cov).dot(x_let) ) # t_max is one of the feasible path's value which the LET path gap_GP3 = abs(t_max - t_min) / t_max ## initialize t=(t_min+t_max)/2, and calculate matrix H, lambda_min and convert to Q and l; ## initialize x_rsp as x_let H = zeta**2 * mymap.cov - np.dot(mymap.mu, mymap.mu.T) lmd = np.linalg.eig(H)[0] lmd_min = np.min(lmd) Q = H - (lmd_min - 1) * np.eye(mymap.n_link) #l = 2 * t * mymap.mu + (lmd_min-1) * np.ones((mymap.n_link, 1)) %no need to initialize l #here, because we will re-initialize l in the while loop path_rsp_GP3 = x_let iter_GP3 = 1 ## loop and update t until convergence. if no feasible path, set t_min = t; if feasible path, set t_max = t; while gap_GP3 > gap: print("gp3", gap_GP3) t = (t_min + t_max) / 2 # update l, l = 2 * t * mymap.mu + (lmd_min - 1) * np.ones((mymap.n_link, 1)) # find the optimal path for the constrained quadratic program x_rsp_propose = func_rsp_path(mymap, Q, l, t, path_rsp_GP3)[1] rsp_min = np.dot(mymap.mu.T, x_rsp_propose) + zeta * np.sqrt( x_rsp_propose.T.dot(mymap.cov).dot(x_rsp_propose)) if rsp_min < t_max: t_max = rsp_min path_rsp_GP3 = x_rsp_propose if rsp_min < t_min: t_min = rsp_min elif rsp_min < t: t_max = rsp_min path_rsp_GP3 = x_rsp_propose else: t_min = t gap_GP3 = abs(t_max - t_min) / t_max iter_GP3 += 1 return path_rsp_GP3, iter_GP3, gap_GP3.item()
def main(): stations = get_stations('wiki.txt', 9, 'mck.txt', 8) table = create_table(stations) br_names = { '1': 'Сокольническая (красная)', '2': 'Замоскворецкая (зеленая)', '3': 'Арбатско-Покровская (синяя)', '4': 'Филёвская (голубая)', '5': 'Кольцевая (коричневая)', '6': 'Калужско-Рижская (оранжевая)', '7': 'Таганско-Краснопресненская (фиолетовая)', '8': 'Калининская (желтая)', '9': 'Серпуховско-Тимирязевская (серая)', '10': 'Люблинско-Дмитровская (салатовая)', '11А': 'Каховская (бирюзовая)', '12': 'Бутовская (серо-голубая)', '14': 'МЦК', '15': 'Некрасовская (розовая)', } br_colors = { '1': '\"#CD0506\"', '2': '\"#0A6F20\"', '3': '\"#072889\"', '4': '\"#069CD3\"', '5': '\"#7F0000\"', '6': '\"#FF7F00\"', '7': '\"#92007B\"', '8': '\"#FFDD03\"', '9': '\"#A2A5B4\"', '10': '\"#8CCE3A\"', '11А': '\"#C9EBE9\"', '12': '\"#B2DAE7\"', '14': '\"#F76093\"', '15': '\"#D765A3\"', } write_gv('metro_graph.gv', table, stations, br_colors) render('dot', 'png', 'metro_graph.gv') while True: while True: options = [] st_1_name = input('Станция отправления: ') for st in stations: if st.name.lower() == st_1_name.lower(): options.append(st) if len(options) == 0: print('Станция с таким названием не найдена.') elif len(options) == 1: st_1 = options[0] break else: print('Есть несколько станций с таким названием: ') for i in range(len(options)): print( str(i + 1) + '. ' + options[i].name + ' - ' + br_names[options[i].branch]) while True: ch = input('Выберите номер нужной станции: ') try: ch = int(ch) if 1 <= ch <= len(options): st_1 = options[ch - 1] break else: print('Неверный выбор, пожалуйста повторите ввод.') except ValueError: print('Неверный выбор, пожалуйста повторите ввод.') break print() while True: options = [] st_1_name = input('Станция прибытия: ') for st in stations: if st.name.lower() == st_1_name.lower(): options.append(st) if len(options) == 0: print('Станция с таким названием не найдена.') elif len(options) == 1: if options[0] == st_1: print( 'Станция совпадает со станцией отправления. Выберите другую.' ) else: st_2 = options[0] break else: print('Есть несколько станций с таким названием: ') for i in range(len(options)): print( str(i + 1) + '. ' + options[i].name + ' - ' + br_names[options[i].branch]) while True: ch = input('Выберите номер нужной станции: ') try: ch = int(ch) if 1 <= ch <= len(options): if options[ch - 1] == st_1: print( 'Станция совпадает со станцией отправления. Выберите другую.' ) else: st_2 = options[ch - 1] break else: print('Неверный выбор, пожалуйста повторите ввод.') except ValueError: print('Неверный выбор, пожалуйста повторите ввод.') break print() distance, paths = dijkstra(table, stations.index(st_1)) print_path(st_1, st_2, distance, paths, stations, table) print()
def zeng2015(mymap, zeta, MaxIter, gap): ## extract information a map, and perform cholesky decomposition over Sigma L_low_triangular = np.linalg.cholesky( mymap.sigma) # cholesky decomposition; get the lower triangular matrix ## initialization, calculate lowerbound and upperbound of the problem lmd = np.random.rand( mymap.n_link, 1) #randomly generate the initial values for lamda,v (0,1) nu = np.random.rand() iter_LR = 1 # initialize iteration number x_let = func.dijkstra(mymap.G, mymap.r_0, mymap.r_s)[2] y_pri = np.dot( np.dot(L_low_triangular.T, x_let).T, np.dot(L_low_triangular.T, x_let)) #the travel time variance of the shortest path # y' is the travel time variance of the shortest distance path upperbound = np.dot(mymap.mu.T, x_let) + zeta * np.sqrt( x_let.T.dot(mymap.sigma).dot(x_let)) #calculate UB using Eq.40 lowerbound = -100 gap_LR = (upperbound - lowerbound) / upperbound L_high_triangular = L_low_triangular.T ## step2 slove the decomposed dual problems while iter_LR < MaxIter and abs(gap_LR) > gap: ## solve a transformed shortest path problem lmd_L = np.dot(lmd.T, L_high_triangular).reshape(-1) nan_position = np.isnan(lmd_L) for i in range(mymap.n_link): if nan_position[i] == 1: lmd_L[i] = 0 lmd[i] = 0 for i in range(mymap.n_link): if lmd_L[i] < 0: lmd_L[i] = -lmd_L[i] dynamic_mu = mymap.mu + lmd_L.reshape(-1, 1) path_rsp_LR = func.dijkstra(mymap.G, mymap.r_0, mymap.r_s, dynamic_mu)[2] ## calculate Lx,Ly,Lw Lx = np.dot(dynamic_mu.T, path_rsp_LR) omega = lmd / ( 2 * nu) # calculate omega ,the second subfunction using Eq.36 Lw = 0 for i in range(mymap.n_link): Lw = Lw + nu * omega[i]**2 - lmd[i] * omega[i] y = np.dot( np.dot(L_low_triangular.T, path_rsp_LR).T, np.dot(L_low_triangular.T, path_rsp_LR)) Ly = 0 # caculate Ly using Eq.34 with Min{0,zeta*sqrt(y')-nu*y'} ## updata LB,UB,and epsilon using Eqs.39-41 lowbound_optimal = Lx upperbound_optimal = np.dot(mymap.mu.T, path_rsp_LR) + zeta * np.sqrt( path_rsp_LR.T.dot(mymap.sigma).dot(path_rsp_LR)) lowerbound = lowbound_optimal upperbound = upperbound_optimal gap_LR = (upperbound - lowerbound) / upperbound ## step 3 update the Lagrangian multipliers (lambda,nu) delta = 0.9 #delta is a scalar chosen between 0 and 2 L_x_let_dynamic = np.dot(L_low_triangular.T, path_rsp_LR) theta_numerator = np.zeros(mymap.n_link) theta_denominator = np.zeros(mymap.n_link) theta = np.zeros(mymap.n_link) for i in range(mymap.n_link): theta_numerator[i] = delta * (upperbound - lowerbound) theta_denominator[i] = 0 for z in range(mymap.n_link): theta_denominator[i] = theta_denominator[i] + ( L_x_let_dynamic[z] - omega[i])**2 theta[i] = theta_numerator[i] / theta_denominator[i] # using heuristic algorithm calculate the step size of each iteration k value_omega = np.dot(omega.T, omega) theta_nu = delta * (upperbound - lowerbound) / ((value_omega - y)**2) nu = nu + theta_nu * value_omega # updata nu value_L_x_let = np.dot(L_low_triangular.T, path_rsp_LR) for i in range(mymap.n_link): lmd[i] = lmd[i] + theta[i] * (value_L_x_let[i] - omega[i] ) #updata lambda iter_LR += 1 return path_rsp_LR, iter_LR, gap_LR
def zhang2019(mymap, zeta, MaxIter, gap): #SG #relative duality gap threshold epsilon, MaxIter is maximum number of iteration ## step 1,variance-covariance maxtrix decomposition eig_value, eig_vector = np.linalg.eig(mymap.cov) ## step2 initialization iter_SG = 0 lower_bound_Z = -1000 lmd = np.ones(mymap.n_link).reshape(-1, 1) x_let = func.dijkstra(mymap.G, mymap.r_0, mymap.r_s)[2] upper_bound_Z = np.dot(mymap.mu.T, x_let) + zeta * np.sqrt( x_let.T.dot(mymap.cov).dot(x_let)) #compute Z as the upper bound gap_SG = (upper_bound_Z - lower_bound_Z) / upper_bound_Z ## step 3 solve lagtangian telaxation problems while iter_SG < MaxIter and gap_SG > gap: dynamic_mu = mymap.mu + np.dot(eig_vector, lmd) dynamic_mu = np.abs(dynamic_mu) x_let = func.dijkstra(mymap.G, mymap.r_0, mymap.r_s, dynamic_mu)[2] optimal_upper_bound_Z = np.dot(mymap.mu.T, x_let) + zeta * np.sqrt( x_let.T.dot(mymap.cov).dot(x_let)) #update upper bound of Z lagrangian_optimal = np.dot((mymap.mu + np.dot(eig_vector, lmd)).T, x_let) ## update upper_bound_Z and save x_let if upper_bound_Z >= optimal_upper_bound_Z: upper_bound_Z = optimal_upper_bound_Z x_SG = x_let x_SG_last = x_SG else: if iter_SG == 0: x_SG = x_let x_SG_last = x_SG else: x_SG = x_SG_last lagrangian_value = lagrangian_optimal ## update low_bound_Z if lagrangian_value >= lower_bound_Z: lower_bound_Z = lagrangian_value # update lagrangian multiplier partial_coefficient = np.dot(eig_vector.T, x_let) coefficient = np.abs(upper_bound_Z - lower_bound_Z) / np.dot( partial_coefficient.T, partial_coefficient) beta = 0.1 lmd_new = lmd + beta * coefficient * partial_coefficient for i in range(mymap.n_link): if lmd_new[i] > np.abs(zeta * np.sqrt(eig_value[i])): lmd_new[i] = lmd[i] lmd = lmd_new iter_SG += 1 gap_SG = (upper_bound_Z - lower_bound_Z) / upper_bound_Z return x_SG, iter_SG, gap_SG.item()