# 手の並べ替え

手の並べ替えは、探索で候補手を調べる順番を工夫する技術である。
[アルファベータ法](/shogi/shogiwiki/search/alpha-beta/)は良い手から先に読むほど枝刈りが増えるため、
探索速度を大きく左右する。

## 概要

[ミニマックス法](/shogi/shogiwiki/search/minimax/)では手順の順番は結果に影響しない。
しかし[アルファベータ法](/shogi/shogiwiki/search/alpha-beta/)では、
有望な手を先に調べるほど早く `alpha` や `beta` の境界が更新され、
後続の枝を省きやすくなる。

そのため、現代的な将棋AIでは
「どの手を先に読むか」は探索アルゴリズムそのものと同じくらい重要である。

## よく使われる順序

典型的には次のような順に試す。

- 前回反復の Principal Variation 手
- [置換表](/shogi/shogiwiki/search/transposition-table/)に入っている hash move
- 良い駒取り
- 昇格など価値の高い手
- [killer heuristic](/shogi/shogiwiki/search/killer-heuristic/) などの非捕獲手
- その他の手

将棋では、

- 王手
- 駒取り
- 成り
- 受けの手

の扱いがチェスより少し複雑になるが、基本思想は同じである。

## 代表的な材料

### Principal Variation 手

[反復深化](/shogi/shogiwiki/search/iterative-deepening/)の前回反復で最善だった手は、次の反復でも有望であることが多い。

### hash move

[置換表](/shogi/shogiwiki/search/transposition-table/)に保存された最善手は、最も重要な順序情報のひとつである。

### 捕獲手の優先順位

駒取りについては、

- MVV-LVA
- [Static Exchange Evaluation](/shogi/shogiwiki/search/static-exchange-evaluation/)

のような方法で優先順位を付けることが多い。

### 非捕獲手の履歴

- [killer heuristic](/shogi/shogiwiki/search/killer-heuristic/)
- [history heuristic](/shogi/shogiwiki/search/history-heuristic/)
- [countermove heuristic](/shogi/shogiwiki/search/countermove-heuristic/)

などが使われる。

## 実装例

単純化した例では、各手にスコアを付けて高い順に読む。

    int scoreMove(const Move& move, const Position& pos) {
        if (move == hashMove(pos)) return 1000000;
        if (isWinningCapture(move, pos)) return 900000;
        if (isKiller(move)) return 800000;
        return historyScore(move);
    }

    void orderMoves(std::vector<Move>& moves, const Position& pos) {
        std::sort(moves.begin(), moves.end(),
            [&](const Move& a, const Move& b) {
                return scoreMove(a, pos) > scoreMove(b, pos);
            });
    }

実際には全手を完全ソートせず、取り出し時に最大のものを選ぶ形もよく使われる。

## 将棋AIでの位置づけ

手の並べ替えは単独で最善手を決める技術ではないが、
探索効率への影響が非常に大きい。

特に、

- [反復深化](/shogi/shogiwiki/search/iterative-deepening/)
- [置換表](/shogi/shogiwiki/search/transposition-table/)
- [Late Move Reductions](/shogi/shogiwiki/search/late-move-reductions/)

と組み合わせると重要性がさらに増す。

## 注意点

- 良い順序付けができないと、アルファベータ法の利点が大きく落ちる
- 計算コストの高い並べ替えは、節約できるノード数と釣り合う必要がある
- ルート付近と深いノードでは、使う並べ替え手法を変えることも多い

## 関連項目

- [アルファベータ法](/shogi/shogiwiki/search/alpha-beta/)
- [反復深化](/shogi/shogiwiki/search/iterative-deepening/)
- [置換表](/shogi/shogiwiki/search/transposition-table/)
- [Static Exchange Evaluation](/shogi/shogiwiki/search/static-exchange-evaluation/)
- [killer heuristic](/shogi/shogiwiki/search/killer-heuristic/)
- [history heuristic](/shogi/shogiwiki/search/history-heuristic/)

## 参考にしたホームページ

- [Chessprogramming Wiki: Move Ordering](https://www.chessprogramming.org/Move_Ordering)
- [Chessprogramming Wiki: Search](https://www.chessprogramming.org/Search)
- [コンピュータ将棋のアルゴリズム HTML版](http://usapyon.game.coocan.jp/ComShogi/index.html)