На всякий сейвлю свою "трассировку". Если это чудо наконец то заработает, я абалдею. Я из за него на улицу не выхожу :(

This commit is contained in:
maksim 2024-06-11 02:35:52 +04:00
parent 48eb02fca7
commit 8bb6a784bf

View File

@ -1,5 +1,5 @@
import json import json
from datetime import datetime, timedelta from datetime import datetime, timedelta, date
import random import random
from typing import Dict, List, Tuple, Any from typing import Dict, List, Tuple, Any
from fastapi import FastAPI, HTTPException, Request from fastapi import FastAPI, HTTPException, Request
@ -7,7 +7,9 @@ from fastapi import FastAPI, HTTPException, Request
from schemas import TripRequest from schemas import TripRequest
def load_graph_from_request(request: TripRequest) -> Tuple[Dict[str, Dict[str, List[Any]]], str, str, List[Dict]]: def load_graph_from_request(request: TripRequest) -> tuple[
dict[str, dict[Any, Any]], dict[str, dict[Any, Any]], str, str, list[dict[str, datetime | str | int]], list[
dict[str, datetime | str | int]], date, date | None]:
graphTo = {} graphTo = {}
flightsDataTo = [] flightsDataTo = []
graphBack = {} graphBack = {}
@ -73,10 +75,11 @@ def load_graph_from_request(request: TripRequest) -> Tuple[Dict[str, Dict[str, L
# Добавление ребра в граф # Добавление ребра в граф
graphBack[departure_point][destination_point] = [flight.distance, departure_time, destination_time] graphBack[departure_point][destination_point] = [flight.distance, departure_time, destination_time]
print(graphTo)
return graphTo,graphBack, start_point, end_point, flightsDataTo, flightsDataBack, departure_date, departure_date_return return graphTo,graphBack, start_point, end_point, flightsDataTo, flightsDataBack, departure_date, departure_date_return
def path_length_and_time(path, graph): def path_length_and_time(path, graph, departure_date):
length = 0 length = 0
if path[0] not in graph or path[1] not in graph[path[0]]: if path[0] not in graph or path[1] not in graph[path[0]]:
return float('inf'), None, None return float('inf'), None, None
@ -87,11 +90,21 @@ def path_length_and_time(path, graph):
for i in range(len(path) - 1): for i in range(len(path) - 1):
if path[i] not in graph or path[i + 1] not in graph[path[i]]: if path[i] not in graph or path[i + 1] not in graph[path[i]]:
return float('inf'), start_time, end_time return float('inf'), start_time, end_time
if departure_date != start_time.date():
return float('inf'), start_time, end_time
if i > 0:
print("Start time:", start_time)
print("graph date:", graph[path[i]][path[i + 1]][1])
if start_time + timedelta(minutes=180) > graph[path[i]][path[i + 1]][1]:
print("Departure date and start time date do not match")
return float('inf'), start_time, end_time
length += graph[path[i]][path[i + 1]][0] length += graph[path[i]][path[i + 1]][0]
if i > 0: # Пропуск первой вершины
if end_time + timedelta(minutes=180) > graph[path[i]][path[i + 1]][1]:
return float('inf'), start_time, end_time # Неприемлемый путь
end_time = graph[path[i]][path[i + 1]][2] end_time = graph[path[i]][path[i + 1]][2]
start_time = end_time
return length, start_time, end_time return length, start_time, end_time
@ -119,10 +132,9 @@ def generate_population(size, start, end, graph, max_attempts=100):
attempts += 1 attempts += 1
return population return population
def select_parents(population, graph, departure_date):
def select_parents(population, graph): sorted_population = sorted(population, key=lambda p: path_length_and_time(p, graph, departure_date)[0])
sorted_population = sorted(population, key=lambda p: path_length_and_time(p, graph)[0]) valid_parents = [p for p in sorted_population if path_length_and_time(p, graph, departure_date)[0] != float('inf')]
valid_parents = [p for p in sorted_population if path_length_and_time(p, graph)[0] != float('inf')]
return valid_parents[:len(valid_parents) // 2] return valid_parents[:len(valid_parents) // 2]
@ -144,20 +156,19 @@ def mutate(child):
return child return child
def update_best_paths(best_paths, path, graph, max_best_paths=10): def update_best_paths(best_paths, path, max_best_paths=10):
length, _, _ = path_length_and_time(path, graph)
if path not in best_paths: if path not in best_paths:
best_paths[path] = length best_paths[path] = None
if len(best_paths) > max_best_paths: if len(best_paths) > max_best_paths:
worst_path = max(best_paths, key=best_paths.get) worst_path = max(best_paths, key=best_paths.get)
del best_paths[worst_path] del best_paths[worst_path]
def genetic_algorithm(start, end, graph, flights_data, type, departure_date, population_size=2000, generations=100): def genetic_algorithm(start, end, graph, flights_data, type, departure_date, population_size=5, generations=5):
population = generate_population(population_size, start, end, graph) population = generate_population(population_size, start, end, graph)
best_paths = {} # Словарь для хранения уникальных лучших маршрутов и их длин best_paths = {} # Словарь для хранения уникальных лучших маршрутов и их длин
for generation in range(generations): for generation in range(generations):
parents = select_parents(population, graph) parents = select_parents(population, graph, departure_date)
# Если не удалось выбрать родителей, завершить алгоритм # Если не удалось выбрать родителей, завершить алгоритм
if not parents: if not parents:
@ -172,7 +183,7 @@ def genetic_algorithm(start, end, graph, flights_data, type, departure_date, pop
child = mutate(child) child = mutate(child)
if child[-1] == end: if child[-1] == end:
new_population.append(child) new_population.append(child)
update_best_paths(best_paths, tuple(child), graph) update_best_paths(best_paths, tuple(child))
population = new_population population = new_population
best_paths = sorted(best_paths.items(), key=lambda item: item[1]) best_paths = sorted(best_paths.items(), key=lambda item: item[1])
@ -190,12 +201,6 @@ def genetic_algorithm(start, end, graph, flights_data, type, departure_date, pop
"destinationPoint": flight['destinationPoint'] "destinationPoint": flight['destinationPoint']
}) })
break break
length, start_time, end_time = path_length_and_time(path, graph)
# Проверка на корректность длины пути и времени
if length == float('inf') or start_time is None or end_time is None:
continue
if datetime(start_time.year, start_time.month, start_time.day).date() != departure_date:
continue
result.append({ result.append({
type: path_data, type: path_data,
}) })