59 lines
2.2 KiB
Python
59 lines
2.2 KiB
Python
"""Modelo MILP do Planejador Missão usando scipy.optimize.milp/HiGHS.
|
|
|
|
Entradas:
|
|
Colunas candidatas viáveis geradas por 04_gerar_colunas_candidatas.py.
|
|
|
|
Saidas:
|
|
Subconjunto de colunas selecionadas pelo solver, representando a escala
|
|
diaria otimizada.
|
|
|
|
Metodologia:
|
|
Variavel de decisao: x_j em {0,1}, onde cada j representa uma coluna
|
|
candidata. Como scipy.optimize.milp minimiza, o modelo minimiza -score_milp,
|
|
equivalente a maximizar o score operacional total.
|
|
|
|
Restricoes implementadas no motor src.planejador_missao.optimizer:
|
|
a) rota acionada obrigatoria coberta exatamente uma vez;
|
|
b) cada tripulante aparece no máximo uma vez no dia;
|
|
c) cada aeronave recebe cobertura principal por rota acionada ou SBV;
|
|
d) aeronave não executa escalas conflitantes de rota/local no mesmo dia;
|
|
e) qualificacao, indisponibilidade e regras de instrucao entram no filtro de
|
|
colunas candidatas, logo colunas inviáveis não chegam ao MILP;
|
|
f) regras específicas de rota, missão local e SBV são preservadas por tipo.
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
import importlib
|
|
|
|
gerador = importlib.import_module("04_gerar_colunas_candidatas")
|
|
io_utils = importlib.import_module("02_io_utils")
|
|
preparar = importlib.import_module("03_preparar_dados")
|
|
|
|
|
|
def resolver_escala(colunas, rotas, aeronaves):
|
|
"""Resolve o MILP e retorna as colunas escolhidas."""
|
|
from src.planejador_missao.optimizer import resolver_milp
|
|
|
|
if colunas.empty:
|
|
raise RuntimeError("Erro: não há colunas candidatas viáveis para montar o MILP.")
|
|
|
|
# O resolvedor cria x_j binario para cada linha de colunas.
|
|
# A função objetivo usa -score_milp porque o HiGHS via SciPy resolve
|
|
# minimizacao; isso preserva a interpretacao de maximizar score.
|
|
return resolver_milp(colunas, rotas, aeronaves)
|
|
|
|
|
|
def main() -> None:
|
|
"""Executa o MILP em modo diagnostico."""
|
|
logger = io_utils.configurar_logger("modelo_milp")
|
|
bases = preparar.carregar_bases()
|
|
colunas = gerador.gerar_colunas_do_dia(bases)
|
|
solucao = resolver_escala(colunas, bases["rotas"], bases["aeronaves"])
|
|
logger.info("Colunas candidatas: %s", len(colunas))
|
|
logger.info("Escalas selecionadas: %s", len(solucao))
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|