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': f'
{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)