"""Modelo MILP do Planejador Missao usando scipy.optimize.milp/HiGHS. Entradas: Colunas candidatas viaveis 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 maximo uma vez no dia; c) cada aeronave recebe cobertura principal por rota acionada ou SBV; d) aeronave nao executa escalas conflitantes de rota/local no mesmo dia; e) qualificacao, indisponibilidade e regras de instrucao entram no filtro de colunas candidatas, logo colunas inviaveis nao chegam ao MILP; f) regras especificas de rota, missao local e SBV sao 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: nao ha colunas candidatas viaveis para montar o MILP.") # O resolvedor cria x_j binario para cada linha de colunas. # A funcao 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()