def simulated_annealing(sol, nodes, vehicles, old_z, temp0=25, r=0.65, tempf=10**-3): min_neighbor = copy.deepcopy(sol) temp = temp0 while temp > tempf: neighborhood = two_opt(min_neighbor, nodes, 0, 0.5) min_z = np.inf for neighbor in neighborhood: z = of(vehicles, nodes, neighbor) if z < min_z: min_neighbor = neighbor min_z = z delta = min_z - old_z if delta < 0 or np.random.rand() < np.exp(-delta / temp): s = copy.deepcopy(min_neighbor) old_z = min_z temp *= r s = two_opt(s, nodes) z = of(vehicles, nodes, s) return s, z
def one_one_exchange(sol, nodes, vehicles, old_z): new_sol = copy.deepcopy(sol) prev_sol = copy.deepcopy(sol) for r1 in range(len(new_sol) - 1): for r2 in range(r1, len(new_sol)): for i in range(1, len(new_sol[r1]) - 1): for j in range(1, len(new_sol[r2]) - 1): new_sol[r1][i], new_sol[r2][j] = new_sol[r2][j], new_sol[ r1][i] nodes['assigned'][i][1], nodes['assigned'][j][1] = nodes[ 'assigned'][j][1], nodes['assigned'][i][1] if check_route(new_sol[r1], nodes, vehicles['capacity'][nodes['assigned'][i][1]]) and \ check_route(new_sol[r2], nodes, vehicles['capacity'][nodes['assigned'][j][1]]): new_z = of(vehicles, nodes, new_sol) if new_z - old_z < 0: prev_sol = copy.deepcopy(new_sol) old_z = new_z else: new_sol[r1][i], new_sol[r2][j] = new_sol[r2][ j], new_sol[r1][i] nodes['assigned'][i][1], nodes['assigned'][j][1] = nodes['assigned'][j][1], \ nodes['assigned'][i][1] else: new_sol[r1][i], new_sol[r2][j] = new_sol[r2][ j], new_sol[r1][i] nodes['assigned'][i][1], nodes['assigned'][j][1] = nodes['assigned'][j][1], \ nodes['assigned'][i][1] return prev_sol, old_z
def vnd(sol, nodes, vehicles, old_z, l=5): j = 0 new_sol = copy.deepcopy(sol) z = old_z while j <= l: if j % 3 == 0: new_sol = two_opt(new_sol, nodes) z = of(vehicles, nodes, new_sol) elif j % 3 == 1: new_sol, z = one_one_exchange(new_sol, nodes, vehicles, z) elif j % 3 == 2: new_sol, z = move(new_sol, nodes, vehicles, z) j += 1 return new_sol, z
def lower_bound_vrp(nodes, vehicles): min_cap = max(vehicles['capacity']) max_vel = min(vehicles['velocity']) lb_routes = [] ideal_vehicle = {'index': [0], 'num_vehicles': [float('Inf')], 'capacity': [min_cap], 'velocity': [max_vel]} for node in nodes['index']: lb_routes.append([node]) nodes['assigned'] = [] for i in range(len(nodes['index'])): nodes['assigned'].append([1, 0]) sol_lb = of(ideal_vehicle, nodes, lb_routes) return sol_lb
def swap(sol, nodes, vehicles, old_z): new_sol = copy.deepcopy(sol) prev_sol = copy.deepcopy(sol) for r in range(len(new_sol)): route = new_sol[r] n = len(route) for i in range(1, n - 2): for j in range(i + 1, n - 1): route[i], route[j] = route[i], route[j] new_z = of(vehicles, nodes, new_sol) if new_z < old_z: route_prev = prev_sol[r] route_prev[i], route_prev[j] = route_prev[j], route_prev[i] old_z = new_z else: route[i], route[j] = route[i], route[j] return prev_sol, old_z
def move(sol, nodes, vehicles, old_z): new_sol = copy.deepcopy(sol) prev_sol = copy.deepcopy(sol) for r in range(len(new_sol)): route = new_sol[r] n = len(route) if len(route) > 4: for i in range(1, n - 2): for j in range(i + 1, n - 1): route.insert(j, route.pop(i)) z = of(vehicles, nodes, new_sol) if z < old_z: route_prev = prev_sol[r] route_prev.insert(j, route_prev.pop(i)) old_z = z else: route.insert(j, route.pop(i)) return prev_sol, old_z
from sweepHCCVRP import sweep, of from lowerBoundHCCVRP import lower_bound_vrp from ioData import read_data, print_routes for i in range(1, 22): # Read data set vehicles, nodes = read_data(i) # Calculate lower bound lb = lower_bound_vrp(nodes, vehicles) # Constructive Algorithm sol = sweep(vehicles, nodes) # Calculate Objective Function z = of(vehicles, nodes, sol) # Output data print_routes(i, vehicles, nodes, sol)