[关闭]
@enhuiz 2016-09-12T05:37:51.000000Z 字数 3499 阅读 347

重要代码

  1. """
  2. 主要变量说明:
  3. _C : 道路设计承载量
  4. _D : 道路长度
  5. _OD : O/D矩阵
  6. _DEG: 结点度数列表
  7. _B : 结点介数列表
  8. _Q : 当前道路承载量
  9. _L : 道路时间开销
  10. _SL : 两点之间最短时间开销
  11. """
  12. def dijkstra(self, G):
  13. """
  14. dijkstra算法
  15. """
  16. # 邻接表
  17. adj = {}
  18. # 距离
  19. dists = {}
  20. # 前置点
  21. prevs = {}
  22. for i in xrange(self.size):
  23. adj[i] = []
  24. for j in xrange(self.size):
  25. if G[i][j] != float('inf'):
  26. adj[i].append(j)
  27. for o in xrange(self.size):
  28. vis = {x: False for x in xrange(self.size)}
  29. min_heap = []
  30. heapq.heappush(min_heap, (0, o))
  31. dist = {x: float('inf') for x in xrange(self.size)}
  32. dist[o] = 0
  33. prev = {x: x for x in xrange(self.size)}
  34. while len(min_heap) > 0:
  35. d, i = heapq.heappop(min_heap)
  36. if vis[i]: continue
  37. vis[i] = True
  38. for j in adj[i]:
  39. if not vis[j] and dist[j] > dist[i] + G[i][j]:
  40. # 松弛操作
  41. dist[j] = dist[i] + G[i][j]
  42. prev[j] = i
  43. heapq.heappush(min_heap, (dist[j], j))
  44. dists[o] = dist
  45. prevs[o] = prev
  46. return dists, prevs
  47. def gen_D(self, is_city):
  48. """
  49. 随机生成路网
  50. """
  51. self._D = np.full((self.base_size, self.base_size), np.inf)
  52. self._DEG = np.zeros(self.base_size)
  53. for i in xrange(self.base_size):
  54. self._D[i][i] = 0
  55. deg = random.randint(0, min(4, self.base_size-1))
  56. connection_list = random.sample(range(self.base_size), deg)
  57. while i in connection_list:
  58. connection_list = random.sample(range(self.base_size), deg)
  59. for j in connection_list:
  60. if self._DEG[i] >= 4 or self._DEG[j] >= 4: continue
  61. if is_city:
  62. # 100 ~ 500 m
  63. self._D[i][j] = self._D[j][i] = random.random() * 0.4 + 0.1
  64. else:
  65. # 30 ~ 300 m
  66. self._D[i][j] = self._D[j][i] = random.random() * 0.27 + 0.03
  67. self._DEG[i] += 1
  68. self._DEG[j] += 1
  69. def cal_B(self):
  70. """
  71. 计算介数
  72. """
  73. self._B = np.zeros(self.size)
  74. dists, prevs = self.dijkstra(self._D)
  75. for o in xrange(self.size):
  76. for d in xrange(self.size):
  77. if o == d or dists[o][d] == float('inf'): continue
  78. u = d
  79. while u != o:
  80. self._B[u] += 1
  81. u = prevs[o][u]
  82. self._B[o] += 1
  83. total = sum(self._B)
  84. self._B /= total
  85. def cal_sp_fast(self):
  86. """
  87. 计算任意两点最短路以及相应路径矩阵
  88. """
  89. self._PATH = np.full(self._D.shape, -1, 'int32')
  90. self._SL = np.array(self._L)
  91. adj = {}
  92. dists, prevs = self.dijkstra(self._L)
  93. for o in xrange(self.size):
  94. for d in xrange(self.size):
  95. self._SL[o][d] = dists[o][d]
  96. if o == d or self._SL[o][d] == float('inf'): continue
  97. u = d
  98. while u != o:
  99. self._PATH[prevs[o][u]][d] = u
  100. u = prevs[o][u]
  101. def iteration(self, eta=0.2, it_no=1, sp_func=None):
  102. """
  103. Frank-Wolfe算法迭代
  104. """
  105. _NEW_Q = np.zeros(self._Q.shape)
  106. # 更新最短时间路径的函数(即cal_sp_fast)
  107. sp_func()
  108. for i in xrange(self.base_size):
  109. for j in xrange(self.base_size):
  110. if i == j: continue
  111. if not self.is_reachalbe(i, j): continue
  112. s = i
  113. while s != j:
  114. t = self._PATH[s][j]
  115. _NEW_Q[s][t] = self._OD[i][j]
  116. s = t
  117. _DETAL_Q = _NEW_Q - self._Q
  118. for i in xrange(self.base_size):
  119. for j in xrange(self.base_size):
  120. if i == j or self._D[i][j] == float('inf'): continue
  121. self._Q[i][j] += eta * _DETAL_Q[i][j] / it_no ** 0.3
  122. self._L[i][j] = bpr(self._D[i][j] / SPEED, self._Q[i][j], self._C[i][j])
  123. ev = self.evaluate()
  124. return ev
  125. def converge_fast(self):
  126. """
  127. 尝试收敛
  128. """
  129. self._L = self._D / SPEED
  130. pre = self.first_iteration(sp_func=self.cal_sp_fast)
  131. now = self.iteration(sp_func=self.cal_sp_fast)
  132. cnt = 1
  133. while now < pre:
  134. pre = now
  135. now = self.iteration(it_no=cnt, sp_func=self.cal_sp_fast)
  136. cnt += 1
  137. return cnt
  138. def get_hub(self, num, mode=1):
  139. """
  140. 获取介数最小,适中,最大的num个结点
  141. """
  142. self.cal_B()
  143. b = zip(self._B, range(len(self._B)))
  144. sorted_b = [y for x, y in sorted(b)]
  145. if num > len(sorted_b):
  146. num = len(sorted_b)
  147. if mode == 0:
  148. ret = sorted_b[:num]
  149. elif mode == 1:
  150. mid = len(sorted_b) / 2
  151. l = mid - num/2
  152. r = mid + num/2
  153. while r - l > num: r -= 1
  154. while r - l < num: r += 1
  155. ret = sorted_b[l:r]
  156. elif mode == 2:
  157. ret = sorted_b[-num:]
  158. return np.array(ret, dtype=int)
  159. def merge(self, other, conn_num=3, mode=0):
  160. """
  161. 按照不同mode合并城市与小区
  162. """
  163. origin_size = self.size
  164. self._D = self.merge_matrix(self._D, other._D, np.inf)
  165. self._C = self.merge_matrix(self._C, other._C, 0.0)
  166. self.size = self._D.shape[0]
  167. city_v = self.get_hub(conn_num, mode/3)
  168. area_v = other.get_hub(conn_num, mode%3) + origin_size
  169. conn_num = min(len(city_v), len(area_v))
  170. for i in xrange(conn_num):
  171. self._D[city_v[i]][area_v[i]] = self._D[area_v[i]][city_v[i]] = 0
  172. self._C[city_v[i]][area_v[i]] = self._C[area_v[i]][city_v[i]] = np.inf
添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注