路由算法(Dijkstra算法以及遗传算法)

(1)Dijkstra算法

  1 class Dijkstra(Algorithm):
  2     """Dijkstra algorithm for unicast route calculation.
  3     """
  4     def __init__(self, delay_coefficient=5000, cost_coefficient=0.02, bw_load_coefficient=50):
  5         if not hasattr(self, 'cost_coeffieient'):
  6             super(Dijkstra, self).__init__()
  7 
  8             self.delay_coefficient = delay_coefficient
  9             self.cost_coefficient = cost_coefficient
 10             self.bw_load_coefficient = bw_load_coefficient
 11 
 12     def __new__(cls, *args, **kwargs):
 13         if not hasattr(cls, '_instance'):
 14             orig = super(Dijkstra, cls)
 15             cls._instance = orig.__new__(cls, *args, **kwargs)
 16         return cls._instance
 17 
 18     def get_link(self, src, dst, link_type=None):
 19         dst_num = self.switch_queue.index(dst)
 20 
 21         links_in_num = None
 22         for num, link in enumerate(self.links):
 23             if dst_num == link[len(link)-1]:
 24                 links_in_num = self.links[num]
 25                 break
 26 
 27         # handle algorithm failure mode
 28         if links_in_num is None:
 29             logger.error("links_in_num is None")
 30             return None, None
 31         elif len(links_in_num) < 2:
 32             # such as when no path from switch A(number:1) to switch B(number:2)
 33             # the result will be [2]
 34             logger.error("destination switch unreachable in graph.")
 35             return None, None
 36 
 37         self.link_cache[links_in_num[0], links_in_num[1]] = links_in_num
 38         links_in_dpid = []
 39         for l in links_in_num:
 40             links_in_dpid.append(self.switch_queue[l])
 41 
 42         link_cost = 0
 43         for i in range(0, len(links_in_num)-1):
 44             for e in self.edges:
 45                 if links_in_num[i] == e[1] and links_in_num[i+1] == e[2] or \
 46                    links_in_num[i] == e[2] and links_in_num[i+1] == e[1]:
 47                     link_cost += e[4]
 48                     break
 49 
 50         return links_in_dpid, link_cost
 51 
 52     def init_algorithm(self, switches, links):
 53         """
 54             called when topo changed.
 55             both switch enter/leave or link add/delete.
 56         """
 57         self.switch_queue = []
 58         self.edge_queue = []
 59         self.switch_neighbors = {}
 60         self.edge_collection = {}
 61         self.vertexs = []
 62         self.edges = []
 63         self.links = []
 64         self.fitness = []
 65         self.link_cache = {}
 66 
 67         # update switch/edge queue
 68         self.switch_queue = switches.keys()
 69         self.edge_queue = links.keys()
 70 
 71         # update switch neighbors
 72         for dpid, sw in switches.items():
 73             num = self.switch_queue.index(dpid)
 74             neighbors_in_dpid = sw.neighbors.keys()
 75             neighbors_in_num = []
 76             for n in neighbors_in_dpid:
 77                 neighbors_in_num.append(self.switch_queue.index(n))
 78             self.switch_neighbors[num] = neighbors_in_num
 79 
 80         # update edge collection
 81         for dpids, edge in links.items():
 82             src_num = self.switch_queue.index(dpids[0])
 83             dst_num = self.switch_queue.index(dpids[1])
 84             ev = edge.values()[0]
 85             self.edge_collection[(src_num, dst_num)] = ev
 86             self.edges.append([0, src_num, dst_num,
 87                                float(ev.delay), float(ev.cost),
 88                                ev.available_band, float(ev.total_band)])
 89 
 90         # update self.vertexs
 91         for src_num, neighbors in self.switch_neighbors.items():
 92             self.vertexs.append([len(neighbors), neighbors, []])
 93             for dst_num in neighbors:
 94                 for num, edge in enumerate(self.edges):
 95                     if (edge[1], edge[2]) == (src_num, dst_num) or \
 96                        (edge[1], edge[2]) == (dst_num, src_num):
 97                         self.vertexs[src_num][2].append(num)
 98 
 99     def update_link_status(self, links):
100         self.edges = []
101         for dpids, edge in links.items():
102             src_num = self.switch_queue.index(dpids[0])
103             dst_num = self.switch_queue.index(dpids[1])
104             ev = edge.values()[0]
105             self.edge_collection[(src_num, dst_num)] = ev
106             self.edges.append([0, src_num, dst_num,
107                                float(ev.delay), float(ev.cost),
108                                float(ev.available_band), float(ev.total_band)])
109             logger.debug("src_dpid:%s, dst_dpid:%s, available band:%s Mbits, total band:%s Mbits, usage:%s",
110                          dpids[0], dpids[1],
111                          float(ev.available_band)/Megabits,
112                          float(ev.total_band)/Megabits,
113                          1.0 - float(ev.available_band) / float(ev.total_band))
114 
115     def run(self, src_dpid, dst_dpid, min_bandwidth):
116         src_num = self.switch_queue.index(src_dpid)
117         self.links = self.calculate(src_num, self.vertexs, self.edges)
118 
119     def calculate(self, sou_vertex, vertexs, edges):
120         """
121             return paths list from source vertex to all the other destination
122             vertex, such as:
123 
124             when source vertex number = 5
125 
126             paths = [[5, 6, 7, ..., 1], [5, ..., 4], [5, 8], ..., [5]]
127         """
128         tag = [0 for i in range(vertexs.__len__())]
129         previous_vertex = [-1 for i in range(vertexs.__len__())]
130         paths_length = [10000 for i in range(vertexs.__len__())]
131         paths = []
132 
133         vertex_selected = sou_vertex
134         tag[sou_vertex] = 1
135         paths_length[sou_vertex] = 0
136 
137         for i in range(vertexs.__len__() - 1):
138             for j in range(vertexs.__len__()):
139                 if tag[j] == 0:
140                     min_length = paths_length[j]
141                     record = j
142                     break
143             for j in vertexs[vertex_selected][1]:
144                 if tag[j] == 0:
145                     temp = self.use_available_bandwidth_mark_weight(vertex_selected, j, edges)
146                     if paths_length[vertex_selected] + temp < paths_length[j]:
147                         paths_length[j] = paths_length[vertex_selected] + temp
148                         previous_vertex[j] = vertex_selected
149             for j in range(vertexs.__len__()):
150                 if tag[j] == 0:
151                     if paths_length[j] < min_length:
152                         min_length = paths_length[j]
153                         record = j
154             vertex_selected = record
155             tag[vertex_selected] = 1
156         for i in range(vertexs.__len__()):
157             paths.append([i])
158             j = i
159             while not previous_vertex[j] == -1:
160                 j = previous_vertex[j]
161                 paths[i].insert(0, j)
162         return paths
163 
164     def use_available_bandwidth_mark_weight(self, vertex1, vertex2, edges):
165         for i in range(edges.__len__()):
166             if vertex1 == edges[i][1]:
167                 if vertex2 == edges[i][2]:
168                     rval = (self.delay_coefficient * edges[i][3] +
169                             self.cost_coefficient * edges[i][4] +
170                             self.bw_load_coefficient * (1-edges[i][5]/edges[i][6]))
171                     return rval
172             if vertex2 == edges[i][1]:
173                 if vertex1 == edges[i][2]:
174                     rval = (self.delay_coefficient * edges[i][3] +
175                             self.cost_coefficient * edges[i][4] +
176                             self.bw_load_coefficient * (1-edges[i][5]/edges[i][6]))
177                     return rval
178         return 2 * (self.delay_coefficient * 1 +
179                     self.cost_coefficient * 100 +
180                     self.bw_load_coefficient * 1)
181 
182     def param_to_dict(self):
183         body = json.dumps({"delay_coefficient": self.delay_coefficient,
184                            "cost_coefficient": self.cost_coefficient,
185                            "bw_load_coefficient": self.bw_load_coefficient})
186         return body
187 
188     def param_to_json(self):
189         r = json.dumps({
190             "communication_mode": "unicast",
191             "algorithm_type": "Dij",
192             "delay_coefficient": str(self.delay_coefficient),
193             "cost_coefficient": str(self.cost_coefficient),
194             "bw_load_coefficient": str(self.bw_load_coefficient)
195         })
196         return r
197 
198     def update_param(self, data):
199         if data["algorithm_type"] != "Dij":
200             return False
201 
202         def update(s, k, p):
203             if k in p: return float(p[k])
204             else: return s
205 
206         self.delay_coefficient = update(self.delay_coefficient, "delay_coefficient", data)
207         self.cost_coefficient = update(self.cost_coefficient, "cost_coefficient", data)
208         self.bw_load_coefficient = update(self.bw_load_coefficient, "bw_load_coefficient", data)
209         return True

(2)遗传算法

 

posted @ 2021-07-09 13:02  Jcpeng_std  阅读(507)  评论(1编辑  收藏  举报