Corrige acentuacao dos textos
This commit is contained in:
@@ -1,16 +1,16 @@
|
||||
"""Orquestrador principal do Planejador Missao.
|
||||
"""Orquestrador principal do Planejador Missão.
|
||||
|
||||
Entradas:
|
||||
Arquivos em dados/, argumentos opcionais de linha de comando e configuracoes
|
||||
centralizadas em scripts/01_config.py.
|
||||
|
||||
Saidas:
|
||||
Planejamento diario em resultados/, historico operacional atualizado,
|
||||
relatorios de validacao quando solicitado e logs em logs/execucao.log.
|
||||
Saídas:
|
||||
Planejamento diário em resultados/, histórico operacional atualizado,
|
||||
relatórios de validação quando solicitado e logs em logs/execucao.log.
|
||||
|
||||
Papel no pipeline:
|
||||
Executa o fluxo completo: leitura de dados, preparacao, geracao de colunas
|
||||
candidatas, montagem/solucao do MILP, exportacao de resultados e validacao.
|
||||
candidatas, montagem/solução do MILP, exportação de resultados e validação.
|
||||
|
||||
Exemplos:
|
||||
python scripts/00_main.py --data 2026-01-02 --modo diario
|
||||
@@ -43,7 +43,7 @@ def atualizar_data_planejamento(data: str) -> None:
|
||||
|
||||
|
||||
def executar_diario(args: argparse.Namespace, logger) -> dict:
|
||||
"""Executa o planejamento diario oficial em Python."""
|
||||
"""Executa o planejamento diário oficial em Python."""
|
||||
io_utils.configurar_ambiente()
|
||||
if args.data:
|
||||
atualizar_data_planejamento(args.data)
|
||||
@@ -60,24 +60,24 @@ def executar_diario(args: argparse.Namespace, logger) -> dict:
|
||||
logger.info("Colunas candidatas: %s", resultado["total_candidatas"])
|
||||
logger.info("Escalas selecionadas: %s", resultado["total_selecionadas"])
|
||||
logger.info("Arquivo exportado: %s", resultado["arquivo_saida"])
|
||||
logger.info("Tempo de execucao: %.1f s", duracao)
|
||||
logger.info("Tempo de execução: %.1f s", duracao)
|
||||
return resultado
|
||||
|
||||
|
||||
def executar_validacao(ano: str, logger) -> dict:
|
||||
"""Executa validacao retrospectiva suportada pelo projeto."""
|
||||
"""Executa validação retrospectiva suportada pelo projeto."""
|
||||
if str(ano) != "2025":
|
||||
raise ValueError("Erro: no momento a validacao disponivel e --validacao 2025.")
|
||||
raise ValueError("Erro: no momento a validação disponível é --validacao 2025.")
|
||||
validacao = importlib.import_module("07_validacao_2025")
|
||||
return validacao.executar_validacao_2025(importar=True, logger=logger)
|
||||
|
||||
|
||||
def parse_args() -> argparse.Namespace:
|
||||
parser = argparse.ArgumentParser(description="Executa o Planejador Missao em Python.")
|
||||
parser.add_argument("--data", help="Data do planejamento diario no formato AAAA-MM-DD.")
|
||||
parser.add_argument("--aeronave", choices=config.AERONAVES, help="Aeronave de referencia para diagnostico.")
|
||||
parser.add_argument("--modo", default="diario", choices=["diario"], help="Modo de execucao do planejamento.")
|
||||
parser.add_argument("--validacao", help="Ano da validacao retrospectiva. Exemplo: --validacao 2025.")
|
||||
parser = argparse.ArgumentParser(description="Executa o Planejador Missão em Python.")
|
||||
parser.add_argument("--data", help="Data do planejamento diário no formato AAAA-MM-DD.")
|
||||
parser.add_argument("--aeronave", choices=config.AERONAVES, help="Aeronave de referência para diagnóstico.")
|
||||
parser.add_argument("--modo", default="diario", choices=["diario"], help="Modo de execução do planejamento.")
|
||||
parser.add_argument("--validacao", help="Ano da validação retrospectiva. Exemplo: --validacao 2025.")
|
||||
return parser.parse_args()
|
||||
|
||||
|
||||
@@ -86,13 +86,13 @@ def main() -> None:
|
||||
logger = io_utils.configurar_logger("main")
|
||||
if args.validacao:
|
||||
saida = executar_validacao(args.validacao, logger)
|
||||
print("\n=== Validacao concluida ===")
|
||||
print("\n=== Validação concluída ===")
|
||||
for path in saida["arquivos"]:
|
||||
print(f"- {path}")
|
||||
return
|
||||
|
||||
resultado = executar_diario(args, logger)
|
||||
print("\n=== Planejamento diario concluido ===")
|
||||
print("\n=== Planejamento diário concluído ===")
|
||||
print(f"Data: {resultado['data_planejamento']}")
|
||||
print(f"Arquivo: {resultado['arquivo_saida']}")
|
||||
print(f"Colunas candidatas: {resultado['total_candidatas']}")
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
"""Configuracao central dos scripts do Planejador Missao.
|
||||
"""Configuração central dos scripts do Planejador Missão.
|
||||
|
||||
Entradas:
|
||||
Estrutura padrao do projeto, com pastas dados/, src/ e resultados/.
|
||||
Estrutura padrão do projeto, com pastas dados/, src/ e resultados/.
|
||||
|
||||
Saidas:
|
||||
Constantes de caminho, parametros operacionais, nomes de arquivos e pesos
|
||||
usados pelos scripts de execucao, validacao e teste.
|
||||
Saídas:
|
||||
Constantes de caminho, parâmetros operacionais, nomes de arquivos e pesos
|
||||
usados pelos scripts de execução, validação e teste.
|
||||
|
||||
Papel no pipeline:
|
||||
Evita caminhos absolutos e concentra convencoes para que o projeto rode em
|
||||
@@ -67,6 +67,6 @@ ARQUIVOS_ENTRADA_OBRIGATORIOS = [
|
||||
|
||||
|
||||
def garantir_diretorios() -> None:
|
||||
"""Cria diretorios de saida e apoio usados pelos scripts."""
|
||||
"""Cria diretórios de saída e apoio usados pelos scripts."""
|
||||
for path in [RESULTADOS_DIR, VALIDACAO_DIR, LOGS_DIR, TEMP_DIR, ARQUIVO_VOOS_2025.parent]:
|
||||
path.mkdir(parents=True, exist_ok=True)
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
"""Utilitarios de entrada, saida e log dos scripts.
|
||||
"""Utilitários de entrada, saída e log dos scripts.
|
||||
|
||||
Entradas:
|
||||
Caminhos definidos em 01_config.py.
|
||||
|
||||
Saidas:
|
||||
Validacoes de arquivos, diretorios criados, logs em logs/execucao.log e
|
||||
Saídas:
|
||||
Validações de arquivos, diretórios criados, logs em logs/execucao.log e
|
||||
funcoes pequenas para exportacao.
|
||||
|
||||
Papel no pipeline:
|
||||
Padroniza mensagens de erro e evita repeticao de codigo de filesystem.
|
||||
Padroniza mensagens de erro e evita repetição de código de filesystem.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
@@ -52,7 +52,7 @@ def configurar_logger(nome: str = "planejador_missao") -> logging.Logger:
|
||||
|
||||
|
||||
def exigir_arquivos(paths: Iterable[Path]) -> None:
|
||||
"""Interrompe a execucao com mensagem clara se algum arquivo faltar."""
|
||||
"""Interrompe a execução com mensagem clara se algum arquivo faltar."""
|
||||
ausentes = [path for path in paths if not path.exists()]
|
||||
if ausentes:
|
||||
lista = "\n".join(f"- {path}" for path in ausentes)
|
||||
@@ -64,7 +64,7 @@ def exigir_colunas(df: pd.DataFrame, colunas: Iterable[str], origem: str) -> Non
|
||||
faltantes = [col for col in colunas if col not in df.columns]
|
||||
if faltantes:
|
||||
raise ValueError(
|
||||
f"Erro: coluna obrigatoria '{faltantes[0]}' nao encontrada em {origem}. "
|
||||
f"Erro: coluna obrigatória '{faltantes[0]}' não encontrada em {origem}. "
|
||||
"Verifique o arquivo de entrada."
|
||||
)
|
||||
|
||||
|
||||
@@ -1,15 +1,15 @@
|
||||
"""Preparacao das bases operacionais do Planejador Missao.
|
||||
"""Preparação das bases operacionais do Planejador Missão.
|
||||
|
||||
Entradas:
|
||||
Planilhas e CSVs em dados/: cadastro, catalogo de OIs, indisponibilidades,
|
||||
progresso, historico, aeronaves, tripulantes disponiveis e rotas acionadas.
|
||||
progresso, histórico, aeronaves, tripulantes disponíveis e rotas acionadas.
|
||||
|
||||
Saidas:
|
||||
Dicionario com DataFrames normalizados para geracao de colunas candidatas.
|
||||
|
||||
Papel no pipeline:
|
||||
Concentra a leitura e a preparacao antes do MILP, mantendo rastreavel quais
|
||||
arquivos alimentam cada execucao.
|
||||
arquivos alimentam cada execução.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
@@ -64,7 +64,7 @@ def main() -> None:
|
||||
logger = io_utils.configurar_logger("preparar_dados")
|
||||
bases = carregar_bases()
|
||||
logger.info("Tripulantes no cadastro: %s", len(bases["cadastro"]))
|
||||
logger.info("Tripulantes disponiveis: %s", len(bases["disponiveis"]))
|
||||
logger.info("Tripulantes disponíveis: %s", len(bases["disponiveis"]))
|
||||
logger.info("Aeronaves informadas: %s", len(bases["aeronaves"]))
|
||||
logger.info("Rotas acionadas: %s", len(bases["rotas"]))
|
||||
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
"""Geracao das colunas candidatas viaveis.
|
||||
"""Geração das colunas candidatas viáveis.
|
||||
|
||||
Entradas:
|
||||
Bases preparadas por 03_preparar_dados.py.
|
||||
|
||||
Saidas:
|
||||
DataFrame em que cada linha representa uma escala possivel: rota acionada,
|
||||
missao local ou sobreaviso, com dupla, aeronave, score, custo e metadados.
|
||||
DataFrame em que cada linha representa uma escala possível: rota acionada,
|
||||
missão local ou sobreaviso, com dupla, aeronave, score, custo e metadados.
|
||||
|
||||
Papel no pipeline:
|
||||
Materializa o espaco de decisoes do MILP. A compatibilidade de aeronave,
|
||||
@@ -21,13 +21,13 @@ io_utils = importlib.import_module("02_io_utils")
|
||||
|
||||
|
||||
def gerar_colunas_do_dia(bases: dict):
|
||||
"""Gera colunas candidatas para a data e parametros informados nas bases."""
|
||||
"""Gera colunas candidatas para a data e parâmetros informados nas bases."""
|
||||
from src.planejador_missao.candidates import gerar_colunas
|
||||
|
||||
parametros = bases["parametros"]
|
||||
# Cada coluna candidata equivale a uma variavel x_j do MILP.
|
||||
# Cada coluna candidata equivale a uma variável x_j do MILP.
|
||||
# As regras de dupla, qualificacao, instrucao e indisponibilidade sao
|
||||
# aplicadas antes do solver para reduzir o modelo a alternativas viaveis.
|
||||
# aplicadas antes do solver para reduzir o modelo a alternativas viáveis.
|
||||
return gerar_colunas(
|
||||
parametros["data_planejamento"],
|
||||
bases["rotas"],
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
"""Modelo MILP do Planejador Missao usando scipy.optimize.milp/HiGHS.
|
||||
"""Modelo MILP do Planejador Missão usando scipy.optimize.milp/HiGHS.
|
||||
|
||||
Entradas:
|
||||
Colunas candidatas viaveis geradas por 04_gerar_colunas_candidatas.py.
|
||||
Colunas candidatas viáveis geradas por 04_gerar_colunas_candidatas.py.
|
||||
|
||||
Saidas:
|
||||
Subconjunto de colunas selecionadas pelo solver, representando a escala
|
||||
@@ -14,12 +14,12 @@ Metodologia:
|
||||
|
||||
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;
|
||||
b) cada tripulante aparece no máximo 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;
|
||||
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 inviaveis nao chegam ao MILP;
|
||||
f) regras especificas de rota, missao local e SBV sao preservadas por tipo.
|
||||
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
|
||||
@@ -36,10 +36,10 @@ def resolver_escala(colunas, rotas, aeronaves):
|
||||
from src.planejador_missao.optimizer import resolver_milp
|
||||
|
||||
if colunas.empty:
|
||||
raise RuntimeError("Erro: nao ha colunas candidatas viaveis para montar o MILP.")
|
||||
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 funcao objetivo usa -score_milp porque o HiGHS via SciPy resolve
|
||||
# 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)
|
||||
|
||||
|
||||
@@ -5,10 +5,10 @@ Entradas:
|
||||
|
||||
Saidas:
|
||||
Planilha em resultados/planejamento_diario_YYYY-MM-DD.xlsx e registros de
|
||||
historico operacional para atualizacao do acumulado.
|
||||
histórico operacional para atualização do acumulado.
|
||||
|
||||
Papel no pipeline:
|
||||
Converte a solucao matematica em artefatos utilizaveis pelo esquadrao.
|
||||
Converte a solução matemática em artefatos utilizáveis pelo esquadrão.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
@@ -11,8 +11,8 @@ Saidas:
|
||||
resultados/validacao/validacao_2025_barras.png
|
||||
|
||||
Papel no pipeline:
|
||||
Mantem a demanda historica de 2025, gera candidatos compativeis para cada
|
||||
slot historico e usa MILP para redistribuir tripulantes preservando horas.
|
||||
Mantém a demanda histórica de 2025, gera candidatos compatíveis para cada
|
||||
slot histórico e usa MILP para redistribuir tripulantes preservando horas.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
@@ -89,7 +89,7 @@ def _tripulantes(valor: object) -> list[str]:
|
||||
|
||||
|
||||
def importar_voos_2025(origem: Path = config.ARQUIVO_QUADRO_VOO_2025, destino: Path = config.ARQUIVO_VOOS_2025) -> pd.DataFrame:
|
||||
"""Importa voos realizados de 2025 da aba VOOS para o CSV de validacao."""
|
||||
"""Importa voos realizados de 2025 da aba VOOS para o CSV de validação."""
|
||||
io_utils.exigir_arquivos([origem])
|
||||
raw = pd.read_excel(origem, sheet_name=config.ABAS["voos_2025"], header=None)
|
||||
linhas = []
|
||||
@@ -176,7 +176,7 @@ def _png_barras(path: Path, metricas: pd.DataFrame) -> Path:
|
||||
|
||||
|
||||
def executar_validacao_2025(importar: bool = True, logger=None) -> dict:
|
||||
"""Executa a validacao completa e exporta os artefatos finais."""
|
||||
"""Executa a validação completa e exporta os artefatos finais."""
|
||||
io_utils.configurar_ambiente()
|
||||
logger = logger or io_utils.configurar_logger("validacao_2025")
|
||||
inicio = pd.Timestamp.now()
|
||||
@@ -189,9 +189,9 @@ def executar_validacao_2025(importar: bool = True, logger=None) -> dict:
|
||||
|
||||
voos = carregar_voos_2025(config.ARQUIVO_VOOS_2025)
|
||||
if voos.empty:
|
||||
raise RuntimeError("Erro: base de validacao 2025 vazia. Verifique dados/validacao/voos_2025.csv.")
|
||||
raise RuntimeError("Erro: base de validação 2025 vazia. Verifique dados/validacao/voos_2025.csv.")
|
||||
if (voos["horas_voadas"] < 0).any():
|
||||
raise RuntimeError("Erro: foram encontradas horas voadas negativas na validacao 2025.")
|
||||
raise RuntimeError("Erro: foram encontradas horas voadas negativas na validação 2025.")
|
||||
|
||||
resultado = otimizar_equalizacao_50(
|
||||
config.PROJECT_ROOT,
|
||||
@@ -204,7 +204,7 @@ def executar_validacao_2025(importar: bool = True, logger=None) -> dict:
|
||||
total_real = float(metricas.loc[metricas["cenario"] == "real_2025", "horas_total"].iloc[0])
|
||||
total_otim = float(metricas.loc[metricas["cenario"] == "otimizado_meta_50", "horas_total"].iloc[0])
|
||||
if abs(total_real - total_otim) > 0.01:
|
||||
logger.warning("Horas nao preservadas: real=%s otimizado=%s", total_real, total_otim)
|
||||
logger.warning("Horas não preservadas: real=%s otimizado=%s", total_real, total_otim)
|
||||
|
||||
resumo_path = config.VALIDACAO_DIR / "validacao_2025_resumo.xlsx"
|
||||
detalhada_path = config.VALIDACAO_DIR / "validacao_2025_detalhada.xlsx"
|
||||
@@ -231,7 +231,7 @@ def executar_validacao_2025(importar: bool = True, logger=None) -> dict:
|
||||
logger.info("Alocacoes otimizadas: %s", len(resultado["otimizados"]))
|
||||
logger.info("Tripulantes comparados: %s", len(resultado["comparativo"]))
|
||||
logger.info("Status solver: %s", resultado["status_solver"]["mensagem"])
|
||||
logger.info("Tempo de validacao: %.1f s", duracao)
|
||||
logger.info("Tempo de validação: %.1f s", duracao)
|
||||
logger.info("Arquivos exportados: %s | %s | %s | %s", resumo_path, detalhada_path, metricas_path, grafico_path)
|
||||
|
||||
return {
|
||||
@@ -242,11 +242,11 @@ def executar_validacao_2025(importar: bool = True, logger=None) -> dict:
|
||||
|
||||
|
||||
def main() -> None:
|
||||
"""Ponto de entrada da validacao 2025."""
|
||||
"""Ponto de entrada da validação 2025."""
|
||||
logger = io_utils.configurar_logger("validacao_2025")
|
||||
saida = executar_validacao_2025(importar=True, logger=logger)
|
||||
metricas = saida["resultado"]["metricas"]
|
||||
print("\n=== Validacao 2025 concluida ===")
|
||||
print("\n=== Validação 2025 concluída ===")
|
||||
print(metricas.to_string(index=False))
|
||||
print("\nArquivos gerados:")
|
||||
for path in saida["arquivos"]:
|
||||
|
||||
@@ -30,7 +30,7 @@ def comando_python_app() -> list[str]:
|
||||
|
||||
|
||||
def abrir_app() -> None:
|
||||
"""Inicia o app em segundo plano sem janela de console quando possivel."""
|
||||
"""Inicia o app em segundo plano sem janela de console quando possível."""
|
||||
io_utils.configurar_ambiente()
|
||||
subprocess.Popen(comando_python_app(), cwd=config.PROJECT_ROOT)
|
||||
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
"""Teste rapido de instalacao do Planejador Missao.
|
||||
"""Teste rápido de instalação do Planejador Missão.
|
||||
|
||||
Entradas:
|
||||
Ambiente Python atual, dependencias instaladas e arquivos em dados/.
|
||||
|
||||
Saidas:
|
||||
Diagnostico amigavel no terminal e log em logs/execucao.log.
|
||||
Saídas:
|
||||
Diagnóstico amigável no terminal e log em logs/execucao.log.
|
||||
|
||||
Papel no pipeline:
|
||||
Permite verificar rapidamente se o computador esta pronto para executar o
|
||||
Permite verificar rapidamente se o computador está pronto para executar o
|
||||
planejador e o solver HiGHS/scipy.optimize.milp.
|
||||
"""
|
||||
|
||||
@@ -56,7 +56,7 @@ def main() -> None:
|
||||
testar_solver_minimo()
|
||||
print("Solver scipy.optimize.milp/HiGHS OK")
|
||||
logger.info("Teste de instalacao concluido com sucesso.")
|
||||
print("Ambiente OK para executar o Planejador Missao.")
|
||||
print("Ambiente OK para executar o Planejador Missão.")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
"""Importa a aba VOOS do Quadro de Voo 2025 para a base de validacao."""
|
||||
"""Importa a aba VOOS do Quadro de Voo 2025 para a base de validação."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
@@ -110,7 +110,7 @@ def importar(origem: Path, destino: Path) -> pd.DataFrame:
|
||||
|
||||
|
||||
def main() -> None:
|
||||
parser = argparse.ArgumentParser(description="Importa voos realizados de 2025 para a validacao.")
|
||||
parser = argparse.ArgumentParser(description="Importa voos realizados de 2025 para a validação.")
|
||||
parser.add_argument(
|
||||
"--origem",
|
||||
type=Path,
|
||||
@@ -121,7 +121,7 @@ def main() -> None:
|
||||
"--destino",
|
||||
type=Path,
|
||||
default=BASE_DIR / "dados" / "validacao" / "voos_2025.csv",
|
||||
help="CSV de validacao gerado.",
|
||||
help="CSV de validação gerado.",
|
||||
)
|
||||
args = parser.parse_args()
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
"""Executa a validacao retrospectiva com voos de 2025."""
|
||||
"""Executa a validação retrospectiva com voos de 2025."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
@@ -29,7 +29,7 @@ def main() -> None:
|
||||
|
||||
voos = carregar_voos_2025(entrada)
|
||||
if voos.empty:
|
||||
print("Base de validacao ainda vazia.")
|
||||
print("Base de validação ainda vazia.")
|
||||
print(f"Preencha o arquivo: {entrada}")
|
||||
print("Colunas esperadas: data,aeronave,tipo_escala,tripulante,funcao,oi,horas_voadas,sbv")
|
||||
return
|
||||
@@ -43,13 +43,13 @@ def main() -> None:
|
||||
)
|
||||
arquivo = salvar_relatorio_validacao(BASE_DIR, resultado, meta_horas=args.meta)
|
||||
|
||||
print("\n=== Validacao 2025 concluida ===")
|
||||
print("\n=== Validação 2025 concluída ===")
|
||||
print(f"Meta de equalizacao: {args.meta:g} horas")
|
||||
print(f"Voos/slots avaliados: {len(resultado['slots'])}")
|
||||
print(f"Tripulantes comparados: {len(resultado['comparativo'])}")
|
||||
print(f"Relatorio: {arquivo}")
|
||||
print(f"Relatório: {arquivo}")
|
||||
print(f"Solver: {resultado['status_solver']['mensagem']}")
|
||||
print("\nMetricas:")
|
||||
print("\nMétricas:")
|
||||
print(resultado["metricas"].to_string(index=False))
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user