ids.py 1.5 KB

123456789101112131415161718192021222324252627282930313233343536
  1. # utils/ids.py — path_id(1-origin) と idx(0-origin) の相互変換ユーティリティ
  2. from typing import Dict, Iterable
  3. def to_idx0(path_id_1origin: int) -> int:
  4. """1-origin の path_id を 0-origin の配列インデックスへ。"""
  5. return int(path_id_1origin) - 1
  6. def to_id1(idx0: int) -> int:
  7. """0-origin の配列インデックスを 1-origin の path_id へ。"""
  8. return int(idx0) + 1
  9. def is_keys_1origin(keys: Iterable[int], L: int) -> bool:
  10. """キー集合が 1..L を完全に満たすか(欠番なし)"""
  11. keys = list(keys)
  12. return bool(keys) and min(keys) == 1 and max(keys) == L and len(keys) == L
  13. def is_keys_0origin(keys: Iterable[int], L: int) -> bool:
  14. """キー集合が 0..L-1 を完全に満たすか(欠番なし)"""
  15. keys = list(keys)
  16. return bool(keys) and min(keys) == 0 and max(keys) == L - 1 and len(keys) == L
  17. def normalize_to_1origin(d: Dict[int, float], L: int) -> Dict[int, float]:
  18. """
  19. キーが 0..L-1 なら 1..L に正規化。すでに 1..L ならそのまま。
  20. 想定外は例外。
  21. """
  22. if not d:
  23. # 空の場合は 1..L の枠を用意して NaN など入れるより、呼び出し側で未測定扱いにするのが自然
  24. return d
  25. keys = list(d.keys())
  26. if is_keys_1origin(keys, L):
  27. return d
  28. if is_keys_0origin(keys, L):
  29. return {k + 1: v for k, v in d.items()}
  30. raise RuntimeError(f"unexpected key scheme for L={L}: keys={sorted(keys)[:6]}...")