def best_objective(solution): routes = list(itertools.permutations(solution)) best_solution = solution for route in routes: if f(route) < f(best_solution) and check_solution(route): best_solution = route return best_solution
def fill_vehicles(solution): a = take_from_dummy_place_first_suitable(solution) b = fill_vehicle(solution) if f(a) < f(b): return a else: return b
def swap(solution): calls = get_calls_including_zeroes(solution) vehicle = random.randrange(1, x.vehicles) route = calls[vehicle] it = 0 while not route or len(route) <= 3: vehicle = random.randrange(1, x.vehicles) route = calls[vehicle] if it == 25: return solution else: it += 1 new_route = route new_calls = calls new_calls[vehicle] = new_route it = 0 while f(calls_to_solution(new_calls)) > f(solution) and not check_solution( calls_to_solution(new_calls)): rand1 = random.randrange(0, len(new_route)) rand2 = random.randrange(0, len(new_route)) if rand1 == 0 or rand2 == 0 or (rand1 == rand2): continue new_route[rand1], new_route[rand2] = new_route[rand2], new_route[rand1] new_calls[vehicle] = new_route if it == 100: return solution else: it += 1 c = calls_to_solution(new_calls) return c
def simulated_annealing_new(init_solution): best_solution = init_solution incumbent = init_solution t0 = 38 t = t0 a = 0.998 p1 = 0.25 p2 = 0.5 clear_br() for i in range(1, 10000): progress_bar(i) rand = random.uniform(0, 1) if rand < p1: new_solution = one_reinsert_most_expensive_from_dummy(incumbent) elif rand < p1 + p2: new_solution = obo.fill_vehicles(incumbent) else: new_solution = best_route(incumbent) delta_e = f(new_solution) - f(incumbent) rand_ii = random.uniform(0, 1) p = math.e * (-delta_e / t) if check_solution(new_solution) and delta_e < 0: incumbent = new_solution if f(incumbent) < f(best_solution): best_solution = incumbent elif check_solution(new_solution) and rand_ii < p: incumbent = new_solution t = a * t return best_solution
def new_simulated_annealing_initializer(init_solution, times, runtime): print("--- Running New Simulated Annealing Algorithm ---") cost_init = f(init_solution) print("\nInitial solution:", init_solution) print("\nCost of initial solution:", cost_init, "\n") total_cost = 0 best_solution = init_solution best_objective = cost_init best_runtime = sys.maxsize start = dt.datetime.now() for i in range(times): print("Run %d of %d. \n" % (i + 1, times)) iter_start_time = dt.datetime.now() new_solution = simulated_annealing_new(init_solution, runtime) cost = f(new_solution) if cost < best_objective: best_objective = cost best_solution = new_solution total_cost += cost iter_end_time = dt.datetime.now() iter_total_runtime = (iter_end_time - iter_start_time).total_seconds() if iter_total_runtime < best_runtime: best_runtime = iter_total_runtime p(start, total_cost, times, cost_init, best_objective, best_runtime, best_solution) print("--- End of New Simulated Annealing Algorithm ---")
def simulated_annealing(init_solution): best_solution = init_solution incumbent = init_solution t0 = 100 t = t0 a = 0.998 p1, p2 = 0.33, 0.33 for i in range(1, 10000): rand = random.uniform(0, 1) if rand < p1: new_solution = two_exchange(incumbent) elif rand < p1 + p2: new_solution = three_exchange(incumbent) else: new_solution = one_reinsert(incumbent) delta_e = f(new_solution)-f(incumbent) rand_ii = random.uniform(0, 1) p = math.e * (-delta_e/t) if check_solution(new_solution) and delta_e < 0: incumbent = new_solution if f(incumbent) < f(best_solution): best_solution = incumbent elif check_solution(new_solution) and rand_ii < p: incumbent = new_solution t = a * t return best_solution
def random_solution_initializer(init_solution, times): print("--- Running Random Search Algorithm ---") cost_init = f(init_solution) print("\nInitial solution:", init_solution) print("\nCost of initial solution:", cost_init) start = dt.datetime.now() total_cost = 0 best_solution = init_solution best_objective = cost_init best_runtime = sys.maxsize for _ in range(times): iter_start_time = dt.datetime.now() new_solution = random_search(init_solution) cost = f(new_solution) if cost < best_objective: best_objective = cost best_solution = new_solution total_cost += cost iter_end_time = dt.datetime.now() iter_total_runtime = (iter_end_time - iter_start_time).total_seconds() if iter_total_runtime < best_runtime: best_runtime = iter_total_runtime p(start, total_cost, times, cost_init, best_objective, best_runtime, best_solution) print("--- End of Random Search Algorithm ---")
def random_search(init_solution): best_solution = init_solution for _ in range(1, 10000): current = random_solution() if check_solution(current) and f(current) < f(best_solution): best_solution = current return best_solution
def pseudo_random_one_reinsert(solution): best_solution = solution best = f(solution) for _ in range(15): new_sol = fast_reinsert(solution) f_new = f(new_sol) score = f_new if f_new < best: best_solution = new_sol best = score return best_solution
def pseudo_random_three_exchange(solution): best_solution = solution best = f(solution) for _ in range(15): new_sol = three_exchange(solution) f_new = f(new_sol) score = f_new if f_new < best: best_solution = new_sol best = score return best_solution
def alns_init(init_solution, times, runtime): print("--- Running Adaptive Large Neighborhood Search ---") cost_init = f(init_solution) print("\nInitial solution:", init_solution) print("\nCost of initial solution:", cost_init, "\n") print( "######################################################################\n" ) total_cost = 0 best_solution = init_solution best_objective = cost_init worst_objective = 0 best_runtime = 100000 worst_runtime = 0 start = dt.datetime.now() for i in range(times): print("Run %d of %d. \n" % (i + 1, times)) iter_start_time = dt.datetime.now() new_solution = adaptive_large_neighborhood_search( init_solution, runtime) cost = f(new_solution) if cost < best_objective: best_objective = cost best_solution = new_solution if cost > worst_objective: worst_objective = cost total_cost += cost iter_end_time = dt.datetime.now() iter_total_runtime = (iter_end_time - iter_start_time).total_seconds() if times > 1: print("Stats for run %d:\n" % (i + 1)) print("Objective: %.2d" % round(cost, 0)) improvement = 100 * (cost_init - cost) / cost_init print("Improvement: %.2f" % round(improvement, 2)) print("Runtime: " + "%.6f" % iter_total_runtime + " seconds\n") if iter_total_runtime < best_runtime: best_runtime = iter_total_runtime if iter_total_runtime > worst_runtime: worst_runtime = iter_total_runtime print( "######################################################################\n" ) print("Stats for Call %d:\n" % x.calls) p(start, total_cost, times, cost_init, best_objective, worst_objective, best_runtime, worst_runtime, best_solution) print("--- End of Adaptive Large Neighborhood Search ---")
def local_search(init_solution): best_solution = init_solution p1, p2 = 0.33, 0.33 for i in range(1, 10000): rand = random.uniform(0, 1) if rand < p1: current = two_exchange(best_solution) elif rand < p1 + p2: current = three_exchange(best_solution) else: current = one_reinsert(best_solution) if check_solution(current) and f(current) < f(best_solution): best_solution = current return best_solution
def try_for_best(solution): # print("Starting solution:", solution) new_solutions = [] calls = get_calls_including_zeroes(solution) dummy_calls = calls[x.vehicles + 1] # print("Dummy calls:", dummy_calls) most_expensive_calls = get_most_expensive_calls(solution) most_expensive_call = 0 for key in most_expensive_calls.keys(): # print("Key:", key) if key in dummy_calls: most_expensive_call = key break if most_expensive_call == 0: return solution # print(most_expensive_call) dummy_most_expensive_removed = [i for i in dummy_calls if i != most_expensive_call] calls[x.vehicles + 1] = dummy_most_expensive_removed # print(dummy_most_expensive_removed) vehicle = random.randrange(1, len(x.vehicles_dict)) # print("Vehicle", vehicle) new_calls = copy.deepcopy(calls) new_calls[vehicle].insert(0, most_expensive_call) if len(calls[vehicle]) > 1: for index in range(len(calls[vehicle])): # print("Calls in loop:", calls) newnew_calls = copy.deepcopy(new_calls) newnew_calls[vehicle].insert(index + 1, most_expensive_call) new_solutions.append(calls_to_solution(newnew_calls)) # print("New calls in loop:", newnew_calls) else: # print("Calls:", calls) new_calls[vehicle].insert(0, most_expensive_call) # print("New calls:", new_calls) new_solutions.append(calls_to_solution(new_calls)) best_solution = solution # print("New solutions:", new_solutions) for sol in new_solutions: if f(sol) < f(best_solution) or random.uniform(0, 1) < 0.25: # print("Chosen solution:", sol) return sol return solution
def tabu_shuffle(solution): calls = get_calls_including_zeroes(solution) rand_vehicle = random.randrange(1, x.vehicles) if len(calls[rand_vehicle]) < 2: return solution current = solution new_sol = swingers(solution) # print("New sol:", new_sol) if f(new_sol) < f(current): current = new_sol elif check_solution(new_sol) and random.uniform(0, 1) < 0.33: current = new_sol return current
def operator(op, curr_sol, curr_weights, index, usage, variable, f_s, f_best): current = op(curr_sol) f_curr = f(current) curr_weights = update_weights(current, curr_weights, index, f_curr, f_s, f_best) usage[index] += 1 variable += 1 return [current, curr_weights, usage, variable, f_curr]
def try_for_best(solution): if solution in tested_solutions: return solution tested_solutions.append(solution) new_solutions = [] calls = get_calls_including_zeroes(solution) dummy_calls = calls[x.vehicles + 1] most_expensive_calls = most_expensive_dummy(solution) mec = list(most_expensive_calls.keys()) most_expensive_call = mec.pop(0) calls_wo_dummy = copy.deepcopy(calls) calls_wo_dummy.pop(x.vehicles + 1) sample = random.sample(calls_wo_dummy.keys(), 2) dummy_most_expensive_removed = [i for i in dummy_calls if i != most_expensive_call] calls[x.vehicles + 1] = dummy_most_expensive_removed for vehicle in sample: new_calls = copy.deepcopy(calls) new_calls[vehicle].insert(0, most_expensive_call) if len(calls[vehicle]) > 1: for index in range(len(calls[vehicle])): # print("Calls in loop:", calls) newnew_calls = copy.deepcopy(new_calls) newnew_calls[vehicle].insert(index + 1, most_expensive_call) if calls_to_solution(newnew_calls) in tested_solutions: continue else: new_solutions.append(calls_to_solution(newnew_calls)) tested_solutions.append(calls_to_solution(newnew_calls)) # print("New calls in loop:", newnew_calls) else: # print("Calls:", calls) new_calls[vehicle].insert(0, most_expensive_call) # print("New calls:", new_calls) new_solutions.append(calls_to_solution(new_calls)) tested_solutions.append(calls_to_solution(new_calls)) best_solution = solution for sol in new_solutions: if f(sol) < f(best_solution) and check_solution(sol): return sol return solution
def best_route(solution): calls = route_planner(solution) vehicle = random.randrange(1, x.vehicles + 1) if not calls[vehicle]: return solution route = calls[vehicle] global tested_solutions if route in tested_solutions: return solution tested_solutions.append(route) # if len(route) > 7: # return solution all_combs = list(set(itertools.permutations(route))) nl = [list(row) for row in all_combs] best_solution = solution for c in nl: rt = copy.deepcopy(get_calls_including_zeroes(solution)) rt[vehicle] = c rt[vehicle].append(0) # print(calls_to_solution(rt)) if f(calls_to_solution(rt)) < f(best_solution): best_solution = calls_to_solution(rt) return best_solution
def adaptive_large_neighborhood_search(init_solution, runtime): s = init_solution s_cost = f(s) best = init_solution best_cost = f(best) global found_solutions found_solutions.clear() operators = ops() break_its = its_without_updates_break() curr_weights = [] usage = [] total_usage = [] for i in range(len(operators)): curr_weights.append(1.0) usage.append(0) total_usage.append(0) prev_weights = curr_weights.copy() end = time.time() + runtime its_since_upd, iteration, diversification_its = 0, 0, 0 par = parameters() t0 = par[0] t = t0 a = par[1] weights_refresh_rate = par[2] diversification_rate = par[3] tot_its = 0 while time.time() < end: if its_since_upd == break_its: s = init_solution s_cost = f(s) tot_its += 1 t0 = par[0] t = t0 its_since_upd = 0 curr_weights.clear() usage.clear() found_solutions.clear() for i in range(len(operators)): curr_weights.append(1.0) usage.append(0) prev_weights = curr_weights.copy() if its_since_upd > diversification_rate: current = obo.move_to_dummy(s) diversification_its += 1 else: current = s if iteration % weights_refresh_rate == 0 and iteration > 0: prev_weights = curr_weights curr_weights = regulate_weights(prev_weights, curr_weights, usage) for i in range(len(operators)): usage[i] = 0 chosen_op = random.choices(operators, prev_weights, k=1).pop(0) if chosen_op == "take_from_dummy_place_first_suitable": oc = obo.take_from_dummy_place_first_suitable elif chosen_op == "swap": oc = swap elif chosen_op == "triple_swap": oc = triple_swap elif chosen_op == "one_reinsert_from_dummy": oc = one_reinsert_from_dummy elif chosen_op == "one_reinsert_most_expensive_call": oc = one_reinsert_most_expensive_call elif chosen_op == "most_expensive_one_reinsert_from_dummy": oc = most_expensive_one_reinsert_from_dummy elif chosen_op == "move_vehicle_to_dummy": oc = obo.move_vehicle_to_dummy elif chosen_op == "move_to_next_valid_vehicle": oc = obo.move_to_next_valid_vehicle elif chosen_op == "change_route": oc = obo.change_route elif chosen_op == "shuffle": oc = shuffle elif chosen_op == "x_one_reinserts_inside_vehicle": oc = x_one_reinserts_inside_vehicle elif chosen_op == "x_one_reinserts_inside_vehicle_dsc": oc = x_one_reinserts_inside_vehicle_dsc op_index = operators.index(chosen_op) op = operator(oc, current, curr_weights, op_index, usage, total_usage[op_index], s_cost, best_cost) current, curr_weights, usage, total_usage[op_index], f_curr = op[ 0], op[1], op[2], op[3], op[4] delta_e = f_curr - s_cost rand_ii = random.uniform(0, 1) p = math.e * (-delta_e / t) if check_solution(current) and delta_e < 0: s = current s_cost = f(s) its_since_upd = 0 if s_cost < best_cost: best = s.copy() best_cost = f(best) elif check_solution(current) and rand_ii < p: s = current its_since_upd = 0 else: its_since_upd += 1 t = a * t iteration += 1 usage_dict = {} for i in range(len(operators)): usage_dict[operators[i]] = total_usage[i] u_d = { k: v for k, v in sorted( usage_dict.items(), key=lambda item: item[1], reverse=True) } for key, value in u_d.items(): print("%d: %s" % (value, key)) print("\n%d: diversification" % diversification_its) print("\nTotal iterations:", (iteration + diversification_its), "\n") return best
def weighted_one_insert(solution): new_sol = one_reinsert(solution) if check_solution(new_sol) and f(new_sol) < f(solution): return new_sol return solution