時間管理

時間管理は、持ち時間の中で各手にどれだけ探索時間を配分するかを決める仕組みである。 実戦の将棋AIでは、探索そのものと同じくらい重要な要素である。

概要

どれだけ強い探索器でも、時間切れ負けしてしまえば意味がない。 そのため実戦エンジンでは、

  • 残り時間
  • 秒読みや加算
  • 現在の局面の難しさ
  • 探索の進み具合

を見ながら、今回の手に使う時間を決める。

基本形

基本的な配分としては、

  • 残り時間を残り手数見込みで割る
  • 秒読みや加算の一部を安全側に足す

という方法がよく使われる。

Chessprogramming Wiki でも、基礎形として base / 20 + increment / 2 のような簡潔な式が紹介されている。

反復深化との関係

反復深化と組み合わせると、

  • 反復の区切りで「次の深さへ進むか」を判断できる
  • 時間切れ直前でも直前反復の最善手を返せる

という利点がある。

そのため、時間管理は通常、反復深化のループの外側または周辺で実装される。

追加で考慮される要素

時間管理では、単純な等分だけでなく次のような情報も使われる。

  • 最善手が何度も入れ替わっているか
  • 評価値が大きく揺れているか
  • 読み筋が一つに絞れているか
  • 王手や大駒の取り合いなど、局面が鋭いか

たとえば、 「最善手が何度も変わる」 「評価値が急落した」 といった場合は、少し長く考える価値がある。

実装例

int allocateTime(int timeLeftMs, int incrementMs) {
    int base = timeLeftMs / 20;
    int bonus = incrementMs / 2;
    return std::max(1, base + bonus);
}

bool shouldStartNextIteration(int elapsedMs, int softLimitMs) {
    return elapsedMs < softLimitMs;
}

実際には、

  • ソフト上限
  • ハード上限
  • ノード数ごとの時計確認

を分けて実装することが多い。

将棋AIでの注意点

将棋では秒読みや加算が付く対局が多く、 通信遅延や GUI 連携の揺れもある。 そのため、理論上ぎりぎりまで使うのではなく、少し安全側にバッファを持たせる実装が一般的である。

関連項目

参考にしたホームページ