75 lines
2.6 KiB
Python
75 lines
2.6 KiB
Python
from huey.contrib.djhuey import task
|
|
import operator
|
|
from django.template.loader import render_to_string
|
|
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, progress, result=None):
|
|
channel_layer = get_channel_layer()
|
|
async_to_sync(channel_layer.group_send)(
|
|
group_name,
|
|
{
|
|
'type': 'channel_message',
|
|
'message': render_to_string('components/tasks/update.html', {
|
|
'progress': progress,
|
|
'result': result,
|
|
}),
|
|
}
|
|
)
|
|
|
|
@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, shortest_route)
|
|
return shortest_route
|
|
|
|
return calculate_shortest_route(distances)
|