重要代码
"""主要变量说明:_C : 道路设计承载量_D : 道路长度_OD : O/D矩阵_DEG: 结点度数列表_B : 结点介数列表_Q : 当前道路承载量_L : 道路时间开销_SL : 两点之间最短时间开销"""def dijkstra(self, G): """ dijkstra算法 """ # 邻接表 adj = {} # 距离 dists = {} # 前置点 prevs = {} for i in xrange(self.size): adj[i] = [] for j in xrange(self.size): if G[i][j] != float('inf'): adj[i].append(j) for o in xrange(self.size): vis = {x: False for x in xrange(self.size)} min_heap = [] heapq.heappush(min_heap, (0, o)) dist = {x: float('inf') for x in xrange(self.size)} dist[o] = 0 prev = {x: x for x in xrange(self.size)} while len(min_heap) > 0: d, i = heapq.heappop(min_heap) if vis[i]: continue vis[i] = True for j in adj[i]: if not vis[j] and dist[j] > dist[i] + G[i][j]: # 松弛操作 dist[j] = dist[i] + G[i][j] prev[j] = i heapq.heappush(min_heap, (dist[j], j)) dists[o] = dist prevs[o] = prev return dists, prevsdef gen_D(self, is_city): """ 随机生成路网 """ self._D = np.full((self.base_size, self.base_size), np.inf) self._DEG = np.zeros(self.base_size) for i in xrange(self.base_size): self._D[i][i] = 0 deg = random.randint(0, min(4, self.base_size-1)) connection_list = random.sample(range(self.base_size), deg) while i in connection_list: connection_list = random.sample(range(self.base_size), deg) for j in connection_list: if self._DEG[i] >= 4 or self._DEG[j] >= 4: continue if is_city: # 100 ~ 500 m self._D[i][j] = self._D[j][i] = random.random() * 0.4 + 0.1 else: # 30 ~ 300 m self._D[i][j] = self._D[j][i] = random.random() * 0.27 + 0.03 self._DEG[i] += 1 self._DEG[j] += 1def cal_B(self): """ 计算介数 """ self._B = np.zeros(self.size) dists, prevs = self.dijkstra(self._D) for o in xrange(self.size): for d in xrange(self.size): if o == d or dists[o][d] == float('inf'): continue u = d while u != o: self._B[u] += 1 u = prevs[o][u] self._B[o] += 1 total = sum(self._B) self._B /= totaldef cal_sp_fast(self): """ 计算任意两点最短路以及相应路径矩阵 """ self._PATH = np.full(self._D.shape, -1, 'int32') self._SL = np.array(self._L) adj = {} dists, prevs = self.dijkstra(self._L) for o in xrange(self.size): for d in xrange(self.size): self._SL[o][d] = dists[o][d] if o == d or self._SL[o][d] == float('inf'): continue u = d while u != o: self._PATH[prevs[o][u]][d] = u u = prevs[o][u]def iteration(self, eta=0.2, it_no=1, sp_func=None): """ Frank-Wolfe算法迭代 """ _NEW_Q = np.zeros(self._Q.shape) # 更新最短时间路径的函数(即cal_sp_fast) sp_func() for i in xrange(self.base_size): for j in xrange(self.base_size): if i == j: continue if not self.is_reachalbe(i, j): continue s = i while s != j: t = self._PATH[s][j] _NEW_Q[s][t] = self._OD[i][j] s = t _DETAL_Q = _NEW_Q - self._Q for i in xrange(self.base_size): for j in xrange(self.base_size): if i == j or self._D[i][j] == float('inf'): continue self._Q[i][j] += eta * _DETAL_Q[i][j] / it_no ** 0.3 self._L[i][j] = bpr(self._D[i][j] / SPEED, self._Q[i][j], self._C[i][j]) ev = self.evaluate() return evdef converge_fast(self): """ 尝试收敛 """ self._L = self._D / SPEED pre = self.first_iteration(sp_func=self.cal_sp_fast) now = self.iteration(sp_func=self.cal_sp_fast) cnt = 1 while now < pre: pre = now now = self.iteration(it_no=cnt, sp_func=self.cal_sp_fast) cnt += 1 return cntdef get_hub(self, num, mode=1): """ 获取介数最小,适中,最大的num个结点 """ self.cal_B() b = zip(self._B, range(len(self._B))) sorted_b = [y for x, y in sorted(b)] if num > len(sorted_b): num = len(sorted_b) if mode == 0: ret = sorted_b[:num] elif mode == 1: mid = len(sorted_b) / 2 l = mid - num/2 r = mid + num/2 while r - l > num: r -= 1 while r - l < num: r += 1 ret = sorted_b[l:r] elif mode == 2: ret = sorted_b[-num:] return np.array(ret, dtype=int)def merge(self, other, conn_num=3, mode=0): """ 按照不同mode合并城市与小区 """ origin_size = self.size self._D = self.merge_matrix(self._D, other._D, np.inf) self._C = self.merge_matrix(self._C, other._C, 0.0) self.size = self._D.shape[0] city_v = self.get_hub(conn_num, mode/3) area_v = other.get_hub(conn_num, mode%3) + origin_size conn_num = min(len(city_v), len(area_v)) for i in xrange(conn_num): self._D[city_v[i]][area_v[i]] = self._D[area_v[i]][city_v[i]] = 0 self._C[city_v[i]][area_v[i]] = self._C[area_v[i]][city_v[i]] = np.inf