Skip to content

Feat/strict hardmask - #33

Open
pkhyrn268 wants to merge 15 commits into
mainfrom
feat/strict-hardmask
Open

Feat/strict hardmask#33
pkhyrn268 wants to merge 15 commits into
mainfrom
feat/strict-hardmask

Conversation

@pkhyrn268

@pkhyrn268 pkhyrn268 commented Aug 20, 2026

Copy link
Copy Markdown
Contributor

작업 목적

기존 모델에서는 pairing의 base 출발·복귀 조건이 일부 실행 옵션과 reward penalty에 의존하고 있었음.

그 결과 실행 경로에 따라 다음 문제가 발생할 수 있었음.

  • base가 아닌 공항에서 pairing 시작
  • 허용 home base에 복귀할 수 없는 flight 선택
  • 허용되지 않은 공항에서 pairing 종료
  • 합법 action이 없을 때 임의 공항 또는 flight로 재시작
  • mask를 거치지 않고 step()을 직접 호출하여 CPP 제약 우회
  • 불완전한 partial pairing이 candidate pool에 포함
  • single rollout과 batch rollout의 legality 차이
  • Phase I, Phase II, 최종 평가 사이의 pairing 정의 불일치
  • 일부 flight가 미커버된 결과를 완전한 CPP 결과처럼 출력

본 PR에서는 이러한 경로를 제거하고, 항공사별 home-base 규칙을 CPP 실행 전체에서 항상 적용되는 불변조건으로 통일함.

주요 변경 사항

1. Base 출발 조건 상시 적용

  • 모든 pairing의 첫 flight를 허용된 home base 출발편으로 제한
  • base 출발편이 없다고 해서 다른 공항의 flight로 pairing을 강제 시작하지 않음
  • strict 관련 option 값으로 base 출발 조건을 끌 수 없도록 변경
  • base 정보가 누락된 경우 임의 기본 공항을 사용하지 않고 구성 오류로 처리

2. Base 복귀 가능성 기반 hard mask 적용

  • 각 flight 선택 이후 허용 home base로 복귀 가능한지 backward reachability로 검사
  • 제한 내 복귀할 수 없는 flight를 decoder 선택 전에 mask에서 제거
  • 다음 resource를 고려하여 복귀 가능성 판정
    • 최대 pairing 기간
    • 현재 duty period
    • 최대 duty period 수
    • 연결 가능한 후속 flight 경로

일반 항공사는 현재 pairing이 시작한 base를 대상으로 reachability를 계산함.

Turkish는 HB1과 HB2 각각의 reachability를 계산하고, 둘 중 하나로 복귀 가능하면 candidate를 허용함.

3. EndPairing legality 강제

EndPairing은 다음 조건을 모두 만족할 때만 허용함.

  • 최소 pairing leg 수 만족
  • 최대 pairing 기간 이내
  • 항공사별 허용 home base 도착

일반 항공사:

현재 공항 = pairing 시작 base

Turkish:

현재 공항 ∈ {HB1, HB2}

decoder mask뿐 아니라 step() 내부에서도 동일 조건을 다시 확인함.

mask를 거치지 않고 EndPairing을 직접 호출하더라도 조건 위반 시 ValueError가 발생하도록 변경함.

4. Flight 및 EndDuty 직접 호출 우회 차단

기존에는 decoder가 mask를 사용하더라도 외부 코드가 step()을 직접 호출하면 일부 제약을 우회할 수 있었음.

다음 검증을 step() 내부에 추가함.

  • action index 범위 검사
  • flight action의 현재 mask 재검사
  • EndDuty의 현재 mask 재검사
  • EndPairing의 현재 mask 재검사

처리 방식:

  • 음수 또는 N+2 이상 action: IndexError
  • mask가 0인 flight 직접 선택: ValueError
  • 불법 EndDuty 직접 호출: ValueError
  • 불법 EndPairing 직접 호출: ValueError

stateassigned를 변경하기 전에 오류가 발생하도록 처리함.

5. All-zero 및 막다른 상태 처리 수정

다음 action이 모두 불가능한 상태를 all-zero 상태로 정의함.

  • 선택 가능한 flight 없음
  • EndDuty 불가
  • EndPairing 불가

기존에는 이 상태에서 다음 동작이 발생할 수 있었음.

  • 임의 공항으로 이동
  • 가장 이른 unassigned flight로 강제 재시작
  • base에 있다는 이유만으로 짧은 pairing 강제 저장
  • 미복귀 partial pairing 저장

현재 처리 방식:

  1. 현재 pairing의 leg 기록 확인
  2. 가장 긴 합법 home-base 복귀 prefix 탐색
  3. 다음 조건을 만족하는 prefix만 보존
    • 허용 home base 도착
    • 최소 pairing leg 수 만족
    • 최대 pairing 기간 만족
  4. prefix 이후 tail leg를 unassigned 상태로 반환
  5. 합법 prefix가 없으면 partial pairing 전체를 저장하지 않음
  6. 동일 starter의 무한 재시도를 막기 위해 bad starter로 기록
  7. 다른 합법 starter가 없으면 rollout 종료

임의 공항 이동과 arbitrary restart는 수행하지 않음.

6. Pairing 저장 경계 검증 추가

mask의 정상 동작에만 의존하지 않고 candidate pool에 pairing을 추가하기 직전에 legality를 다시 검사함.

검사 항목:

  • 허용 home base에서 시작했는지
  • 허용 home base로 복귀했는지
  • 최소 pairing leg 수를 만족하는지
  • 최대 pairing 기간을 초과하지 않는지

검사를 통과하지 못한 pairing은 pool에 추가하지 않거나 ValueError로 처리함.

동일 검사를 다음 경로에 적용함.

  • 일반 rollout pool
  • salvage prefix
  • Phase II dual pool
  • 최종 평가 pool

7. Single 및 batch rollout 계약 통일

기존 vectorized batch rollout은 single rollout과 lifecycle이 달랐으며, 다음 처리가 완전히 동일하지 않았음.

  • base rotation
  • reachability
  • all-zero 처리
  • salvage
  • pairing 저장 검증

현재는 correctness가 검증된 single rollout을 batch 크기만큼 실행하도록 변경함.

rollout_batch(B)
  → rollout_with_pairings() B회 실행

이에 따라 single과 batch에서 같은 CPP legality를 보장함.

현재 구현은 속도보다 correctness를 우선함.

동일 lifecycle을 유지하는 vectorization은 후속 작업으로 분리함.

8. Phase I 학습 경로 정합화

모든 학습 episode에서 항공사별 home-base reachability를 구성함.

변경 사항:

  • 일반 항공사는 episode base reachability 구성
  • Turkish는 HB1/HB2 reachability 모두 구성
  • 동일 episode와 base 집합에서는 계산 결과 재사용
  • all-zero 상태에서 강제 deadhead 또는 arbitrary restart 제거
  • 합법 action이 없으면 미커버 상태로 episode 종료
  • 미커버 flight 수를 metric과 final reward에 반영

관련 metric:

  • n_uncovered
  • coverage_pct
  • n_zero_mask
  • n_deadheads
  • n_pairings

9. Phase II dual pool 정합화

Phase II의 restricted LP와 dual 학습에 infeasible column이 들어가지 않도록 수정함.

변경 사항:

  • 첫 flight도 허용 home base 출발 여부와 복귀 가능성 검사
  • all-zero에서 미복귀 partial pairing 미저장
  • flush 직전 home-base 복귀 여부 재검사
  • 최소 leg 및 최대 기간 재검사
  • 합법 column만 restricted LP와 dual 계산에 사용

이를 통해 infeasible pairing이 dual signal을 왜곡하는 경로를 차단함.

10. 최종 평가 correctness 강화

평가 함수와 CLI에서 base-return 검사를 끄는 option을 제거함.

각 평가 chunk에서 local flight ID 기준 reachability를 구성함.

항공사별 pairing 유효성 판정:

  • 일반 항공사: 시작 base와 종료 base 동일 여부 확인
  • Turkish: 시작과 종료가 HB1/HB2 home-base 집합에 포함되는지 확인

최종 set-covering 결과가 다음 중 하나에 해당하면 완성된 CPP 결과로 보고하지 않음.

uncoverable > 0
coverage < 1.0

이 경우 RuntimeError를 발생시키며, 불완전 coverage 상태의 ManDays와 FTC 등을 최종 결과처럼 출력하지 않음.

변경된 주요 파일

  • RL/base_reach.py
    • 복수 home-base reachability 생성 및 판정 함수 추가
  • RL/environment.py
    • 일반 항공사 hard mask 및 direct action 검증
  • RL/turkish/environment_turkish.py
    • HB1/HB2 home-base 집합 기반 mask 및 종료 처리
  • RL/turkish/constraints_turkish.py
    • Turkish 교차 home-base 복귀 규칙 명시
  • RL/rollout.py
    • starter, reachability, salvage, flush, batch lifecycle 정합화
  • experiments/train.py
    • Phase I 및 Phase II constraint와 all-zero 처리 통일
  • evaluation/evaluate_ip.py
    • 항공사별 pool 유효성 검사 및 완전 coverage fail-fast
  • test/v1_strict_hardmask/
    • CPP correctness 회귀 테스트
  • result/v1_strict_hardmask/
    • 테스트 실행 결과

동작 변경 및 주의사항

  • 합법 action이 없는 episode는 임의 재시작하지 않고 미커버 상태로 종료됨
  • 불완전 coverage 결과는 정상 CPP 결과가 아니라 오류로 처리됨
  • batch rollout은 기존 vectorized 구현보다 느릴 수 있음
  • Turkish의 HB1/HB2 교차 home-base 복귀는 기존 문제 정의대로 유지됨
  • 일반 항공사의 동일-base 복귀 조건은 유지됨

후속 작업

  • 미커버 flight 대상 targeted rollout
  • 완전 coverage 확보용 repair column 생성
  • lambda_dh sweep
  • IP time limit sweep
  • deadhead penalty sweep
  • 동일 CPP lifecycle을 보존하는 batch vectorization
  • 대규모 데이터에서 coverage, 비용, 실행시간 검증

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant