1. 程式人生 > 其它 >路由演算法(Dijkstra演算法以及遺傳演算法)

路由演算法(Dijkstra演算法以及遺傳演算法)

(1)Dijkstra演算法

class Dijkstra(Algorithm):
"""Dijkstra algorithm for unicast route calculation.
"""
def __init__(self, delay_coefficient=5000, cost_coefficient=0.02, bw_load_coefficient=50):
if not hasattr(self, 'cost_coeffieient'):
super(Dijkstra, self).__init__()

self.delay_coefficient = delay_coefficient
self.cost_coefficient = cost_coefficient
self.bw_load_coefficient = bw_load_coefficient

def __new__(cls, *args, **kwargs):
if not hasattr(cls, '_instance'):
orig = super(Dijkstra, cls)
cls._instance = orig.__new__(cls, *args, **kwargs)
return cls._instance

def get_link(self, src, dst, link_type=None):
dst_num = self.switch_queue.index(dst)

links_in_num = None
for num, link in enumerate(self.links):
if dst_num == link[len(link)-1]:
links_in_num = self.links[num]
break

# handle algorithm failure mode
if links_in_num is None:
logger.error("links_in_num is None")
return None, None
elif len(links_in_num) < 2:
# such as when no path from switch A(number:1) to switch B(number:2)
# the result will be [2]
logger.error("destination switch unreachable in graph.")
return None, None

self.link_cache[links_in_num[0], links_in_num[1]] = links_in_num
links_in_dpid = []
for l in links_in_num:
links_in_dpid.append(self.switch_queue[l])

link_cost = 0
for i in range(0, len(links_in_num)-1):
for e in self.edges:
if links_in_num[i] == e[1] and links_in_num[i+1] == e[2] or \
links_in_num[i] == e[2] and links_in_num[i+1] == e[1]:
link_cost += e[4]
break

return links_in_dpid, link_cost

def init_algorithm(self, switches, links):
"""
called when topo changed.
both switch enter/leave or link add/delete.
"""
self.switch_queue = []
self.edge_queue = []
self.switch_neighbors = {}
self.edge_collection = {}
self.vertexs = []
self.edges = []
self.links = []
self.fitness = []
self.link_cache = {}

# update switch/edge queue
self.switch_queue = switches.keys()
self.edge_queue = links.keys()

# update switch neighbors
for dpid, sw in switches.items():
num = self.switch_queue.index(dpid)
neighbors_in_dpid = sw.neighbors.keys()
neighbors_in_num = []
for n in neighbors_in_dpid:
neighbors_in_num.append(self.switch_queue.index(n))
self.switch_neighbors[num] = neighbors_in_num

# update edge collection
for dpids, edge in links.items():
src_num = self.switch_queue.index(dpids[0])
dst_num = self.switch_queue.index(dpids[1])
ev = edge.values()[0]
self.edge_collection[(src_num, dst_num)] = ev
self.edges.append([0, src_num, dst_num,
float(ev.delay), float(ev.cost),
ev.available_band, float(ev.total_band)])

# update self.vertexs
for src_num, neighbors in self.switch_neighbors.items():
self.vertexs.append([len(neighbors), neighbors, []])
for dst_num in neighbors:
for num, edge in enumerate(self.edges):
if (edge[1], edge[2]) == (src_num, dst_num) or \
(edge[1], edge[2]) == (dst_num, src_num):
self.vertexs[src_num][2].append(num)

def update_link_status(self, links):
self.edges = []
for dpids, edge in links.items():
src_num = self.switch_queue.index(dpids[0])
dst_num = self.switch_queue.index(dpids[1])
ev = edge.values()[0]
self.edge_collection[(src_num, dst_num)] = ev
self.edges.append([0, src_num, dst_num,
float(ev.delay), float(ev.cost),
float(ev.available_band), float(ev.total_band)])
logger.debug("src_dpid:%s, dst_dpid:%s, available band:%s Mbits, total band:%s Mbits, usage:%s",
dpids[0], dpids[1],
float(ev.available_band)/Megabits,
float(ev.total_band)/Megabits,
1.0 - float(ev.available_band) / float(ev.total_band))

def run(self, src_dpid, dst_dpid, min_bandwidth):
src_num = self.switch_queue.index(src_dpid)
self.links = self.calculate(src_num, self.vertexs, self.edges)

def calculate(self, sou_vertex, vertexs, edges):
"""
return paths list from source vertex to all the other destination
vertex, such as:

when source vertex number = 5

paths = [[5, 6, 7, ..., 1], [5, ..., 4], [5, 8], ..., [5]]
"""
tag = [0 for i in range(vertexs.__len__())]
previous_vertex = [-1 for i in range(vertexs.__len__())]
paths_length = [10000 for i in range(vertexs.__len__())]
paths = []

vertex_selected = sou_vertex
tag[sou_vertex] = 1
paths_length[sou_vertex] = 0

for i in range(vertexs.__len__() - 1):
for j in range(vertexs.__len__()):
if tag[j] == 0:
min_length = paths_length[j]
record = j
break
for j in vertexs[vertex_selected][1]:
if tag[j] == 0:
temp = self.use_available_bandwidth_mark_weight(vertex_selected, j, edges)
if paths_length[vertex_selected] + temp < paths_length[j]:
paths_length[j] = paths_length[vertex_selected] + temp
previous_vertex[j] = vertex_selected
for j in range(vertexs.__len__()):
if tag[j] == 0:
if paths_length[j] < min_length:
min_length = paths_length[j]
record = j
vertex_selected = record
tag[vertex_selected] = 1
for i in range(vertexs.__len__()):
paths.append([i])
j = i
while not previous_vertex[j] == -1:
j = previous_vertex[j]
paths[i].insert(0, j)
return paths

def use_available_bandwidth_mark_weight(self, vertex1, vertex2, edges):
for i in range(edges.__len__()):
if vertex1 == edges[i][1]:
if vertex2 == edges[i][2]:
rval = (self.delay_coefficient * edges[i][3] +
self.cost_coefficient * edges[i][4] +
self.bw_load_coefficient * (1-edges[i][5]/edges[i][6]))
return rval
if vertex2 == edges[i][1]:
if vertex1 == edges[i][2]:
rval = (self.delay_coefficient * edges[i][3] +
self.cost_coefficient * edges[i][4] +
self.bw_load_coefficient * (1-edges[i][5]/edges[i][6]))
return rval
return 2 * (self.delay_coefficient * 1 +
self.cost_coefficient * 100 +
self.bw_load_coefficient * 1)

def param_to_dict(self):
body = json.dumps({"delay_coefficient": self.delay_coefficient,
"cost_coefficient": self.cost_coefficient,
"bw_load_coefficient": self.bw_load_coefficient})
return body

def param_to_json(self):
r = json.dumps({
"communication_mode": "unicast",
"algorithm_type": "Dij",
"delay_coefficient": str(self.delay_coefficient),
"cost_coefficient": str(self.cost_coefficient),
"bw_load_coefficient": str(self.bw_load_coefficient)
})
return r

def update_param(self, data):
if data["algorithm_type"] != "Dij":
return False

def update(s, k, p):
if k in p: return float(p[k])
else: return s

self.delay_coefficient = update(self.delay_coefficient, "delay_coefficient", data)
self.cost_coefficient = update(self.cost_coefficient, "cost_coefficient", data)
self.bw_load_coefficient = update(self.bw_load_coefficient, "bw_load_coefficient", data)
return True

(2)遺傳演算法