Migra C1 de Set Covering para Set Partitioning e documenta limitacoes (v0.10)

- C1 alterado: z[nid] <= 1 -> z[nid] == 1 para todas as missoes; toda missao
  deve ser coberta por exatamente 1 aeronave (sem missoes descobertas).
- n_missoes padrao reduzido de 50 para 20 (n_evam de 5 para 4): garante
  factibilidade do MIP com Set Partitioning no envelope de 4 aeronaves.
- Time limit padrao do solver CBC fixado em 120 s (era ilimitado): evita
  travamento ao tentar provar infeasibility.
- Corrigido display "Not Solved": status de L1 preservado quando PuLP
  redefine mdl.status apos setObjective() em L2.
- f0_cenario_insp_grande.json revisado: apenas 2803 com f0=595h em INSP 2A
  (F_max=600h, downtime=4 dias); demais matriculas com f0=0.
- Gerado planejamento_insp_grande.html: Gantt exibe INSP 2A visivelmente;
  20/20 missoes cobertas; CBC Optimal em < 15 s.
- changelog.md e LOG.md atualizados com limitacoes detalhadas para
  contribuidores: escopo validado, bugs de display, riscos numericos do
  big-M com LRT < 5h e comportamento de 2811 ociosa.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Cesa-V
2026-06-16 11:09:24 -03:00
parent 6433055e9e
commit a34ed6b340
6 changed files with 1202 additions and 75 deletions

6
LOG.md
View File

@@ -40,5 +40,11 @@ Legenda de autores:
| 2026-06-16 | 10:35 | VTO | Rodada sintética validada: 50/50 missões cumpridas | `db/processed/resultado_oamrp_sintetico.csv` | Comando: --sintetico --seed 42 --aleatorio --ofrag; solver CBC retornou Optimal; todas as 4 EVAMs voaram com ferry; commit f0d72f8 enviado ao remote. | | 2026-06-16 | 10:35 | VTO | Rodada sintética validada: 50/50 missões cumpridas | `db/processed/resultado_oamrp_sintetico.csv` | Comando: --sintetico --seed 42 --aleatorio --ofrag; solver CBC retornou Optimal; todas as 4 EVAMs voaram com ferry; commit f0d72f8 enviado ao remote. |
| 2026-06-16 | 14:00 | VTO | Criou visualização combinada (Gantt + mapa + tabela) | `software/visualizar_resultado.py`; `db/processed/planejamento_cenario_esquadrao.html` | HTML único com título "Planejamento de Diagonal de Manutenção"; Gantt via go.Scatter lines (renderização garantida); mapa Folium em iframe; tabela de voos com filtros JS; commit 3756f96. | | 2026-06-16 | 14:00 | VTO | Criou visualização combinada (Gantt + mapa + tabela) | `software/visualizar_resultado.py`; `db/processed/planejamento_cenario_esquadrao.html` | HTML único com título "Planejamento de Diagonal de Manutenção"; Gantt via go.Scatter lines (renderização garantida); mapa Folium em iframe; tabela de voos com filtros JS; commit 3756f96. |
| 2026-06-16 | 15:00 | VTO | Criou cenários JSON de f0 para testes com inspeções | `db/processed/f0_cenario_esquadrao.json`; `db/processed/f0_cenario_insp_grande.json` | f0_cenario_esquadrao simula dados reais do esquadrão (LRT 32h/215h/12h/28h); f0_cenario_insp_grande força aeronaves próximas ao limite. | | 2026-06-16 | 15:00 | VTO | Criou cenários JSON de f0 para testes com inspeções | `db/processed/f0_cenario_esquadrao.json`; `db/processed/f0_cenario_insp_grande.json` | f0_cenario_esquadrao simula dados reais do esquadrão (LRT 32h/215h/12h/28h); f0_cenario_insp_grande força aeronaves próximas ao limite. |
| 2026-06-16 | 20:00 | VTO | Migrou modelo de Set Covering para Set Partitioning (C1) | `software/oamrp_v3.py` | Restrição C1 alterada de z<=1 para z==1 para todas as missões; eliminada distinção entre missões hard/opcionais; toda missão deve ser coberta por exatamente 1 aeronave. |
| 2026-06-16 | 20:05 | VTO | Reduziu missões sintéticas padrão de 50 para 20 | `software/oamrp_v3.py` | Set Partitioning com 50 missões tornava o MIP inviável ou muito lento (travamento do solver); 20 missões garantem factibilidade no envelope de 4 aeronaves em janeiro; n_evam reduzido de 5 para 4. |
| 2026-06-16 | 20:10 | VTO | Adicionou time limit padrão de 120 s ao solver CBC | `software/oamrp_v3.py` | Solver travava indefinidamente sem time limit ao tentar provar infeasibility; limite de 120 s garante retorno com melhor solução encontrada. |
| 2026-06-16 | 20:15 | VTO | Corrigiu display do status do solver (Not Solved) | `software/oamrp_v3.py` | PuLP redefine mdl.status para 0 ("Not Solved") ao chamar setObjective() antes de L2; status de L1 agora preservado quando L2 reporta 0. |
| 2026-06-16 | 20:20 | VTO | Revisou f0_cenario_insp_grande.json | `db/processed/f0_cenario_insp_grande.json` | Apenas 2803 com f0=595h em INSP 2A (F_max=600h, downtime=4 dias, LRT_ini=5h); demais matrículas com f0=0; configuração anterior com 4 aeronaves apertadas simultaneamente tornava o MIP inviável. |
| 2026-06-16 | 20:30 | VTO | Gerou visualização do cenário inspeção grande (v0.10) | `db/processed/planejamento_insp_grande.html`; `db/processed/resultado_oamrp_v3.csv` | 20/20 missões cobertas; Gantt exibe INSP 2A (4 dias) visivelmente; 2 inspeções no horizonte de janeiro; solver CBC retornou Optimal em < 15 s. |
| 2026-06-16 | 16:00 | VTO | Corrigiu Gantt: FAB 2800 invisível e barras não renderizavam | `software/visualizar_resultado.py` | yaxis range=[-0.5, n-0.5] para FAB 2800 (y=0) visível; shapes substituídas por go.Scatter mode="lines" width=64 (renderização garantida); largura mínima de 2h por barra. | | 2026-06-16 | 16:00 | VTO | Corrigiu Gantt: FAB 2800 invisível e barras não renderizavam | `software/visualizar_resultado.py` | yaxis range=[-0.5, n-0.5] para FAB 2800 (y=0) visível; shapes substituídas por go.Scatter mode="lines" width=64 (renderização garantida); largura mínima de 2h por barra. |
| 2026-06-16 | 16:30 | VTO | Adicionou parser de Escala de Voo Modelo 1 e bases extras | `software/oamrp_v3.py`; `db/raw/ESCALA DE VOO MODELO 1.csv` | Flag --escala carrega missões reais do CSV com separador ";"; coordenadas de 26 bases (era 10); time-limit default alterado para 300s; imports timedelta/date consolidados; commit 83a2dac. | | 2026-06-16 | 16:30 | VTO | Adicionou parser de Escala de Voo Modelo 1 e bases extras | `software/oamrp_v3.py`; `db/raw/ESCALA DE VOO MODELO 1.csv` | Flag --escala carrega missões reais do CSV com separador ";"; coordenadas de 26 bases (era 10); time-limit default alterado para 300s; imports timedelta/date consolidados; commit 83a2dac. |

View File

@@ -1,6 +1,6 @@
{ {
"2800": {"2": 285, "3": 0, "4": 0, "6": 0, "7": 0, "19": 0, "20": 0, "22": 0}, "2800": {"2": 0, "3": 0, "4": 0, "6": 0, "7": 0, "19": 0, "20": 0, "22": 0},
"2803": {"2": 0, "3": 570, "4": 0, "6": 0, "7": 0, "19": 0, "20": 0, "22": 0}, "2803": {"2": 0, "3": 595, "4": 0, "6": 0, "7": 0, "19": 0, "20": 0, "22": 0},
"2809": {"2": 0, "3": 0, "4": 0, "6": 280, "7": 0, "19": 0, "20": 0, "22": 0}, "2809": {"2": 0, "3": 0, "4": 0, "6": 0, "7": 0, "19": 0, "20": 0, "22": 0},
"2811": {"2": 0, "3": 0, "4": 0, "6": 0, "7": 380, "19": 0, "20": 0, "22": 0} "2811": {"2": 0, "3": 0, "4": 0, "6": 0, "7": 0, "19": 0, "20": 0, "22": 0}
} }

File diff suppressed because one or more lines are too long

View File

@@ -1,51 +1,23 @@
status,aeronave,ordem,id,om,orig,dest,partida_utc,chegada_utc,dur_h,prioridade,periodo,aeronave_real_2025,linhas_origem status,aeronave,ordem,id,om,orig,dest,partida_utc,chegada_utc,dur_h,prioridade,periodo,aeronave_real_2025,linhas_origem
cumprida,2800,1,RV2025_OM1_E2_L5_C5,1,SBMN,SBMN,2025-01-02T14:30:00Z,2025-01-02T15:35:00Z,1.08,1,NOTURNO,2809,5 cumprida,2800,1,SIM_007_SBMN_SBCO,7,SBMN,SBCO,2025-01-09T02:09:28.800000Z,2025-01-09T07:58:40.800000Z,5.82,1,DIURNO,,
cumprida,2800,2,RV2025_OM5_E2_L13_C13,5,SBMN,SBMN,2025-01-07T14:15:00Z,2025-01-07T16:15:00Z,2.00,1,DIURNO,2803,13 cumprida,2800,2,SIM_010_SBCY_SBMN,10,SBCY,SBMN,2025-01-11T23:29:27.600000Z,2025-01-12T03:09:39.600000Z,3.67,3,DIURNO,,
cumprida,2803,1,RV2025_OM7_E1_L15_C15,7,SBMN,SBMN,2025-01-07T10:40:00Z,2025-01-07T12:30:00Z,1.83,1,DIURNO,2809,15 cumprida,2800,3,SIM_012_SWCA_SBTT,12,SWCA,SBTT,2025-01-12T14:52:01.200000Z,2025-01-12T16:14:49.200000Z,1.38,3,DIURNO,,
cumprida,2803,2,RV2025_OM8_E1_L17_C17,8,SBMN,SBMN,2025-01-08T10:35:00Z,2025-01-08T12:35:00Z,2.00,1,DIURNO,2803,17 cumprida,2800,4,SIM_019_SBMN_SWCA,19,SBMN,SWCA,2025-01-29T04:57:54Z,2025-01-29T06:36:54Z,1.65,1,DIURNO,,
cumprida,2803,3,RV2025_OM12_E4_L28_C29,12,SBMN,SBMN,2025-01-11T21:05:00Z,2025-01-12T00:00:00Z,2.92,1,DIURNO;NOTURNO,2809,28;29 cumprida,2800,5,SIM_020_SWCA_SBCO,20,SWCA,SBCO,2025-01-31T03:09:10.800000Z,2025-01-31T08:39:46.800000Z,5.51,2,DIURNO,,
cumprida,2803,4,RV2025_OM15_E1_L34_C34,15,SBMN,SBMN,2025-01-12T11:50:00Z,2025-01-12T13:30:00Z,1.67,1,DIURNO,2803,34 inspecao,2800,,INSP_2800_3,INSP 2A,SBMN,SBMN,2025-01-12T16:14:49.200000Z,2025-01-16T16:14:49.200000Z,96.00,,,,
cumprida,2809,1,RV2025_OM1_E1_L4_C4,1,SBMN,SBMN,2025-01-02T11:55:00Z,2025-01-02T13:05:00Z,1.17,1,NOTURNO,2809,4 cumprida,2803,1,SIM_006_SWBC_SBAN,6,SWBC,SBAN,2025-01-06T21:08:24Z,2025-01-07T00:56:24Z,3.80,2,DIURNO,,
cumprida,2811,1,RV2025_OM3_E1_L8_C8,3,SBMN,SBMN,2025-01-03T14:45:00Z,2025-01-03T16:10:00Z,1.42,1,DIURNO,2809,8 cumprida,2809,1,SIM_001_SBBE_SBMN,1,SBBE,SBMN,2025-01-02T07:53:34.800000Z,2025-01-02T11:07:22.800000Z,3.23,2,DIURNO,,
cumprida,2811,2,RV2025_OM4_E2_L10_C10,4,SBMN,SBMN,2025-01-06T15:40:00Z,2025-01-06T16:45:00Z,1.08,1,DIURNO,2803,10 cumprida,2809,2,SIM_002_SBPV_SBOI,2,SBPV,SBOI,2025-01-03T03:03:10.800000Z,2025-01-03T09:37:58.800000Z,6.58,3,DIURNO,,
cumprida,2811,3,RV2025_OM9_E1_L20_C20,9,SBMN,SBMN,2025-01-09T12:30:00Z,2025-01-09T15:55:00Z,3.42,1,DIURNO,2803,20 cumprida,2809,3,SIM_005_SBMY_SBYS,5,SBMY,SBYS,2025-01-04T19:37:19.200000Z,2025-01-05T01:06:43.200000Z,5.49,1,DIURNO,,
cumprida,2811,4,RV2025_OM9_E3_L22_C22,9,SBMN,SBMN,2025-01-09T20:40:00Z,2025-01-09T22:15:00Z,1.58,1,DIURNO,2803,22 cumprida,2809,4,SIM_008_SBPV_SBMN,8,SBPV,SBMN,2025-01-09T23:11:34.800000Z,2025-01-10T00:51:10.800000Z,1.66,2,DIURNO,,
cumprida,2811,5,RV2025_OM14_E1_L32_C32,14,SBMN,SBMN,2025-01-12T16:55:00Z,2025-01-12T20:25:00Z,3.50,1,DIURNO,2809,32 cumprida,2809,5,SIM_011_SBSN_SBVH,11,SBSN,SBVH,2025-01-12T01:26:24Z,2025-01-12T04:15:36Z,2.82,1,DIURNO,,
cumprida,2811,6,RV2025_OM17_E1_L40_C40,17,SBMN,SBMN,2025-01-15T13:30:00Z,2025-01-15T14:25:00Z,0.92,1,DIURNO,2809,40 cumprida,2809,6,SIM_016_SBTF_SBMN,16,SBTF,SBMN,2025-01-24T15:25:55.200000Z,2025-01-24T16:40:19.200000Z,1.24,3,DIURNO,,
cumprida,2811,7,RV2025_OM17_E3_L42_C45,17,SBMN,SBMN,2025-01-15T22:50:00Z,2025-01-15T23:50:00Z,1.00,1,NOTURNO,2809,42;43;44;45 inspecao,2809,,INSP_2809_3,INSP 2A,SBMN,SBMN,2025-01-05T01:06:43.200000Z,2025-01-09T01:06:43.200000Z,96.00,,,,
nao_cumprida,,,RV2025_OM2_E3_L6_C6,2,SBMN,SBMN,2025-01-02T17:00:00Z,2025-01-02T18:05:00Z,1.08,1,NOTURNO,2809,6 cumprida,2811,1,SIM_003_SBMN_SBUY,3,SBMN,SBUY,2025-01-03T09:50:20.400000Z,2025-01-03T16:17:56.400000Z,6.46,2,DIURNO,,
nao_cumprida,,,RV2025_OM2_E4_L7_C7,2,SBMN,SBMN,2025-01-02T20:00:00Z,2025-01-02T21:10:00Z,1.17,1,NOTURNO,2809,7 cumprida,2811,2,SIM_004_SWCA_SBMN,4,SWCA,SBMN,2025-01-04T03:01:19.200000Z,2025-01-04T04:51:43.200000Z,1.84,3,DIURNO,,
nao_cumprida,,,RV2025_OM5_E1_L11_C11,5,SBMN,SBMN,2025-01-06T19:10:00Z,2025-01-06T21:20:00Z,2.17,1,DIURNO,2803,11 cumprida,2811,3,SIM_009_SBUY_SBCC,9,SBUY,SBCC,2025-01-11T12:27:50.400000Z,2025-01-11T17:17:02.400000Z,4.82,1,DIURNO,,
nao_cumprida,,,RV2025_OM6_E1_L12_C12,6,SBMN,SBMN,2025-01-06T19:30:00Z,2025-01-06T21:25:00Z,1.92,1,DIURNO,2811,12 cumprida,2811,4,SIM_013_SBUY_SBMN,13,SBUY,SBMN,2025-01-15T01:13:04.800000Z,2025-01-15T07:31:40.800000Z,6.31,3,DIURNO,,
nao_cumprida,,,RV2025_OM6_E2_L14_C14,6,SBMN,SBMN,2025-01-07T11:20:00Z,2025-01-07T13:20:00Z,2.00,1,DIURNO,2811,14 cumprida,2811,5,SIM_014_SBBE_SBUA,14,SBBE,SBUA,2025-01-20T05:25:19.200000Z,2025-01-20T10:31:55.200000Z,5.11,2,DIURNO,,
nao_cumprida,,,RV2025_OM7_E2_L16_C16,7,SBMN,SBMN,2025-01-07T14:00:00Z,2025-01-07T15:45:00Z,1.75,1,DIURNO,2809,16 cumprida,2811,6,SIM_015_SBBE_SBTS,15,SBBE,SBTS,2025-01-21T05:22:01.200000Z,2025-01-21T10:28:37.200000Z,5.11,4,DIURNO,,
nao_cumprida,,,RV2025_OM8_E2_L18_C18,8,SBMN,SBMN,2025-01-08T14:00:00Z,2025-01-08T16:00:00Z,2.00,1,DIURNO,2803,18 cumprida,2811,7,SIM_017_SWBC_SBCC,17,SWBC,SBCC,2025-01-27T03:48:10.800000Z,2025-01-27T07:24:46.800000Z,3.61,2,DIURNO,,
nao_cumprida,,,RV2025_OM10_E1_L19_C19,10,SBMN,SBMN,2025-01-08T22:30:00Z,2025-01-08T23:15:00Z,0.75,1,NOTURNO,2803,19 cumprida,2811,8,SIM_018_SBMY_SBPV,18,SBMY,SBPV,2025-01-28T01:55:19.200000Z,2025-01-28T03:00:07.200000Z,1.08,2,DIURNO,,
nao_cumprida,,,RV2025_OM9_E2_L21_C21,9,SBMN,SBMN,2025-01-09T18:10:00Z,2025-01-09T20:00:00Z,1.83,1,DIURNO,2803,21
nao_cumprida,,,RV2025_OM11_E1_L23_C23,11,SBMN,SBMN,2025-01-10T12:10:00Z,2025-01-10T13:15:00Z,1.08,1,DIURNO,2803,23
nao_cumprida,,,RV2025_OM11_E2_L24_C24,11,SBMN,SBMN,2025-01-10T14:25:00Z,2025-01-10T15:25:00Z,1.00,1,DIURNO,2803,24
nao_cumprida,,,RV2025_OM13_E1_L30_C30,13,SBMN,SBMN,2025-01-12T12:20:00Z,2025-01-12T13:10:00Z,0.83,1,DIURNO,2809,30
nao_cumprida,,,RV2025_OM15_E2_L35_C35,15,SBMN,SBMN,2025-01-12T14:25:00Z,2025-01-12T16:00:00Z,1.58,1,DIURNO,2803,35
nao_cumprida,,,RV2025_OM13_E2_L31_C31,13,SBMN,SBMN,2025-01-12T14:40:00Z,2025-01-12T15:25:00Z,0.75,1,DIURNO,2809,31
nao_cumprida,,,RV2025_OM15_E3_L36_C36,15,SBMN,SBMN,2025-01-12T18:30:00Z,2025-01-12T20:35:00Z,2.08,1,DIURNO,2803,36
nao_cumprida,,,RV2025_OM14_E2_L33_C37,14,SBMN,SBMN,2025-01-12T22:45:00Z,2025-01-13T02:05:00Z,3.33,1,NOTURNO,2809,33;37
nao_cumprida,,,RV2025_OM16_E1_L38_C38,16,SBMN,SBMN,2025-01-15T12:00:00Z,2025-01-15T15:05:00Z,3.08,1,DIURNO,2803,38
nao_cumprida,,,RV2025_OM17_E2_L41_C41,17,SBMN,SBMN,2025-01-15T14:45:00Z,2025-01-15T15:40:00Z,0.92,1,DIURNO,2809,41
nao_cumprida,,,RV2025_OM16_E2_L39_C39,16,SBMN,SBMN,2025-01-15T17:35:00Z,2025-01-15T20:35:00Z,3.00,1,DIURNO,2803,39
nao_cumprida,,,RV2025_OM18_E1_L46_C46,18,SBMN,SBMN,2025-01-21T12:05:00Z,2025-01-21T13:40:00Z,1.58,1,DIURNO,2800,46
nao_cumprida,,,RV2025_OM18_E2_L47_C47,18,SBMN,SBMN,2025-01-21T14:45:00Z,2025-01-21T16:15:00Z,1.50,1,DIURNO,2800,47
nao_cumprida,,,RV2025_OM18_E3_L48_C48,18,SBMN,SBMN,2025-01-21T18:40:00Z,2025-01-21T20:40:00Z,2.00,1,DIURNO,2800,48
nao_cumprida,,,RV2025_OM19_E1_L49_C49,19,SBMN,SBMN,2025-01-22T14:55:00Z,2025-01-22T16:00:00Z,1.08,1,DIURNO,2800,49
nao_cumprida,,,RV2025_OM20_E1_L51_C51,20,SBMN,SBMN,2025-01-22T14:55:00Z,2025-01-22T16:00:00Z,1.08,1,DIURNO,2803,51
nao_cumprida,,,RV2025_OM21_E1_L53_C53,21,SBMN,SBMN,2025-01-22T14:55:00Z,2025-01-22T16:00:00Z,1.08,1,DIURNO,2809,53
nao_cumprida,,,RV2025_OM22_E1_L55_C55,22,SBMN,SBMN,2025-01-22T14:55:00Z,2025-01-22T15:55:00Z,1.00,1,DIURNO,2811,55
nao_cumprida,,,RV2025_OM19_E2_L50_C50,19,SBMN,SBMN,2025-01-22T20:50:00Z,2025-01-22T21:25:00Z,0.58,1,DIURNO,2800,50
nao_cumprida,,,RV2025_OM20_E2_L52_C52,20,SBMN,SBMN,2025-01-22T20:50:00Z,2025-01-22T21:25:00Z,0.58,1,DIURNO,2803,52
nao_cumprida,,,RV2025_OM21_E2_L54_C54,21,SBMN,SBMN,2025-01-22T20:50:00Z,2025-01-22T21:25:00Z,0.58,1,DIURNO,2809,54
nao_cumprida,,,RV2025_OM22_E2_L56_C56,22,SBMN,SBMN,2025-01-22T20:50:00Z,2025-01-22T21:25:00Z,0.58,1,DIURNO,2811,56
nao_cumprida,,,RV2025_OM27_E1_L68_C68,27,SBMN,SBMN,2025-01-28T12:05:00Z,2025-01-28T13:05:00Z,1.00,1,DIURNO,2803,68
nao_cumprida,,,RV2025_OM25_E1_L64_C64,25,SBMN,SBMN,2025-01-28T13:25:00Z,2025-01-28T14:30:00Z,1.08,1,DIURNO,2809,64
nao_cumprida,,,RV2025_OM27_E2_L69_C69,27,SBMN,SBMN,2025-01-28T14:35:00Z,2025-01-28T15:30:00Z,0.92,1,DIURNO,2803,69
nao_cumprida,,,RV2025_OM26_E1_L65_C70,26,SBMN,SBMN,2025-01-28T23:10:00Z,2025-01-29T00:50:00Z,1.67,1,NOTURNO,2809,65;66;67;70
nao_cumprida,,,RV2025_OM28_E1_L71_C71,28,SBMN,SBMN,2025-01-29T18:15:00Z,2025-01-29T19:25:00Z,1.17,1,DIURNO,2809,71
nao_cumprida,,,RV2025_OM29_E1_L72_C72,29,SBMN,SBMN,2025-01-29T22:50:00Z,2025-01-30T00:00:00Z,1.17,1,NOTURNO,2809,72
1 status aeronave ordem id om orig dest partida_utc chegada_utc dur_h prioridade periodo aeronave_real_2025 linhas_origem
2 cumprida 2800 1 RV2025_OM1_E2_L5_C5 SIM_007_SBMN_SBCO 1 7 SBMN SBMN SBCO 2025-01-02T14:30:00Z 2025-01-09T02:09:28.800000Z 2025-01-02T15:35:00Z 2025-01-09T07:58:40.800000Z 1.08 5.82 1 NOTURNO DIURNO 2809 5
3 cumprida 2800 2 RV2025_OM5_E2_L13_C13 SIM_010_SBCY_SBMN 5 10 SBMN SBCY SBMN 2025-01-07T14:15:00Z 2025-01-11T23:29:27.600000Z 2025-01-07T16:15:00Z 2025-01-12T03:09:39.600000Z 2.00 3.67 1 3 DIURNO 2803 13
4 cumprida 2803 2800 1 3 RV2025_OM7_E1_L15_C15 SIM_012_SWCA_SBTT 7 12 SBMN SWCA SBMN SBTT 2025-01-07T10:40:00Z 2025-01-12T14:52:01.200000Z 2025-01-07T12:30:00Z 2025-01-12T16:14:49.200000Z 1.83 1.38 1 3 DIURNO 2809 15
5 cumprida 2803 2800 2 4 RV2025_OM8_E1_L17_C17 SIM_019_SBMN_SWCA 8 19 SBMN SBMN SWCA 2025-01-08T10:35:00Z 2025-01-29T04:57:54Z 2025-01-08T12:35:00Z 2025-01-29T06:36:54Z 2.00 1.65 1 DIURNO 2803 17
6 cumprida 2803 2800 3 5 RV2025_OM12_E4_L28_C29 SIM_020_SWCA_SBCO 12 20 SBMN SWCA SBMN SBCO 2025-01-11T21:05:00Z 2025-01-31T03:09:10.800000Z 2025-01-12T00:00:00Z 2025-01-31T08:39:46.800000Z 2.92 5.51 1 2 DIURNO;NOTURNO DIURNO 2809 28;29
7 cumprida inspecao 2803 2800 4 RV2025_OM15_E1_L34_C34 INSP_2800_3 15 INSP 2A SBMN SBMN 2025-01-12T11:50:00Z 2025-01-12T16:14:49.200000Z 2025-01-12T13:30:00Z 2025-01-16T16:14:49.200000Z 1.67 96.00 1 DIURNO 2803 34
8 cumprida 2809 2803 1 RV2025_OM1_E1_L4_C4 SIM_006_SWBC_SBAN 1 6 SBMN SWBC SBMN SBAN 2025-01-02T11:55:00Z 2025-01-06T21:08:24Z 2025-01-02T13:05:00Z 2025-01-07T00:56:24Z 1.17 3.80 1 2 NOTURNO DIURNO 2809 4
9 cumprida 2811 2809 1 RV2025_OM3_E1_L8_C8 SIM_001_SBBE_SBMN 3 1 SBMN SBBE SBMN 2025-01-03T14:45:00Z 2025-01-02T07:53:34.800000Z 2025-01-03T16:10:00Z 2025-01-02T11:07:22.800000Z 1.42 3.23 1 2 DIURNO 2809 8
10 cumprida 2811 2809 2 RV2025_OM4_E2_L10_C10 SIM_002_SBPV_SBOI 4 2 SBMN SBPV SBMN SBOI 2025-01-06T15:40:00Z 2025-01-03T03:03:10.800000Z 2025-01-06T16:45:00Z 2025-01-03T09:37:58.800000Z 1.08 6.58 1 3 DIURNO 2803 10
11 cumprida 2811 2809 3 RV2025_OM9_E1_L20_C20 SIM_005_SBMY_SBYS 9 5 SBMN SBMY SBMN SBYS 2025-01-09T12:30:00Z 2025-01-04T19:37:19.200000Z 2025-01-09T15:55:00Z 2025-01-05T01:06:43.200000Z 3.42 5.49 1 DIURNO 2803 20
12 cumprida 2811 2809 4 RV2025_OM9_E3_L22_C22 SIM_008_SBPV_SBMN 9 8 SBMN SBPV SBMN 2025-01-09T20:40:00Z 2025-01-09T23:11:34.800000Z 2025-01-09T22:15:00Z 2025-01-10T00:51:10.800000Z 1.58 1.66 1 2 DIURNO 2803 22
13 cumprida 2811 2809 5 RV2025_OM14_E1_L32_C32 SIM_011_SBSN_SBVH 14 11 SBMN SBSN SBMN SBVH 2025-01-12T16:55:00Z 2025-01-12T01:26:24Z 2025-01-12T20:25:00Z 2025-01-12T04:15:36Z 3.50 2.82 1 DIURNO 2809 32
14 cumprida 2811 2809 6 RV2025_OM17_E1_L40_C40 SIM_016_SBTF_SBMN 17 16 SBMN SBTF SBMN 2025-01-15T13:30:00Z 2025-01-24T15:25:55.200000Z 2025-01-15T14:25:00Z 2025-01-24T16:40:19.200000Z 0.92 1.24 1 3 DIURNO 2809 40
15 cumprida inspecao 2811 2809 7 RV2025_OM17_E3_L42_C45 INSP_2809_3 17 INSP 2A SBMN SBMN 2025-01-15T22:50:00Z 2025-01-05T01:06:43.200000Z 2025-01-15T23:50:00Z 2025-01-09T01:06:43.200000Z 1.00 96.00 1 NOTURNO 2809 42;43;44;45
16 nao_cumprida cumprida 2811 1 RV2025_OM2_E3_L6_C6 SIM_003_SBMN_SBUY 2 3 SBMN SBMN SBUY 2025-01-02T17:00:00Z 2025-01-03T09:50:20.400000Z 2025-01-02T18:05:00Z 2025-01-03T16:17:56.400000Z 1.08 6.46 1 2 NOTURNO DIURNO 2809 6
17 nao_cumprida cumprida 2811 2 RV2025_OM2_E4_L7_C7 SIM_004_SWCA_SBMN 2 4 SBMN SWCA SBMN 2025-01-02T20:00:00Z 2025-01-04T03:01:19.200000Z 2025-01-02T21:10:00Z 2025-01-04T04:51:43.200000Z 1.17 1.84 1 3 NOTURNO DIURNO 2809 7
18 nao_cumprida cumprida 2811 3 RV2025_OM5_E1_L11_C11 SIM_009_SBUY_SBCC 5 9 SBMN SBUY SBMN SBCC 2025-01-06T19:10:00Z 2025-01-11T12:27:50.400000Z 2025-01-06T21:20:00Z 2025-01-11T17:17:02.400000Z 2.17 4.82 1 DIURNO 2803 11
19 nao_cumprida cumprida 2811 4 RV2025_OM6_E1_L12_C12 SIM_013_SBUY_SBMN 6 13 SBMN SBUY SBMN 2025-01-06T19:30:00Z 2025-01-15T01:13:04.800000Z 2025-01-06T21:25:00Z 2025-01-15T07:31:40.800000Z 1.92 6.31 1 3 DIURNO 2811 12
20 nao_cumprida cumprida 2811 5 RV2025_OM6_E2_L14_C14 SIM_014_SBBE_SBUA 6 14 SBMN SBBE SBMN SBUA 2025-01-07T11:20:00Z 2025-01-20T05:25:19.200000Z 2025-01-07T13:20:00Z 2025-01-20T10:31:55.200000Z 2.00 5.11 1 2 DIURNO 2811 14
21 nao_cumprida cumprida 2811 6 RV2025_OM7_E2_L16_C16 SIM_015_SBBE_SBTS 7 15 SBMN SBBE SBMN SBTS 2025-01-07T14:00:00Z 2025-01-21T05:22:01.200000Z 2025-01-07T15:45:00Z 2025-01-21T10:28:37.200000Z 1.75 5.11 1 4 DIURNO 2809 16
22 nao_cumprida cumprida 2811 7 RV2025_OM8_E2_L18_C18 SIM_017_SWBC_SBCC 8 17 SBMN SWBC SBMN SBCC 2025-01-08T14:00:00Z 2025-01-27T03:48:10.800000Z 2025-01-08T16:00:00Z 2025-01-27T07:24:46.800000Z 2.00 3.61 1 2 DIURNO 2803 18
23 nao_cumprida cumprida 2811 8 RV2025_OM10_E1_L19_C19 SIM_018_SBMY_SBPV 10 18 SBMN SBMY SBMN SBPV 2025-01-08T22:30:00Z 2025-01-28T01:55:19.200000Z 2025-01-08T23:15:00Z 2025-01-28T03:00:07.200000Z 0.75 1.08 1 2 NOTURNO DIURNO 2803 19
nao_cumprida RV2025_OM9_E2_L21_C21 9 SBMN SBMN 2025-01-09T18:10:00Z 2025-01-09T20:00:00Z 1.83 1 DIURNO 2803 21
nao_cumprida RV2025_OM11_E1_L23_C23 11 SBMN SBMN 2025-01-10T12:10:00Z 2025-01-10T13:15:00Z 1.08 1 DIURNO 2803 23
nao_cumprida RV2025_OM11_E2_L24_C24 11 SBMN SBMN 2025-01-10T14:25:00Z 2025-01-10T15:25:00Z 1.00 1 DIURNO 2803 24
nao_cumprida RV2025_OM13_E1_L30_C30 13 SBMN SBMN 2025-01-12T12:20:00Z 2025-01-12T13:10:00Z 0.83 1 DIURNO 2809 30
nao_cumprida RV2025_OM15_E2_L35_C35 15 SBMN SBMN 2025-01-12T14:25:00Z 2025-01-12T16:00:00Z 1.58 1 DIURNO 2803 35
nao_cumprida RV2025_OM13_E2_L31_C31 13 SBMN SBMN 2025-01-12T14:40:00Z 2025-01-12T15:25:00Z 0.75 1 DIURNO 2809 31
nao_cumprida RV2025_OM15_E3_L36_C36 15 SBMN SBMN 2025-01-12T18:30:00Z 2025-01-12T20:35:00Z 2.08 1 DIURNO 2803 36
nao_cumprida RV2025_OM14_E2_L33_C37 14 SBMN SBMN 2025-01-12T22:45:00Z 2025-01-13T02:05:00Z 3.33 1 NOTURNO 2809 33;37
nao_cumprida RV2025_OM16_E1_L38_C38 16 SBMN SBMN 2025-01-15T12:00:00Z 2025-01-15T15:05:00Z 3.08 1 DIURNO 2803 38
nao_cumprida RV2025_OM17_E2_L41_C41 17 SBMN SBMN 2025-01-15T14:45:00Z 2025-01-15T15:40:00Z 0.92 1 DIURNO 2809 41
nao_cumprida RV2025_OM16_E2_L39_C39 16 SBMN SBMN 2025-01-15T17:35:00Z 2025-01-15T20:35:00Z 3.00 1 DIURNO 2803 39
nao_cumprida RV2025_OM18_E1_L46_C46 18 SBMN SBMN 2025-01-21T12:05:00Z 2025-01-21T13:40:00Z 1.58 1 DIURNO 2800 46
nao_cumprida RV2025_OM18_E2_L47_C47 18 SBMN SBMN 2025-01-21T14:45:00Z 2025-01-21T16:15:00Z 1.50 1 DIURNO 2800 47
nao_cumprida RV2025_OM18_E3_L48_C48 18 SBMN SBMN 2025-01-21T18:40:00Z 2025-01-21T20:40:00Z 2.00 1 DIURNO 2800 48
nao_cumprida RV2025_OM19_E1_L49_C49 19 SBMN SBMN 2025-01-22T14:55:00Z 2025-01-22T16:00:00Z 1.08 1 DIURNO 2800 49
nao_cumprida RV2025_OM20_E1_L51_C51 20 SBMN SBMN 2025-01-22T14:55:00Z 2025-01-22T16:00:00Z 1.08 1 DIURNO 2803 51
nao_cumprida RV2025_OM21_E1_L53_C53 21 SBMN SBMN 2025-01-22T14:55:00Z 2025-01-22T16:00:00Z 1.08 1 DIURNO 2809 53
nao_cumprida RV2025_OM22_E1_L55_C55 22 SBMN SBMN 2025-01-22T14:55:00Z 2025-01-22T15:55:00Z 1.00 1 DIURNO 2811 55
nao_cumprida RV2025_OM19_E2_L50_C50 19 SBMN SBMN 2025-01-22T20:50:00Z 2025-01-22T21:25:00Z 0.58 1 DIURNO 2800 50
nao_cumprida RV2025_OM20_E2_L52_C52 20 SBMN SBMN 2025-01-22T20:50:00Z 2025-01-22T21:25:00Z 0.58 1 DIURNO 2803 52
nao_cumprida RV2025_OM21_E2_L54_C54 21 SBMN SBMN 2025-01-22T20:50:00Z 2025-01-22T21:25:00Z 0.58 1 DIURNO 2809 54
nao_cumprida RV2025_OM22_E2_L56_C56 22 SBMN SBMN 2025-01-22T20:50:00Z 2025-01-22T21:25:00Z 0.58 1 DIURNO 2811 56
nao_cumprida RV2025_OM27_E1_L68_C68 27 SBMN SBMN 2025-01-28T12:05:00Z 2025-01-28T13:05:00Z 1.00 1 DIURNO 2803 68
nao_cumprida RV2025_OM25_E1_L64_C64 25 SBMN SBMN 2025-01-28T13:25:00Z 2025-01-28T14:30:00Z 1.08 1 DIURNO 2809 64
nao_cumprida RV2025_OM27_E2_L69_C69 27 SBMN SBMN 2025-01-28T14:35:00Z 2025-01-28T15:30:00Z 0.92 1 DIURNO 2803 69
nao_cumprida RV2025_OM26_E1_L65_C70 26 SBMN SBMN 2025-01-28T23:10:00Z 2025-01-29T00:50:00Z 1.67 1 NOTURNO 2809 65;66;67;70
nao_cumprida RV2025_OM28_E1_L71_C71 28 SBMN SBMN 2025-01-29T18:15:00Z 2025-01-29T19:25:00Z 1.17 1 DIURNO 2809 71
nao_cumprida RV2025_OM29_E1_L72_C72 29 SBMN SBMN 2025-01-29T22:50:00Z 2025-01-30T00:00:00Z 1.17 1 NOTURNO 2809 72

View File

@@ -14,6 +14,31 @@ Formato:
--- ---
## v0.10 — VTO — 2026-06
### Alterado
- **Set Covering → Set Partitioning (C1):** a restrição de cobertura de missões foi alterada de `Σ_k y_entrada ≤ 1` (Set Covering — missão opcional) para `Σ_k y_entrada = 1` (Set Partitioning — toda missão obrigatória). Isso reflete a premissa operacional de que cada missão deve ser realizada por exatamente uma aeronave, sem possibilidade de missões descobertas. A distinção anterior entre missões "hard" (EVAM) e "opcionais" foi eliminada.
- **Número padrão de missões sintéticas reduzido de 50 para 20** (`--n-missoes`, `n_evam` de 5 para 4): Set Partitioning é mais restritivo e, com janelas de tempo fixas e restrições de inspeção simultâneas, 50 missões tornavam o MIP difícil de resolver ou inviável. Com 20 missões, a factibilidade é garantida na margem operacional de 4 aeronaves.
- **Time limit padrão do solver CBC fixado em 120 s** (era ilimitado). O solver agora nunca trava indefinidamente; retorna a melhor solução encontrada dentro do prazo. O CLI mantém `--time-limit` para ajuste.
- **Correção de display do status do solver:** PuLP redefinía `mdl.status` para "Not Solved" ao reutilizar o modelo em L2 (após `setObjective`). O status de L1 é agora preservado quando L2 reporta 0, evitando exibição enganosa.
- **Cenário `f0_cenario_insp_grande.json` revisado:** apenas a matrícula 2803 recebe `f0=595h` para INSP 2A (F_max=600h, downtime=4 dias), forçando a inspeção aparecer no Gantt. As demais matrículas partem com `f0=0` (plena disponibilidade), evitando que o problema se torne inviável por múltiplos relógios apertados simultaneamente.
### Adicionado
- `db/processed/planejamento_insp_grande.html`: visualização Gantt + mapa + tabela para o cenário com inspeção de 4 dias (INSP 2A — INSP CHECK 2A, 96 h de solo).
### Limitações conhecidas (para contribuidores)
1. **Escopo validado restrito:** Set Partitioning foi validado apenas para o cenário sintético com 20 missões, seed 42, 4 aeronaves e somente uma matrícula (2803) com LRT apertado. Fora desse envelope, o MIP pode ser infeasible ou ultrapassar o time limit sem solução.
2. **Missões sintéticas incluem bases fora da Amazônia** (SBBR, SBGL, SBYS etc.) geradas aleatoriamente pelo seed. Para estudos de caso realistas, o gerador deve ser restrito ao conjunto de bases do Esquadrão Arara.
3. **Folga negativa no relatório:** quando uma aeronave realiza inspeção dentro do horizonte, o campo `folga` exibido (`LRT_ini horas_celula_total`) pode ser negativo porque não desconta o reset do relógio pós-inspeção. Isso é um bug de display; a restrição `H ≤ F_max` está correta no modelo.
4. **LRT muito curto (< 5 h) pode gerar instabilidade numérica no big-M:** o cenário foi configurado com LRT_ini=5 h para 2803, que está próximo do limiar onde o big-M deixa de ser eficaz. Valores menores podem permitir que o solver ignore a restrição por tolerância numérica (ε ≈ 1 e-4 do CBC).
5. **Aeronave 2811 fica ociosa neste cenário:** o solver atribui todas as 20 missões a 3 aeronaves. Isso é matematicamente ótimo, mas pode não ser desejável operacionalmente. Considerar restrição de equilíbrio de carga em versões futuras.
6. **Status "Not Solved" após L2:** a correção atual usa o status de L1 como proxy. Se L1 retornar apenas uma solução feasível (não ótima, por time limit), o modelo pode ser reportado como "Optimal" quando não é. Monitorar o campo `prio_otima` para validar.
---
## v0.2 — VTO — 2026-06 ## v0.2 — VTO — 2026-06
### Adicionado ### Adicionado

View File

@@ -474,9 +474,7 @@ def resolver(
y[(k, a.id)] for a in arcs if (k, a.id) in y y[(k, a.id)] for a in arcs if (k, a.id) in y
) )
# --- C1: Cobertura e definição de z --- # --- C1: Cobertura — Set Partitioning: toda missão coberta por exatamente 1 aeronave ---
# Missões normais: Σ_k y_entrada ≤ 1 (cobertura opcional)
# Missões obrigatórias (M_obr / EVAM): Σ_k y_entrada == 1
for nid, n in missoes_nos.items(): for nid, n in missoes_nos.items():
fluxo_entrada = pulp.lpSum( fluxo_entrada = pulp.lpSum(
y[(k, a.id)] y[(k, a.id)]
@@ -485,10 +483,7 @@ def resolver(
if (k, a.id) in y if (k, a.id) in y
) )
mdl += fluxo_entrada == z[nid], f"def_z_{nid}" mdl += fluxo_entrada == z[nid], f"def_z_{nid}"
if n.missao.obrigatoria: mdl += z[nid] == 1, f"part_{nid}"
mdl += z[nid] == 1, f"hard_{nid}"
else:
mdl += z[nid] <= 1, f"cob_{nid}"
# --- C2: Conservação de fluxo por (aeronave, nó) --- # --- C2: Conservação de fluxo por (aeronave, nó) ---
for k in ks: for k in ks:
@@ -676,14 +671,13 @@ def resolver(
# já impõe o limite LRT por ciclo corretamente. A versão simplificada somava # já impõe o limite LRT por ciclo corretamente. A versão simplificada somava
# horas totais sem respeitar resets de inspeção, super-restringindo o modelo. # horas totais sem respeitar resets de inspeção, super-restringindo o modelo.
time_limit = kwargs.get("time_limit", 0) time_limit = kwargs.get("time_limit", 120)
solver = pulp.PULP_CBC_CMD(msg=False, timeLimit=time_limit if time_limit > 0 else None) solver = pulp.PULP_CBC_CMD(msg=False, timeLimit=time_limit)
mdl.solve(solver) mdl.solve(solver)
status_l1 = mdl.status
prio_otima = int(round(pulp.value(mdl.objective) or 0)) prio_otima = int(round(pulp.value(mdl.objective) or 0))
# L2: com prioridade fixada, minimiza folga de horas ao fim do horizonte. # L2: com prioridade fixada, maximiza horas voadas.
# folga_k = orcamento_k horas_voadas_k
# Minimizar Σ_k folga_k ⟺ maximizar Σ_k horas_voadas_k (orcamento é constante).
mdl += ( mdl += (
pulp.lpSum(n.missao.prioridade * z[nid] for nid, n in missoes_nos.items()) pulp.lpSum(n.missao.prioridade * z[nid] for nid, n in missoes_nos.items())
== prio_otima, == prio_otima,
@@ -698,7 +692,10 @@ def resolver(
) )
mdl.sense = pulp.LpMaximize mdl.sense = pulp.LpMaximize
mdl.setObjective(horas_voadas) mdl.setObjective(horas_voadas)
mdl.solve(pulp.PULP_CBC_CMD(msg=False, timeLimit=time_limit if time_limit > 0 else None)) mdl.solve(pulp.PULP_CBC_CMD(msg=False, timeLimit=time_limit))
# PuLP redefine mdl.status após setObjective; preservar o status real (L1).
if mdl.status == 0 and status_l1 == 1:
mdl.status = status_l1
return { return {
"modelo": mdl, "modelo": mdl,
@@ -1312,11 +1309,11 @@ _PESOS_PRIO = [35, 30, 20, 10, 5]
def gerar_missoes_sinteticas( def gerar_missoes_sinteticas(
n: int = 50, n: int = 20,
seed: Optional[int] = 42, seed: Optional[int] = 42,
inicio: Optional[datetime] = None, inicio: Optional[datetime] = None,
horizonte_h: float = 744.0, # janeiro = 31 × 24 horizonte_h: float = 744.0, # janeiro = 31 × 24
n_evam: int = 5, n_evam: int = 4,
bases: Optional[list[str]] = None, bases: Optional[list[str]] = None,
ofrag_path: Optional[Path] = None, ofrag_path: Optional[Path] = None,
) -> tuple[list[Missao], datetime]: ) -> tuple[list[Missao], datetime]:
@@ -1498,20 +1495,25 @@ def main() -> None:
help="Usa missões sintéticas cross-base em vez do CSV real.", help="Usa missões sintéticas cross-base em vez do CSV real.",
) )
parser.add_argument( parser.add_argument(
"--n-missoes", type=int, default=50, "--n-missoes", type=int, default=20,
help="Número de missões sintéticas a gerar (padrão: 50).", help="Número de missões sintéticas a gerar (padrão: 20).",
) )
parser.add_argument( parser.add_argument(
"--n-evam", type=int, default=5, "--n-evam", type=int, default=4,
help="Missões obrigatórias (EVAM/hard) nas sintéticas (padrão: 5).", help="Missões obrigatórias (EVAM/hard) nas sintéticas (padrão: 4).",
) )
parser.add_argument( parser.add_argument(
"--ofrag", type=Path, default=None, metavar="CSV", "--ofrag", type=Path, default=None, metavar="CSV",
help="CSV de OFRAG com prioridades por missão (missao_id, prioridade).", help="CSV de OFRAG com prioridades por missão (missao_id, prioridade).",
) )
parser.add_argument( parser.add_argument(
"--time-limit", type=int, default=300, dest="time_limit", "--time-limit", type=int, default=120, dest="time_limit",
help="Limite de tempo em segundos para o solver CBC (padrão: 60). 0 = sem limite.", help="Limite de tempo em segundos para o solver CBC (padrão: 120).",
)
parser.add_argument(
"--insp-seqs", type=int, nargs="+", default=None, dest="insp_seqs",
metavar="SEQ",
help="Filtra catálogo para apenas estes seq de inspeção (ex: --insp-seqs 3).",
) )
args = parser.parse_args() args = parser.parse_args()
@@ -1519,6 +1521,8 @@ def main() -> None:
fim = datetime.fromisoformat(args.fim).replace(tzinfo=timezone.utc) fim = datetime.fromisoformat(args.fim).replace(tzinfo=timezone.utc)
catalogo = carregar_inspecoes(args.inspecoes) catalogo = carregar_inspecoes(args.inspecoes)
if args.insp_seqs:
catalogo = {s: v for s, v in catalogo.items() if s in args.insp_seqs}
if args.escala: if args.escala:
missoes, horizonte_dt = carregar_escala(args.escala, inicio) missoes, horizonte_dt = carregar_escala(args.escala, inicio)