def DeuxOpt(route): l = len(route) - 1 best_tuple = (0, 0) best = 2e-5 # to avoid floating errors for i in range(l - 1): pi = const.instance[route[i]] spi = const.instance[route[i + 1]] for j in range(i + 2, l - 1): pj = const.instance[route[j]] spj = const.instance[route[j + 1]] d = (utile.distance(pi, spi) + utile.distance(pj, spj)) - \ utile.distance(pi, pj) - utile.distance(spi, spj) if d > best: best_tuple = (i, j) best = d if best_tuple[0] != best_tuple[1]: cand = route.copy() cand[best_tuple[0] + 1], cand[best_tuple[1]] = cand[best_tuple[1]], cand[best_tuple[0] + 1] return cand else: return route
def compute_savings(lam, mu, nu): savings = [] for i in range(len(const.instance)-1): s = 0 for j in range(i+1, len(const.instance)-1): if (i == j): savings.append([0, (i+1, j+1)]) else: s = utile.distance(const.instance[i+1], const.instance[0]) + utile.distance(const.instance[j+1], const.instance[0]) - lam*utile.distance(const.instance[i+1], const.instance[j+1]) + mu*abs( utile.distance(const.instance[i+1], const.instance[0]) - utile.distance(const.instance[j+1], const.instance[0])) + (nu*(const.demand[i+1] + const.demand[j+1])/const.meanDemand) if s >= 0: savings.append([s, (i+1, j+1)]) savings.sort() return savings
def decross_route(route, inst): route.append(0) d = (utile.distance(inst[route[2]], inst[route[1]]) + utile.distance(inst[route[0]], inst[route[-2]]) - utile.distance(inst[route[0]], inst[route[2]]) - utile.distance(inst[route[-2]], inst[route[1]])) if d > 0: cand = route.copy() cand.remove(route[1]) cand.insert(-1, route[1]) cand.pop() return cand else: route.pop() return route
def max_depth(inst): d = 0 for i in inst: di = utile.distance(i, (0, 0)) if di > d: d = di return d
def decross_route(route): inst = const.instance route.append(0) d = (utile.distance(inst[route[2]], inst[route[1]]) + utile.distance(inst[route[0]], inst[route[-2]]) - utile.distance(inst[route[0]], inst[route[2]]) - utile.distance(inst[route[-2]], inst[route[1]])) if d > 0: # There is an improvement cand = route.copy() cand.remove(route[1]) cand.insert(-1, route[1]) cand.pop() return cand else: route.pop() return route
def cost_sol(routes, inst, mode): c = 0 for r in routes: if mode == "Float": for i in range(len(r)-1): a = inst[r[i]] b = inst[r[i+1]] c += utile.distance(a, b) c += utile.distance(inst[r[len(r)-1]], inst[r[0]]) elif mode == "Int": for i in range(len(r)-1): a = inst[r[i]] b = inst[r[i+1]] c += round(utile.distance(a, b)) c += round(utile.distance(inst[r[len(r)-1]], inst[r[0]])) return c
def compute_savings(inst, demand, lam, mu, nu): savings = [] d_bar = mean_demand(demand) for i in range(len(inst) - 1): s = 0 for j in range(i + 1, len(inst) - 1): if (i == j): savings.append([0, (i + 1, j + 1)]) else: s = utile.distance(inst[i + 1], inst[0]) + utile.distance( inst[j + 1], inst[0]) - lam * utile.distance( inst[i + 1], inst[j + 1]) + mu * abs( utile.distance(inst[i + 1], inst[0]) - utile.distance(inst[j + 1], inst[0])) + ( nu * (demand[i + 1] + demand[j + 1]) / d_bar) if s >= 0: savings.append([s, (i + 1, j + 1)]) savings.sort() return savings
def voisins(k): v = [] for i in range(len(instance)): vi = [] couples = [] for j in range(len(instance)): if i != j: vi.append([utile.distance(instance[i], instance[j]), j]) vi.sort() for l in vi: couples.append(l[1]) v.append(couples[:k]) return v
def cost_sol(solution, mode): c = 0 for r in solution: # Distances are floating numbers if mode == "Float": for i in range(len(r) - 1): a = const.instance[r[i]] b = const.instance[r[i + 1]] c += utile.distance(a, b) c += utile.distance(const.instance[r[len(r) - 1]], const.instance[r[0]]) # Distances are int elif mode == "Int": for i in range(len(r) - 1): a = const.instance[r[i]] b = const.instance[r[i + 1]] c += round(utile.distance(a, b)) c += round( utile.distance(const.instance[r[len(r) - 1]], const.instance[r[0]])) return c
def saving(i, ri, j, rj, inst): ri.append(0) rj.append(0) s = utile.distance(inst[ri[i]], inst[ri[i+1]]) s += utile.distance(inst[ri[i]], inst[ri[i-1]]) s -= utile.distance(inst[ri[i+1]], inst[ri[i-1]]) s += utile.distance(inst[rj[j]], inst[rj[j+1]]) s -= utile.distance(inst[ri[i]], inst[rj[j]]) s -= utile.distance(inst[ri[i]], inst[rj[j+1]]) ri.pop() rj.pop() return s
def depth(i, j): return max(utile.distance(i, (0, 0)), utile.distance(j, (0, 0)))
def cost(i, j, p): return utile.distance(i, j) * (1 + 0.1 * p)
def width(i, j, G): theta = m.acos(G[1] / utile.distance(G, (0, 0))) proj_i = (i[0] * m.sin(theta), i[1] * m.cos(theta)) proj_j = (j[0] * m.sin(theta), j[1] * m.cos(theta)) return abs(utile.distance(i, proj_i) - utile.distance(j, proj_j))