from huey.contrib.djhuey import task import operator from itertools import permutations from collections import Counter from functools import reduce from math import factorial from channels.layers import get_channel_layer from asgiref.sync import async_to_sync def render_progress_bar(group_name, message): channel_layer = get_channel_layer() async_to_sync(channel_layer.group_send)( group_name, { 'type': 'channel_message', 'message': message } ) @task() def calculate_min_distance(group_name): # Distance matrix between cities distances = [ [0, 29, 20, 21, 16, 31, 100, 12, 5, 78], [29, 0, 15, 29, 28, 40, 72, 21, 29, 41], [20, 15, 0, 15, 14, 25, 81, 9, 23, 27], [21, 29, 15, 0, 4, 12, 92, 12, 25, 13], [16, 28, 14, 4, 0, 16, 94, 9, 20, 16], [31, 40, 25, 12, 16, 0, 95, 24, 36, 3], [100, 72, 81, 92, 94, 95, 0, 90, 101, 99], [12, 21, 9, 12, 9, 24, 90, 0, 15, 25], [5, 29, 23, 25, 20, 36, 101, 15, 0, 35], [78, 41, 27, 13, 16, 3, 99, 25, 35, 0], ] num_cities = len(distances) cities = list(range(num_cities)) def count_permutations(sequence): total = factorial(len(sequence)) duplicates = Counter(sequence).values() divisor = reduce(operator.mul, (factorial(v) for v in duplicates), 1) return total / divisor def calculate_shortest_route(distances): shortest_route = float("inf") city_count = 0 # Calculate all possible permutations of cities (routes) total_permutations = count_permutations(cities) percentaje = 0 for perm in permutations(cities): # Send progress to the group temp_percentaje = int(city_count / total_permutations * 100) if temp_percentaje != percentaje: percentaje = temp_percentaje render_progress_bar(group_name, percentaje) city_count += 1 # Calculate the distance of the route route_distance = 0 for i in range(num_cities - 1): route_distance += distances[perm[i]][perm[i + 1]] route_distance += distances[perm[-1]][perm[0]] # Back to the start city shortest_route = min(shortest_route, route_distance) render_progress_bar(group_name, 100) return shortest_route return calculate_shortest_route(distances)