def opt2(solution=[], dist_matrix=[]): #no puedo llamarle 2_opt """ Implementacion del algoritmo 2-Optimo nota: nelson descubrio donde fallaba el algoritmo :P """ n_vertex = len(solution) soluc = solution[:] for i in xrange(n_vertex - 3): for j in xrange(i + 2, n_vertex - 1): vi = soluc[i] vj = soluc[i + 1] vk = soluc[j] vl = soluc[j + 1] d1 = dist(vi, vj, dist_matrix) + dist(vk, vl, dist_matrix) d2 = dist(vi, vk, dist_matrix) + dist(vj, vl, dist_matrix) if d2 < d1: ini = soluc[:i + 1] med = soluc[i + 1:j + 1] med.reverse() fin = soluc[j + 1:] soluc = ini + med + fin return soluc
def opt2(solution=[], dist_matrix=[]): #no puedo llamarle 2_opt """ Implementacion del algoritmo 2-Optimo nota: nelson descubrio donde fallaba el algoritmo :P """ n_vertex = len(solution) soluc = solution[:] for i in xrange(n_vertex-3): for j in xrange(i+2, n_vertex-1): vi = soluc[i] vj = soluc[i+1] vk = soluc[j] vl = soluc[j+1] d1 = dist(vi,vj,dist_matrix) + dist(vk,vl,dist_matrix) d2 = dist(vi,vk,dist_matrix) + dist(vj,vl,dist_matrix) if d2 < d1: ini = soluc[:i+1] med = soluc[i+1:j+1] med.reverse() fin = soluc[j+1:] soluc = ini + med + fin return soluc
def nearest_vertex(distances, size): random.seed() tsp_sol = [] number_of_vertex = size vertex_list = range(number_of_vertex) incoming_vertex = random.randint(0,number_of_vertex-1) min_distance = 0 tsp_sol.append(incoming_vertex) vertex_list.remove(incoming_vertex) counter = 0 echo("building solution.....") while counter < number_of_vertex-1: flag = 0 vertex = tsp_sol[-1] #el ultimo elemento de tsp_sol for vertex_2 in vertex_list: if not flag: flag = 1 min_distance=dist(vertex,vertex_2,distances) incoming_vertex = vertex_2 else: temp_distance = dist(vertex,vertex_2,distances) if min_distance > temp_distance: min_distance = temp_distance incoming_vertex = vertex_2 tsp_sol.append(incoming_vertex) vertex_list.remove(incoming_vertex) counter+=1 echo("Done") return tsp_sol
def nearest_vertex(distances, size): random.seed() tsp_sol = [] number_of_vertex = size vertex_list = range(number_of_vertex) incoming_vertex = random.randint(0, number_of_vertex - 1) min_distance = 0 tsp_sol.append(incoming_vertex) vertex_list.remove(incoming_vertex) counter = 0 echo("building solution.....") while counter < number_of_vertex - 1: flag = 0 vertex = tsp_sol[-1] #el ultimo elemento de tsp_sol for vertex_2 in vertex_list: if not flag: flag = 1 min_distance = dist(vertex, vertex_2, distances) incoming_vertex = vertex_2 else: temp_distance = dist(vertex, vertex_2, distances) if min_distance > temp_distance: min_distance = temp_distance incoming_vertex = vertex_2 tsp_sol.append(incoming_vertex) vertex_list.remove(incoming_vertex) counter += 1 echo("Done") return tsp_sol
def create_neighbor(solution_o, k, memory, maximum, probability, distances, invert_mode = False): """ Crea un vecino de solution perteneciente al vecindario k, pero tomando en cuenta la memoria de largo plazo """ if not invert_mode: a = 0 b = -1 else: a = 1 b = 1 random.seed() solution = solution_o[:] selected = [] alredy_selected = [0]*len(solution_o) if k == len(solution): selected = solution else: for i in range(k): found = 0 while not found: alredy_used = 0 while not alredy_used: vertex = random.choice(solution) index = solution.index(vertex) if alredy_selected[index] == 0: alredy_used = 1 vertex_a = solution[index-1] if index == (len(solution)-1): index = -1 vertex_p = solution[index+1] counter_a = dist(vertex_a, vertex, memory) counter_p = dist(vertex_p, vertex, memory) if counter_a > counter_p: counter = counter_a else: counter = counter_p prob = counter*probability/maximum prob = (a-prob)*b luck = random.random() #print prob, luck, maximum if luck >= prob: selected.append(vertex) alredy_selected[index] = 1 found = 1 neighbor = solution_o[:] vertex = random.choice(selected) selected.remove(vertex) index = neighbor.index(vertex) while selected != []: vertex_b = random.choice(selected) selected.remove(vertex_b) index_b = neighbor.index(vertex_b) neighbor[index] = vertex_b neighbor[index_b] = vertex index = index_b return neighbor
def nearest_neighbor_sort(graph: Graph) -> Node: def follow_path(n: Node): if len(n.edges) > 1: raise ValueError('Start {!r} has more than one edge'.format(n)) if len(n.edges) == 0: return n last = n selected = next(iter(n.edges)) while len(selected.edges) != 1: if len(selected.edges) != 2: raise ValueError('Inner {!r} does not have two edges'.format(selected)) next_node = next(iter(selected.edges.difference({last}))) last = selected selected = next_node return selected picked = set() # we only want to connect nodes on the end of a path, not in the middle end_nodes = set(filter(lambda n: len(n.edges) <= 1, graph.nodes)) # pick a node to start from start = random.choice(list(end_nodes)) # TODO: find a better way to get a random element selected = follow_path(start) picked.add(selected) picked.add(start) remaining = end_nodes.difference(picked) while len(remaining) != 0: next_node = min(remaining, key=lambda n: dist(selected, n)) # follow node to the end of its path end = follow_path(next_node) selected.connect(next_node) picked.add(next_node) picked.add(end) selected = end remaining = end_nodes.difference(picked) return start
def vns_opt2(solution=[], dist_matrix=[]): #no puedo llamarle 2_opt """ Implementacion del algoritmo 2-Optimo que funciona como VNS el algoritmo es algo trucho pero es entre 10 y 20 veses mas rapido que 3opt y los resultados varian muy poco """ n_vertex = len(solution) soluc = solution[:] loop=True while loop: i=0 while i < n_vertex-3: j = i + 2 while j < n_vertex-1: vi = soluc[i] vj = soluc[i+1] vk = soluc[j] vl = soluc[j+1] d1 = dist(vi,vj,dist_matrix) + dist(vk,vl,dist_matrix) d2 = dist(vi,vk,dist_matrix) + dist(vj,vl,dist_matrix) if d2 < d1: ini = soluc[:i+1] med = soluc[i+1:j+1] med.reverse() fin = soluc[j+1:] soluc = ini + med + fin i = 0 j = 1 #con esto remplazo el break de abajo #break #los break no son muy elegantes por eso lo quito j += 1 i += 1 if i == n_vertex - 3: loop = False return soluc
def vns_opt2(solution=[], dist_matrix=[]): #no puedo llamarle 2_opt """ Implementacion del algoritmo 2-Optimo que funciona como VNS el algoritmo es algo trucho pero es entre 10 y 20 veses mas rapido que 3opt y los resultados varian muy poco """ n_vertex = len(solution) soluc = solution[:] loop = True while loop: i = 0 while i < n_vertex - 3: j = i + 2 while j < n_vertex - 1: vi = soluc[i] vj = soluc[i + 1] vk = soluc[j] vl = soluc[j + 1] d1 = dist(vi, vj, dist_matrix) + dist(vk, vl, dist_matrix) d2 = dist(vi, vk, dist_matrix) + dist(vj, vl, dist_matrix) if d2 < d1: ini = soluc[:i + 1] med = soluc[i + 1:j + 1] med.reverse() fin = soluc[j + 1:] soluc = ini + med + fin i = 0 j = 1 #con esto remplazo el break de abajo #break #los break no son muy elegantes por eso lo quito j += 1 i += 1 if i == n_vertex - 3: loop = False return soluc
def min_(k, vertex_list, dist_matrix=[]): """ Calcula el vertice perteneciente a vertex_list mas cercano a k. Retorna ady_vertex : vertice mas cercano a k cost: costo de agregar el nuevo vertice """ ady_vertex = None #vertice adyacente que se agregara cost = 9999999999 #defino un costo inicial muy elevado for vert in vertex_list: #bobo un algoritmo de busqueda if vert != k: ncost = dist(k, vert, dist_matrix) if ncost < cost: ady_vertex = vert cost = ncost return ady_vertex, cost
def opt3_(solution=[], d_m=[]): """ Implementacion del Algoritmo 3-Optimo, optimizado en velocidad calculo """ n_vertex = len(solution) soluc = solution[:] for i in xrange(n_vertex-5): for j in xrange(i+2, n_vertex-3): for k in xrange(j+2, n_vertex-3): va, vb = soluc[i], soluc[i+1] vc, vd = soluc[j], soluc[j+1] ve, vf = soluc[k], soluc[k+1] #calculo las distancias de todas las posibles conbinaciones #muchos calculos entre las conv se repiten y para no hacerlos #de nuevo los calculo una sola ves lo que reduce a la mitad la #cantida usos de la func dist d_ab = dist(va,vb,d_m) d_ac = dist(va,vc,d_m) d_ad = dist(va,vd,d_m) d_ae = dist(va,ve,d_m) d_ef = dist(ve,vf,d_m) d_df = dist(vd,vf,d_m) d_cf = dist(vc,vf,d_m) d_vf = dist(vb,vf,d_m) d_bd = dist(vb,vd,d_m) # d_bd = d_db d_cd = dist(vc,vd,d_m) # d_cd = d_dc d_be = dist(vb,ve,d_m) # d_be = d_eb d_ce = dist(vc,ve,d_m) # d_ce = d_ec distances = [ d_ab + d_cd + d_ef, d_ac + d_bd + d_ef, d_ab + d_ce + d_df, d_ac + d_be + d_df, d_ad + d_be + d_cf, d_ae + d_bd + d_cf, d_ad + d_ce + d_vf, d_ae + d_cd + d_vf, ] ini = soluc[:i+1] #tramo hasta a includo t_bc = soluc[i+1:j+1] #tramo bc t_de = soluc[j+1:k+1] #tramo de fin = soluc[k+1:] #tramo desde f includo #d = distances[:] #d.sort() mini = distances.index(min(distances)) #el primer caso es el original, no implica ningun cambio #por eso no hago nada, ahh aca no hay case pero lo mismo eso #se soluciona a como sigue :P if mini == 1: t_bc.reverse() elif mini == 2: t_de.reverse() elif mini == 3: t_bc.reverse() t_de.reverse() #cuando min = 4 solo invierte las posiciones de tramos bc y ef #osea intercambo ambos tramos bc -> ef y ef -> bc elif mini == 5: t_de.reverse() elif mini == 6: t_bc.reverse() elif mini == 7: t_bc.reverse() t_de.reverse() if mini < 4: soluc = ini + t_bc + t_de + fin else: soluc = ini + t_de + t_bc + fin return soluc
def opt3(solution=[], d_m=[]): """ Implementacion del Algoritmo 3-Optimo """ n_vertex = len(solution) soluc = solution[:] for i in xrange(n_vertex-5): for j in xrange(i+2, n_vertex-3): for k in xrange(j+2, n_vertex-3): va, vb = soluc[i], soluc[i+1] vc, vd = soluc[j], soluc[j+1] ve, vf = soluc[k], soluc[k+1] #calculo las distancias de todas las posibles conbinaciones distances = [ dist(va,vb,d_m) + dist(vc,vd,d_m) + dist(ve,vf,d_m), dist(va,vc,d_m) + dist(vb,vd,d_m) + dist(ve,vf,d_m), dist(va,vb,d_m) + dist(vc,ve,d_m) + dist(vd,vf,d_m), dist(va,vc,d_m) + dist(vb,ve,d_m) + dist(vd,vf,d_m), dist(va,vd,d_m) + dist(ve,vb,d_m) + dist(vc,vf,d_m), dist(va,ve,d_m) + dist(vd,vb,d_m) + dist(vc,vf,d_m), dist(va,vd,d_m) + dist(ve,vc,d_m) + dist(vb,vf,d_m), dist(va,ve,d_m) + dist(vd,vc,d_m) + dist(vb,vf,d_m), ] ini = soluc[:i+1] #tramo hasta a includo t_bc = soluc[i+1:j+1] #tramo bc t_de = soluc[j+1:k+1] #tramo de fin = soluc[k+1:] #tramo desde f includo d = distances[:] d.sort() min = distances.index(d[0]) #el primer caso es el original, no implica ningun cambio #por eso no hago nada, ahh aca no hay case pero lo mismo eso #se soluciona a como sigue :P if min == 1: t_bc.reverse() elif min == 2: t_de.reverse() elif min == 3: t_bc.reverse() t_de.reverse() #cuando min = 4 solo invierte las posiciones de tramos bc y ef #osea intercambo ambos tramos bc -> ef y ef -> bc elif min == 5: t_de.reverse() elif min == 6: t_bc.reverse() elif min == 7: t_bc.reverse() t_de.reverse() if min < 4: soluc = ini + t_bc + t_de + fin else: soluc = ini + t_de + t_bc + fin return soluc
def create_neighbor(solution_o, k, memory, maximum, probability, distances, invert_mode=False): """ Crea un vecino de solution perteneciente al vecindario k, pero tomando en cuenta la memoria de largo plazo """ if not invert_mode: a = 0 b = -1 else: a = 1 b = 1 random.seed() solution = solution_o[:] selected = [] alredy_selected = [0] * len(solution_o) if k == len(solution): selected = solution else: for i in range(k): found = 0 while not found: alredy_used = 0 while not alredy_used: vertex = random.choice(solution) index = solution.index(vertex) if alredy_selected[index] == 0: alredy_used = 1 vertex_a = solution[index - 1] if index == (len(solution) - 1): index = -1 vertex_p = solution[index + 1] counter_a = dist(vertex_a, vertex, memory) counter_p = dist(vertex_p, vertex, memory) if counter_a > counter_p: counter = counter_a else: counter = counter_p prob = counter * probability / maximum prob = (a - prob) * b luck = random.random() #print prob, luck, maximum if luck >= prob: selected.append(vertex) alredy_selected[index] = 1 found = 1 neighbor = solution_o[:] vertex = random.choice(selected) selected.remove(vertex) index = neighbor.index(vertex) while selected != []: vertex_b = random.choice(selected) selected.remove(vertex_b) index_b = neighbor.index(vertex_b) neighbor[index] = vertex_b neighbor[index_b] = vertex index = index_b return neighbor
def opt3_(solution=[], d_m=[]): """ Implementacion del Algoritmo 3-Optimo, optimizado en velocidad calculo """ n_vertex = len(solution) soluc = solution[:] for i in xrange(n_vertex - 5): for j in xrange(i + 2, n_vertex - 3): for k in xrange(j + 2, n_vertex - 3): va, vb = soluc[i], soluc[i + 1] vc, vd = soluc[j], soluc[j + 1] ve, vf = soluc[k], soluc[k + 1] #calculo las distancias de todas las posibles conbinaciones #muchos calculos entre las conv se repiten y para no hacerlos #de nuevo los calculo una sola ves lo que reduce a la mitad la #cantida usos de la func dist d_ab = dist(va, vb, d_m) d_ac = dist(va, vc, d_m) d_ad = dist(va, vd, d_m) d_ae = dist(va, ve, d_m) d_ef = dist(ve, vf, d_m) d_df = dist(vd, vf, d_m) d_cf = dist(vc, vf, d_m) d_vf = dist(vb, vf, d_m) d_bd = dist(vb, vd, d_m) # d_bd = d_db d_cd = dist(vc, vd, d_m) # d_cd = d_dc d_be = dist(vb, ve, d_m) # d_be = d_eb d_ce = dist(vc, ve, d_m) # d_ce = d_ec distances = [ d_ab + d_cd + d_ef, d_ac + d_bd + d_ef, d_ab + d_ce + d_df, d_ac + d_be + d_df, d_ad + d_be + d_cf, d_ae + d_bd + d_cf, d_ad + d_ce + d_vf, d_ae + d_cd + d_vf, ] ini = soluc[:i + 1] #tramo hasta a includo t_bc = soluc[i + 1:j + 1] #tramo bc t_de = soluc[j + 1:k + 1] #tramo de fin = soluc[k + 1:] #tramo desde f includo #d = distances[:] #d.sort() mini = distances.index(min(distances)) #el primer caso es el original, no implica ningun cambio #por eso no hago nada, ahh aca no hay case pero lo mismo eso #se soluciona a como sigue :P if mini == 1: t_bc.reverse() elif mini == 2: t_de.reverse() elif mini == 3: t_bc.reverse() t_de.reverse() #cuando min = 4 solo invierte las posiciones de tramos bc y ef #osea intercambo ambos tramos bc -> ef y ef -> bc elif mini == 5: t_de.reverse() elif mini == 6: t_bc.reverse() elif mini == 7: t_bc.reverse() t_de.reverse() if mini < 4: soluc = ini + t_bc + t_de + fin else: soluc = ini + t_de + t_bc + fin return soluc
def opt3(solution=[], d_m=[]): """ Implementacion del Algoritmo 3-Optimo """ n_vertex = len(solution) soluc = solution[:] for i in xrange(n_vertex - 5): for j in xrange(i + 2, n_vertex - 3): for k in xrange(j + 2, n_vertex - 3): va, vb = soluc[i], soluc[i + 1] vc, vd = soluc[j], soluc[j + 1] ve, vf = soluc[k], soluc[k + 1] #calculo las distancias de todas las posibles conbinaciones distances = [ dist(va, vb, d_m) + dist(vc, vd, d_m) + dist(ve, vf, d_m), dist(va, vc, d_m) + dist(vb, vd, d_m) + dist(ve, vf, d_m), dist(va, vb, d_m) + dist(vc, ve, d_m) + dist(vd, vf, d_m), dist(va, vc, d_m) + dist(vb, ve, d_m) + dist(vd, vf, d_m), dist(va, vd, d_m) + dist(ve, vb, d_m) + dist(vc, vf, d_m), dist(va, ve, d_m) + dist(vd, vb, d_m) + dist(vc, vf, d_m), dist(va, vd, d_m) + dist(ve, vc, d_m) + dist(vb, vf, d_m), dist(va, ve, d_m) + dist(vd, vc, d_m) + dist(vb, vf, d_m), ] ini = soluc[:i + 1] #tramo hasta a includo t_bc = soluc[i + 1:j + 1] #tramo bc t_de = soluc[j + 1:k + 1] #tramo de fin = soluc[k + 1:] #tramo desde f includo d = distances[:] d.sort() min = distances.index(d[0]) #el primer caso es el original, no implica ningun cambio #por eso no hago nada, ahh aca no hay case pero lo mismo eso #se soluciona a como sigue :P if min == 1: t_bc.reverse() elif min == 2: t_de.reverse() elif min == 3: t_bc.reverse() t_de.reverse() #cuando min = 4 solo invierte las posiciones de tramos bc y ef #osea intercambo ambos tramos bc -> ef y ef -> bc elif min == 5: t_de.reverse() elif min == 6: t_bc.reverse() elif min == 7: t_bc.reverse() t_de.reverse() if min < 4: soluc = ini + t_bc + t_de + fin else: soluc = ini + t_de + t_bc + fin return soluc