def k_local_search(solution, customers, facilities, k = 5, njobs = 1): allocations = solution.copy() n_cutomers = len(customers) n_facilities = len(facilities) old_cost = total_cost(allocations, customers, facilities) pbar = trange(n_cutomers) for i in pbar: last_cost = total_cost(allocations, customers, facilities) customer = customers[i] costs = np.zeros(n_facilities) old_alloc = allocations[i] current_fac = solution[i] closest_facs = find_k_neighbors([facilities[current_fac]],facilities,k)[0] parallel = Parallel(n_jobs=njobs) delayed_func = delayed(eval_swap_values) costs = parallel( delayed_func( allocations=allocations, customers=customers, facilities=facilities, customer=i, new_facility=closest_facs[j], ) for j in range(k)) new_alloc = closest_facs[np.argmin(costs)] allocations[i] = new_alloc desc = '{:.1f} --> {:.1f} --> {:.1f}'.format( old_cost, last_cost, min(costs), ) pbar.set_description(desc) return allocations
def ex_local_search(solution, customers, facilities, njobs=1): allocations = solution.copy() n_cutomers = len(customers) n_facilities = len(facilities) old_cost = total_cost(allocations, customers, facilities) pbar = trange(n_cutomers) for i in pbar: customer = customers[i] costs = np.zeros(n_facilities) old_alloc = allocations[i] parallel = Parallel(n_jobs=njobs) delayed_func = delayed(eval_swap_values) costs = parallel( delayed_func( allocations=allocations, customers=customers, facilities=facilities, customer=i, new_facility=j, ) for j in range(n_facilities)) new_alloc = np.argmin(costs) allocations[i] = new_alloc desc = '{:.1f} --> {:.1f} --> {:.1f}'.format( old_cost, costs[old_alloc], costs[new_alloc], ) pbar.set_description(desc) return allocations
def ant_colony( customers, facilities, q=1, offset=0, evaporation=0.1, ants=100, generations=100, ): n_cust = len(customers) n_fac = len(facilities) dist = distance_matrix(customers, facilities) weights = np.ones_like(dist) best_sol = None best_cost = np.inf metrics = defaultdict(list) for gen in trange(generations): probs = weights / dist updates = np.zeros_like(dist) costs = [] for ant in range(ants): solution = ant_simulator(customers, facilities, dist, probs) cost = total_cost(solution, customers, facilities) edges = allocation2matrix(solution, n_fac) updates += edges * q / (cost - offset) costs.append(cost) if cost < best_cost: best_cost = cost best_sol = solution weights = weights * (1 - evaporation) + updates metrics["min_cost"].append(np.min(costs)) metrics["max_cost"].append(np.max(costs)) metrics["mean_cost"].append(np.mean(costs)) return best_sol, metrics
def double_trial(customers, facilities, solver, **kwargs): # First attempt solution = solver(customers, facilities, **kwargs) cost = total_cost(solution, customers, facilities) # Choosing top facilities min_fac = est_facilities(customers, facilities) sorted_facs = sorted(Counter(solution).items(), key=itemgetter(1), reverse=True) top_facs_idx = [f for f, i in sorted_facs[:min_fac]] top_facs = [facilities[f] for f in top_facs_idx] # Second Attempt solution2 = greedy_furthest(customers, top_facs, **kwargs) # Rearrange the solution solution2 = [top_facs_idx[f] for f in solution2] cost2 = total_cost(solution2, customers, facilities) if cost2 < cost: return solution2 else: return solution
def greedy_restart(customers,facilities,restarts=100,branches = 5,random_state=None): best_sol = [] best_cost = np.inf pbar = trange(restarts) for _ in pbar: pbar.set_description(f'{best_cost:.1f}') solution = iter_greedy(customers,facilities,branches,random_state) cost = total_cost(solution,customers,facilities) if cost<best_cost: best_cost = cost best_sol = solution return best_sol
def iter_greedy(customers,facilities,branches = 5,random_state=None): np.random.seed(random_state) solution = greedy_furthest(customers,facilities,pbar=False) cost = total_cost(solution, customers, facilities) for _ in range(len(facilities)): idx = np.random.choice(np.unique(solution),5) # new_facilities = [f for f in facilities if f.index!=dropped_facility] old_facilities = facilities.copy() new_sols = [] new_costs = [] for i in idx: facilities = old_facilities.copy() dropped_facility = facilities.pop(i) new_sols.append( greedy_furthest(customers,facilities,pbar=False)) new_costs.append( total_cost(new_sols[-1], customers, facilities)) if min(new_costs)<cost: i = np.argmin(new_costs) solution = new_sols[i] cost = new_costs[i] else: return [old_facilities[f].index for f in solution]
def ex_local_search(solution, customers, facilities, verbose=False): allocations = solution.copy() n_cutomers = len(customers) n_facilities = len(facilities) old_cost = total_cost(allocations, customers, facilities) pbar = trange(n_cutomers) for i in pbar: customer = customers[i] costs = np.zeros(n_facilities) old_alloc = allocations[i] for j in range(n_facilities): allocations[i] = j costs[j] = total_cost(allocations, customers, facilities) new_alloc = np.argmin(costs) allocations[i] = new_alloc if verbose: desc = '{:.1f} --> {:.1f} --> {:.1f}'.format( old_cost, costs[old_alloc], costs[new_alloc], ) pbar.set_description(desc) return allocations
def ant_colony( customers, facilities, q=1, offset=0, evaporation=.1, ants=100, generations=100, ): n_cust = len(customers) n_fac = len(facilities) dist = distance_matrix(customers, facilities) weights = np.ones_like(dist) best_sol = None best_cost = np.inf metrics = defaultdict(list) greedy_solution = double_trial( customers, facilities, greedy_furthest, p_skip=0, pbar=False, ) for gen in trange(generations): probs = weights/dist updates = np.zeros_like(dist) costs = [] for ant in range(ants): if ant==0: solution = greedy_solution.copy() else: solution = ant_simulator(customers, facilities, dist, probs) cost = total_cost(solution,customers, facilities) edges = allocation2matrix(solution, n_fac) updates += edges*q/(cost-offset) costs.append(cost) if cost<best_cost: best_cost = cost best_sol = solution weights = weights*(1-evaporation) + updates metrics['min_cost'].append(np.min(costs)) metrics['max_cost'].append(np.max(costs)) metrics['mean_cost'].append(np.mean(costs)) return best_sol, metrics
def view_solution(solution, customers, facilities, figsize=(8, 8)): loc_cust = np.array([c.location for c in customers]) loc_fac = np.array([f.location for f in facilities]) plt.figure(figsize=figsize) plt.scatter(loc_cust[:, 0], loc_cust[:, 1], marker="o", c="k", s=5) plt.scatter(loc_fac[:, 0], loc_fac[:, 1], marker="*", c="r", s=5) cost = total_cost(solution, customers, facilities) s = "" try: validate(solution, customers, facilities) except AssertionError: s = "*" plt.title( f"{len(customers)} Customers {len(facilities)} Facilities Total Cost{s} = {cost:.1f}" ) for c, f in enumerate(solution): x = [facilities[f].location.x, customers[c].location.x] y = [facilities[f].location.y, customers[c].location.y] plt.plot(x, y, "-k", alpha=0.5)
def eval_swap_values(allocations, customers, facilities, customer, new_facility): alloc = allocations.copy() alloc[customer] = new_facility return total_cost(alloc, customers, facilities)
kdtree = KDTree(y) dist, neighbors = kdtree.query(x,k) return neighbors # - from algorithms import greedy from calc import total_cost customers, facilities = load_data('fl_1000_2') len(customers),len(facilities) # sol = random_allocation(customers,facilities) sol = greedy(customers,facilities) total_cost(sol,customers,facilities) sol2 = k_local_search(sol,customers,facilities,12) sol = greedy(customers,facilities) total_cost(sol,customers,facilities) sol2 = local_search(sol,customers,facilities,True) view_solution(sol2,customers,facilities) validate(sol2,customers,facilities) # ## Constraint Programming
def solve_it(input_data): # Modify this code to run your optimization algorithm # parse the input customers, facilities = parse_input(input_data) facility_count = len(facilities) customer_count = len(customers) # Solution # Selecting the solver if facility_count > 100: mode = 6 else: mode = 5 # Applying the solver status = "FEASIBLE" if mode == 0: solution = greedy(customers, facilities) solution = ex_local_search(solution, customers, facilities, True) elif mode == 1: solution = clustering(customers, facilities) elif mode == 2: print("*** Using MIP solver ***") solution, status = cap_mip(customers, facilities, 8 * 3600) print(f'MIP Solver finished with status "{status}"') elif mode == 3: print("Double trial with greedy") solution = double_trial(customers, facilities, greedy_furthest) elif mode == 4: print("*** Using Ant Colony Optimisation ***") solution = double_trial( customers, facilities, greedy_furthest, p_skip=0, pbar=False, ) cost = total_cost(solution, customers, facilities) q = cost offset = cost * 0.75 solution, _ = ant_colony( customers, facilities, q=q, offset=offset, evaporation=0.1, ) elif mode == 5: print("*** Using Gurobi Solver ***") solution = cap_mip_gr(customers, facilities, 120) solution1 = fix_allocations(solution, customers, facilities) cost1 = total_cost(solution1, customers, facilities) solution2 = double_trial(customers, facilities, greedy_furthest) cost2 = total_cost(solution2, customers, facilities) if cost1 < cost2: solution = solution1 else: solution = solution2 elif mode == 6: print("*** Using Piecewise Gurobi Solver ***") solution1 = piecewise_mip(customers, facilities, per_grid=80) cost1 = total_cost(solution1, customers, facilities) solution2 = double_trial(customers, facilities, greedy_furthest) cost2 = total_cost(solution2, customers, facilities) if cost1 < cost2: solution = solution1 else: solution = solution2 else: solution = greedy(customers, facilities) status = "FEASIBLE" # calculate the cost of the solution obj = total_cost(solution, customers, facilities) # prepare the solution in the specified output format status_code = 1 if status == "OPTIMAL" else 0 output_data = "%.2f" % obj + " " + str(status_code) + "\n" output_data += " ".join(map(str, solution)) return output_data