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)
|
- dow: día de la semana (0-6, requerido)
|
||||||
- hour: hora del día (0-23, requerido)
|
- hour: hora del día (0-23, requerido)
|
||||||
- k: número de grúas (opcional, default=2)
|
- 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)
|
- optimize: si es True, encuentra k óptimo (opcional, default=False)
|
||||||
- min_gruas: mínimo de grúas para optimización (opcional, default=1)
|
- 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)
|
- 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"])
|
hour = int(request.args["hour"])
|
||||||
|
|
||||||
k = request.args.get("k", default=2, type=int)
|
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"
|
optimize = request.args.get("optimize", default="false").lower() == "true"
|
||||||
min_gruas = request.args.get("min_gruas", default=1, type=int)
|
min_gruas = request.args.get("min_gruas", default=1, type=int)
|
||||||
max_gruas = request.args.get("max_gruas", default=10, 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
|
return jsonify({"error": "hour debe estar entre 0 y 23"}), 400
|
||||||
if k < 1:
|
if k < 1:
|
||||||
return jsonify({"error": "k debe ser al menos 1"}), 400
|
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
|
# Obtener modelos
|
||||||
demand_model = model_manager.get_model("demand")
|
demand_model = model_manager.get_model("demand")
|
||||||
@@ -201,10 +205,10 @@ def recommend_gruas():
|
|||||||
}), 500
|
}), 500
|
||||||
|
|
||||||
if DEBUG_MODE:
|
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
|
# 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:
|
if df.empty:
|
||||||
return jsonify({
|
return jsonify({
|
||||||
@@ -234,6 +238,10 @@ def recommend_gruas():
|
|||||||
"semana": week,
|
"semana": week,
|
||||||
"dia_semana": dow,
|
"dia_semana": dow,
|
||||||
"hora": hour,
|
"hora": hour,
|
||||||
|
"trafico": {
|
||||||
|
"nivel": traffic,
|
||||||
|
"descripcion": {1: "bajo", 2: "medio", 3: "alto"}.get(traffic, "desconocido")
|
||||||
|
},
|
||||||
"optimizacion": {
|
"optimizacion": {
|
||||||
"k_optimo": result['optimal_k'],
|
"k_optimo": result['optimal_k'],
|
||||||
"porcentaje_cobertura": result['coverage_percentage'],
|
"porcentaje_cobertura": result['coverage_percentage'],
|
||||||
@@ -263,7 +271,11 @@ def recommend_gruas():
|
|||||||
"hora": hour,
|
"hora": hour,
|
||||||
"parametros": {
|
"parametros": {
|
||||||
"k": k,
|
"k": k,
|
||||||
"optimizacion": optimize
|
"optimizacion": optimize,
|
||||||
|
"trafico": {
|
||||||
|
"nivel": traffic,
|
||||||
|
"descripcion": {1: "bajo", 2: "medio", 3: "alto"}.get(traffic, "desconocido")
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"h3_recomendados": result['selected'],
|
"h3_recomendados": result['selected'],
|
||||||
"estadisticas": result.get('statistics', []),
|
"estadisticas": result.get('statistics', []),
|
||||||
@@ -505,7 +517,7 @@ def index():
|
|||||||
"ruta": "/recommend",
|
"ruta": "/recommend",
|
||||||
"metodo": "GET",
|
"metodo": "GET",
|
||||||
"descripcion": "Recomendar ubicaciones para grúas",
|
"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",
|
"ruta": "/coverage/radius",
|
||||||
|
|||||||
@@ -3,22 +3,58 @@ import pandas as pd
|
|||||||
from typing import List, Set, Dict, Tuple
|
from typing import List, Set, Dict, Tuple
|
||||||
import numpy as np
|
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
|
baja (<2) | 18
|
||||||
media (2-5) | 12
|
media (2-5) | 12
|
||||||
alta (≥5) | 6
|
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:
|
if expected_demand < 2:
|
||||||
return 18
|
base_radius = 18
|
||||||
elif expected_demand < 5:
|
elif expected_demand < 5:
|
||||||
return 12
|
base_radius = 12
|
||||||
else:
|
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:
|
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)
|
return total_risk * (1 + 0.1 * demand_weight)
|
||||||
|
|
||||||
def build_prediction_grid(week: int, dow: int, hour: int,
|
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.
|
Construye una cuadricula de predicciones para todas las celdas H3.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
h3_resolution: Resolución H3 (default=8 para áreas urbanas)
|
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
|
# Obtener todas las celdas H3 únicas de la base de datos
|
||||||
from db import get_all_h3_cells
|
from db import get_all_h3_cells
|
||||||
@@ -117,8 +155,8 @@ def build_prediction_grid(week: int, dow: int, hour: int,
|
|||||||
# Calcular riesgo
|
# Calcular riesgo
|
||||||
risk = calculate_risk(expected_demand, nulo_prob)
|
risk = calculate_risk(expected_demand, nulo_prob)
|
||||||
|
|
||||||
# Determinar radio de cobertura y peso
|
# Determinar radio de cobertura y peso (ajustado por tráfico)
|
||||||
radius = coverage_radius(expected_demand)
|
radius = coverage_radius(expected_demand, traffic_level)
|
||||||
coverage_weight = get_coverage_weight(expected_demand)
|
coverage_weight = get_coverage_weight(expected_demand)
|
||||||
|
|
||||||
predictions.append({
|
predictions.append({
|
||||||
|
|||||||
Reference in New Issue
Block a user