Испавил ген.алгоритм, надо только нормально по папочкам расскидать (мне сного шутить, что у меня нет папы?)
This commit is contained in:
parent
0c55d4912a
commit
82e6075f3f
@ -1,11 +1,15 @@
|
|||||||
import json
|
import json
|
||||||
from datetime import datetime, timedelta
|
from datetime import datetime, timedelta
|
||||||
import random
|
import random
|
||||||
from typing import Dict, List
|
from typing import Dict, List, Tuple, Any
|
||||||
from fastapi import FastAPI, HTTPException, Request
|
from fastapi import FastAPI, HTTPException, Request
|
||||||
|
|
||||||
def load_graph_from_request(request) -> Dict[str, Dict[str, List]]:
|
from schemas import TripRequest
|
||||||
|
|
||||||
|
|
||||||
|
def load_graph_from_request(request: TripRequest) -> Tuple[Dict[str, Dict[str, List[Any]]], str, str, List[Dict]]:
|
||||||
graph = {}
|
graph = {}
|
||||||
|
flights_data = []
|
||||||
|
|
||||||
# Загрузить данные о полетах из запроса
|
# Загрузить данные о полетах из запроса
|
||||||
flights = request.flights
|
flights = request.flights
|
||||||
@ -19,6 +23,15 @@ def load_graph_from_request(request) -> Dict[str, Dict[str, List]]:
|
|||||||
departure_time = datetime.fromisoformat(flight.departureTime)
|
departure_time = datetime.fromisoformat(flight.departureTime)
|
||||||
destination_time = datetime.fromisoformat(flight.destinationTime)
|
destination_time = datetime.fromisoformat(flight.destinationTime)
|
||||||
|
|
||||||
|
# Сохранение данных о полете для вывода
|
||||||
|
flights_data.append({
|
||||||
|
"id": flight.id,
|
||||||
|
"departurePoint": departure_point,
|
||||||
|
"destinationPoint": destination_point,
|
||||||
|
"departureTime": departure_time,
|
||||||
|
"destinationTime": destination_time
|
||||||
|
})
|
||||||
|
|
||||||
# Проверка наличия вершин в графе и их создание при необходимости
|
# Проверка наличия вершин в графе и их создание при необходимости
|
||||||
if departure_point not in graph:
|
if departure_point not in graph:
|
||||||
graph[departure_point] = {}
|
graph[departure_point] = {}
|
||||||
@ -28,9 +41,9 @@ def load_graph_from_request(request) -> Dict[str, Dict[str, List]]:
|
|||||||
# Добавление ребра в граф
|
# Добавление ребра в граф
|
||||||
graph[departure_point][destination_point] = [flight.distance, departure_time, destination_time]
|
graph[departure_point][destination_point] = [flight.distance, departure_time, destination_time]
|
||||||
|
|
||||||
return graph, start_point, end_point
|
return graph, start_point, end_point, flights_data
|
||||||
|
|
||||||
|
|
||||||
# Функция для вычисления длины и времени пути с учетом минимального интервала времени
|
|
||||||
def path_length_and_time(path, graph):
|
def path_length_and_time(path, graph):
|
||||||
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]]:
|
||||||
@ -49,8 +62,8 @@ def path_length_and_time(path, graph):
|
|||||||
end_time = graph[path[i]][path[i + 1]][2]
|
end_time = graph[path[i]][path[i + 1]][2]
|
||||||
return length, start_time, end_time
|
return length, start_time, end_time
|
||||||
|
|
||||||
# Функция для генерации начальной популяции
|
|
||||||
def generate_population(size, start, end, graph, max_attempts=100):
|
def generate_population(size, start, end, graph, max_attempts=1000):
|
||||||
population = []
|
population = []
|
||||||
for i in range(size):
|
for i in range(size):
|
||||||
attempts = 0
|
attempts = 0
|
||||||
@ -74,13 +87,12 @@ def generate_population(size, start, end, graph, max_attempts=100):
|
|||||||
attempts += 1
|
attempts += 1
|
||||||
return population
|
return population
|
||||||
|
|
||||||
# Функция для селекции родителей
|
|
||||||
def select_parents(population, graph):
|
def select_parents(population, graph):
|
||||||
sorted_population = sorted(population, key=lambda p: path_length_and_time(p, graph)[0])
|
sorted_population = sorted(population, key=lambda p: path_length_and_time(p, graph)[0])
|
||||||
return sorted_population[:len(sorted_population) // 2]
|
return sorted_population[:len(sorted_population) // 2]
|
||||||
|
|
||||||
|
|
||||||
# Функция для скрещивания (кроссинговера)
|
|
||||||
def crossover(parent1, parent2):
|
def crossover(parent1, parent2):
|
||||||
crossover_point = len(parent1) // 2
|
crossover_point = len(parent1) // 2
|
||||||
child = parent1[:crossover_point]
|
child = parent1[:crossover_point]
|
||||||
@ -90,7 +102,6 @@ def crossover(parent1, parent2):
|
|||||||
return child
|
return child
|
||||||
|
|
||||||
|
|
||||||
# Функция для мутации
|
|
||||||
def mutate(child):
|
def mutate(child):
|
||||||
if len(child) <= 2:
|
if len(child) <= 2:
|
||||||
return child # Если путь состоит из одной вершины, мутация не требуется
|
return child # Если путь состоит из одной вершины, мутация не требуется
|
||||||
@ -100,9 +111,18 @@ def mutate(child):
|
|||||||
return child
|
return child
|
||||||
|
|
||||||
|
|
||||||
# Главная функция генетического алгоритма
|
def update_best_paths(best_paths, path, graph, max_best_paths=3):
|
||||||
def genetic_algorithm(start, end, graph, population_size=100, generations=100):
|
length, _, _ = path_length_and_time(path, graph)
|
||||||
|
if path not in best_paths:
|
||||||
|
best_paths[path] = length
|
||||||
|
if len(best_paths) > max_best_paths:
|
||||||
|
worst_path = max(best_paths, key=best_paths.get)
|
||||||
|
del best_paths[worst_path]
|
||||||
|
|
||||||
|
|
||||||
|
def genetic_algorithm(start, end, graph, flights_data, population_size=100, generations=100):
|
||||||
population = generate_population(population_size, start, end, graph)
|
population = generate_population(population_size, start, end, graph)
|
||||||
|
best_paths = {} # Словарь для хранения уникальных лучших маршрутов и их длин
|
||||||
for generation in range(generations):
|
for generation in range(generations):
|
||||||
parents = select_parents(population, graph)
|
parents = select_parents(population, graph)
|
||||||
new_population = parents[:]
|
new_population = parents[:]
|
||||||
@ -112,8 +132,35 @@ def genetic_algorithm(start, end, graph, population_size=100, generations=100):
|
|||||||
child = crossover(parent1, parent2)
|
child = crossover(parent1, parent2)
|
||||||
if random.random() < 0.1: # Вероятность мутации
|
if random.random() < 0.1: # Вероятность мутации
|
||||||
child = mutate(child)
|
child = mutate(child)
|
||||||
|
if child[-1] == end:
|
||||||
new_population.append(child)
|
new_population.append(child)
|
||||||
|
update_best_paths(best_paths, tuple(child), graph)
|
||||||
population = new_population
|
population = new_population
|
||||||
best_path = min(population, key=lambda p: path_length_and_time(p, graph)[0])
|
|
||||||
best_length, start_time, end_time = path_length_and_time(best_path, graph)
|
best_paths = sorted(best_paths.items(), key=lambda item: item[1])
|
||||||
return best_path, best_length, start_time, end_time
|
top_paths = [list(path) for path, _ in best_paths[:3]]
|
||||||
|
|
||||||
|
result = []
|
||||||
|
for path in top_paths:
|
||||||
|
path_data = []
|
||||||
|
for i in range(len(path) - 1):
|
||||||
|
for flight in flights_data:
|
||||||
|
if flight['departurePoint'] == path[i] and flight['destinationPoint'] == path[i + 1]:
|
||||||
|
path_data.append({
|
||||||
|
"id": flight['id'],
|
||||||
|
"departurePoint": flight['departurePoint'],
|
||||||
|
"destinationPoint": flight['destinationPoint']
|
||||||
|
})
|
||||||
|
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
|
||||||
|
result.append({
|
||||||
|
"to": path_data,
|
||||||
|
"start_time": start_time.isoformat() if start_time else None,
|
||||||
|
"end_time": end_time.isoformat() if end_time else None,
|
||||||
|
"best_length": length
|
||||||
|
})
|
||||||
|
|
||||||
|
return result
|
||||||
|
@ -17,9 +17,11 @@ router = APIRouter(
|
|||||||
|
|
||||||
@router.post("/get_flight/")
|
@router.post("/get_flight/")
|
||||||
async def get_flight(request: TripRequest):
|
async def get_flight(request: TripRequest):
|
||||||
graph, start_point, end_point = load_graph_from_request(request)
|
graph, start_point, end_point, flights_data = load_graph_from_request(request)
|
||||||
best_path, best_length, start_time, end_time = genetic_algorithm(start_point, end_point, graph)
|
result = genetic_algorithm(start_point, end_point, graph, flights_data)
|
||||||
return best_path, best_length, start_time, end_time
|
if not result:
|
||||||
|
raise HTTPException(status_code=404, detail="No valid paths found")
|
||||||
|
return result
|
||||||
|
|
||||||
@router.get("/negative")
|
@router.get("/negative")
|
||||||
async def get_class_names() -> List[str]:
|
async def get_class_names() -> List[str]:
|
||||||
|
Loading…
x
Reference in New Issue
Block a user