FT: Mejora del modelo añadiendo control de tráfico además de demanda
This commit is contained in:
20
src/app.py
20
src/app.py
@@ -166,6 +166,7 @@ def recommend_gruas():
|
||||
- dow: día de la semana (0-6, requerido)
|
||||
- hour: hora del día (0-23, requerido)
|
||||
- k: número de grúas (opcional, default=2)
|
||||
- traffic: nivel de tráfico 1=bajo, 2=medio, 3=alto (opcional, default=1)
|
||||
- optimize: si es True, encuentra k óptimo (opcional, default=False)
|
||||
- min_gruas: mínimo de grúas para optimización (opcional, default=1)
|
||||
- max_gruas: máximo de grúas para optimización (opcional, default=10)
|
||||
@@ -178,6 +179,7 @@ def recommend_gruas():
|
||||
hour = int(request.args["hour"])
|
||||
|
||||
k = request.args.get("k", default=2, type=int)
|
||||
traffic = request.args.get("traffic", default=1, type=int)
|
||||
optimize = request.args.get("optimize", default="false").lower() == "true"
|
||||
min_gruas = request.args.get("min_gruas", default=1, type=int)
|
||||
max_gruas = request.args.get("max_gruas", default=10, type=int)
|
||||
@@ -190,6 +192,8 @@ def recommend_gruas():
|
||||
return jsonify({"error": "hour debe estar entre 0 y 23"}), 400
|
||||
if k < 1:
|
||||
return jsonify({"error": "k debe ser al menos 1"}), 400
|
||||
if not (1 <= traffic <= 3):
|
||||
return jsonify({"error": "traffic debe estar entre 1 (bajo) y 3 (alto)"}), 400
|
||||
|
||||
# Obtener modelos
|
||||
demand_model = model_manager.get_model("demand")
|
||||
@@ -201,10 +205,10 @@ def recommend_gruas():
|
||||
}), 500
|
||||
|
||||
if DEBUG_MODE:
|
||||
print(f"DEBUG: Building prediction grid for week={week}, dow={dow}, hour={hour}")
|
||||
print(f"DEBUG: Building prediction grid for week={week}, dow={dow}, hour={hour}, traffic={traffic}")
|
||||
|
||||
# Construir grilla de predicciones
|
||||
df = build_prediction_grid(week, dow, hour, demand_model, nulo_model)
|
||||
df = build_prediction_grid(week, dow, hour, demand_model, nulo_model, traffic_level=traffic)
|
||||
|
||||
if df.empty:
|
||||
return jsonify({
|
||||
@@ -234,6 +238,10 @@ def recommend_gruas():
|
||||
"semana": week,
|
||||
"dia_semana": dow,
|
||||
"hora": hour,
|
||||
"trafico": {
|
||||
"nivel": traffic,
|
||||
"descripcion": {1: "bajo", 2: "medio", 3: "alto"}.get(traffic, "desconocido")
|
||||
},
|
||||
"optimizacion": {
|
||||
"k_optimo": result['optimal_k'],
|
||||
"porcentaje_cobertura": result['coverage_percentage'],
|
||||
@@ -263,7 +271,11 @@ def recommend_gruas():
|
||||
"hora": hour,
|
||||
"parametros": {
|
||||
"k": k,
|
||||
"optimizacion": optimize
|
||||
"optimizacion": optimize,
|
||||
"trafico": {
|
||||
"nivel": traffic,
|
||||
"descripcion": {1: "bajo", 2: "medio", 3: "alto"}.get(traffic, "desconocido")
|
||||
}
|
||||
},
|
||||
"h3_recomendados": result['selected'],
|
||||
"estadisticas": result.get('statistics', []),
|
||||
@@ -505,7 +517,7 @@ def index():
|
||||
"ruta": "/recommend",
|
||||
"metodo": "GET",
|
||||
"descripcion": "Recomendar ubicaciones para grúas",
|
||||
"parametros": "week, dow, hour (requeridos), k, optimize, min_gruas, max_gruas, target_coverage (opcionales)"
|
||||
"parametros": "week, dow, hour (requeridos), k, traffic (1-3), optimize, min_gruas, max_gruas, target_coverage (opcionales)"
|
||||
},
|
||||
{
|
||||
"ruta": "/coverage/radius",
|
||||
|
||||
@@ -3,22 +3,58 @@ import pandas as pd
|
||||
from typing import List, Set, Dict, Tuple
|
||||
import numpy as np
|
||||
|
||||
def coverage_radius(expected_demand: float) -> int:
|
||||
def get_max_radius_by_traffic(traffic_level: int) -> int:
|
||||
"""
|
||||
Determina el radio de cobertura según la demanda esperada, como medimos anteriormente
|
||||
Determina el radio máximo de cobertura según el nivel de tráfico.
|
||||
|
||||
Nivel demanda | Radio H3
|
||||
Nivel tráfico | Radio H3 máximo
|
||||
---------------|----------------
|
||||
Bajo (1) | 18
|
||||
Medio (2) | 12
|
||||
Alto (3) | 9
|
||||
|
||||
Args:
|
||||
traffic_level: Nivel de tráfico (1=bajo, 2=medio, 3=alto)
|
||||
|
||||
Returns:
|
||||
Radio máximo en hexágonos H3
|
||||
"""
|
||||
traffic_limits = {
|
||||
1: 18, # Tráfico bajo
|
||||
2: 12, # Tráfico medio
|
||||
3: 9 # Tráfico alto
|
||||
}
|
||||
return traffic_limits.get(traffic_level, 18) # Default a tráfico bajo
|
||||
|
||||
def coverage_radius(expected_demand: float, traffic_level: int = 1) -> int:
|
||||
"""
|
||||
Determina el radio de cobertura según la demanda esperada y el nivel de tráfico.
|
||||
El radio final es el mínimo entre el radio calculado por demanda y el límite de tráfico.
|
||||
|
||||
Nivel demanda | Radio H3 base
|
||||
---------------|----------
|
||||
baja (<2) | 18
|
||||
media (2-5) | 12
|
||||
alta (≥5) | 6
|
||||
|
||||
Args:
|
||||
expected_demand: Demanda esperada
|
||||
traffic_level: Nivel de tráfico (1=bajo, 2=medio, 3=alto)
|
||||
|
||||
Returns:
|
||||
Radio de cobertura ajustado por tráfico
|
||||
"""
|
||||
# Radio base según demanda
|
||||
if expected_demand < 2:
|
||||
return 18
|
||||
base_radius = 18
|
||||
elif expected_demand < 5:
|
||||
return 12
|
||||
base_radius = 12
|
||||
else:
|
||||
return 6
|
||||
base_radius = 6
|
||||
|
||||
# Aplicar restricción de tráfico
|
||||
max_radius = get_max_radius_by_traffic(traffic_level)
|
||||
return min(base_radius, max_radius)
|
||||
|
||||
def get_coverage_weight(expected_demand: float) -> float:
|
||||
"""
|
||||
@@ -82,12 +118,14 @@ def calculate_coverage_score(cell: str, radius: int, df: pd.DataFrame) -> float:
|
||||
return total_risk * (1 + 0.1 * demand_weight)
|
||||
|
||||
def build_prediction_grid(week: int, dow: int, hour: int,
|
||||
demand_model, nulo_model, h3_resolution: int = 8) -> pd.DataFrame:
|
||||
demand_model, nulo_model, h3_resolution: int = 8,
|
||||
traffic_level: int = 1) -> pd.DataFrame:
|
||||
"""
|
||||
Construye una cuadricula de predicciones para todas las celdas H3.
|
||||
|
||||
Args:
|
||||
h3_resolution: Resolución H3 (default=8 para áreas urbanas)
|
||||
traffic_level: Nivel de tráfico (1=bajo, 2=medio, 3=alto)
|
||||
"""
|
||||
# Obtener todas las celdas H3 únicas de la base de datos
|
||||
from db import get_all_h3_cells
|
||||
@@ -117,8 +155,8 @@ def build_prediction_grid(week: int, dow: int, hour: int,
|
||||
# Calcular riesgo
|
||||
risk = calculate_risk(expected_demand, nulo_prob)
|
||||
|
||||
# Determinar radio de cobertura y peso
|
||||
radius = coverage_radius(expected_demand)
|
||||
# Determinar radio de cobertura y peso (ajustado por tráfico)
|
||||
radius = coverage_radius(expected_demand, traffic_level)
|
||||
coverage_weight = get_coverage_weight(expected_demand)
|
||||
|
||||
predictions.append({
|
||||
|
||||
Reference in New Issue
Block a user