🔎 詳細

やねうら王 — 日本将棋AIの探索基盤

やねうら王 は、やねうらお 氏が開発する将棋AIエンジン。 日本の将棋AI界では 探索エンジンのデファクトスタンダード であり、 「水匠」「Háo」「tanuki-」など、現在世界トップクラスの評価関数たちは すべて やねうら王の上で動いている。 このページでは、やねうら王の 歴史・アーキテクチャ・探索アルゴリズム・エコシステムを、 第7章第8章 よりも一段深く掘り下げます。

やねうら王とは何か(概要)

1

探索エンジンのデファクトスタンダード

やねうら王は 「指し手の探索」 を担う将棋AIエンジン本体。 評価関数(NNUE)は別に学習され、ファイル(nn.bin)で差し替え可能。

2

GitHubで完全オープンソース

ソースコードもビルド手順も公開。個人でも改造して大会に出られる。 やねうらお氏のブログ・著書で技術解説も豊富。

3

エコシステムの土台

「やねうら王 + 水匠」「やねうら王 + Háo」「やねうら王 + tanuki-」… 探索の達人評価関数の達人を分業させる構図を作った。

💡 核心: やねうら王の最大の功績は 「探索と評価関数を分離するインターフェース」 を整備したこと。 これにより、探索の改良評価関数の学習を別チームが並行して進められるようになり、 日本将棋AIは個人開発者の集合知で世界トップに上り詰めた。

1. 歴史 — やねうらお氏の歩み

やねうら王の歴史は、「将棋AIの民主化」 の歴史でもあります。 以下、主要な節目をたどります。

出来事 意義
2005年 Bonanza(保木邦仁氏)が機械学習で評価関数を獲得 「Bonanzaメソッド」の衝撃。やねうらお氏もこれに触発される
2013年頃 やねうらお氏が将棋AI開発に本格参入 Stockfish 系の探索を将棋に移植・改良
2015年 やねうら王を GitHub で公開 本格的なオープンソース化。世界中の開発者が改造できるように
2017年 第27回世界コンピュータ将棋選手権 で elmo(やねうら王ベース)が優勝 探索エンジンとしての地位を確立
2018年 NNUE(那須悠氏)の登場、やねうら王に統合 CPU 上の浅いMLP評価関数を載せた最強構成が誕生
2019年〜 水匠・たぬき・Háo などの評価関数チームが続々と「やねうら王 + 評価関数ファイル」で参戦 分業エコシステムの完成形
2020年代 ふかうら王(DL 版やねうら王)公開 NNUE 系だけでなく dlshogi 系の MCTS + 深いCNN も同じブランドでカバー
継続中 やねうらお氏のブログ・著書で技術解説 『コンピュータ将棋の進歩』『〜将棋AI開発でガチで使える本』など、後進への啓蒙
🏔️ 補足:やねうらお氏の人物像(クリックで展開)

やねうらお氏は、ハンドルネームで活動する個人開発者。本業はゲーム開発エンジニア。 Stockfish(チェス)の探索アルゴリズムを徹底的に読み込み、将棋向けに改造・拡張する形で やねうら王を育ててきた。

  • ブログ『やねうら王公式サイト』で 開発記録を逐一公開
  • 世界コンピュータ将棋選手権・電竜戦などに継続参戦
  • 著書を通じて「将棋AIの内部構造」を後進に伝える
  • 「個人でも世界トップを狙える」と示し続けたカリスマ

まっしー視点では「OSS と個人開発のロールモデル」として強く意識している人物。

📚 補足:Stockfish ベースから独自進化への流れ(クリックで展開)

やねうら王の初期は、チェスの世界最強オープンソースエンジン Stockfish の 探索コードを将棋に移植したものでした。

  • α-β + LMR + Null Move などの探索テクニックは Stockfish 由来
  • 将棋特有の「持ち駒」「成り」「打ち」を扱うため、指し手生成・置換表のキー設計を大幅改造
  • その後、定跡データベース・並列化・将棋特有の枝刈りなどで Stockfish とは別の方向へ進化

逆方向に、NNUE は 将棋発でチェス Stockfish に逆輸入 された珍しい例。日本発の発明が世界標準になった瞬間。

2. アーキテクチャ — 探索特化のエンジン

やねうら王の中身は大きく 4ブロック に分けられます。 ここを理解すれば、「なぜ評価関数を差し替えられるのか」が一目でわかります。

やねうら王アーキテクチャ — 探索部 + 評価関数(差し替え可能) + 定跡 + 並列化 📦 やねうら王本体(C++ で実装、OSS) 🌳 探索部(Search) アルゴリズム: • α-β木探索(反復深化) • LMR(Late Move Reductions) • Null Move Pruning • 置換表(Transposition Table) • 静止探索(Quiescence Search) → 「どの手を、どこまで深く読むか」を全部ここで決める 🧠 評価関数(差し替え可能) 外部ファイル(nn.bin): • 水匠 10(HalfKP_256x2-32-32) • Háo(HalfKP系・自己対局学習) • tanuki-(NNUE系) • オリジナル自作評価関数 同じやねうら王に別の脳を差し替え → 「局面 → 評価値」だけが仕事 局面 評価値 📖 定跡データベース • 序盤の指し手はDBから瞬時に決定 • 評価値・出現頻度・採用率を記録 • .db .yaneuraou-bin など独自フォーマット → 序盤で探索を節約 → 中盤に思考時間を集中投資 ⚡ 並列探索 / NUMA対応 • 複数スレッドで木を並列展開 • 置換表を共有しつつロック回避 • NUMA(多CPU)でも線形にスケール → 64コア機で「秒間1億局面」級に到達 外部I/O:USIプロトコル(GUIや対局サーバーとの標準インターフェース)

ポイント:探索部と評価関数の境界が 明確に定義されている。 探索部は evaluate(position) -> int という関数を呼ぶだけで、 その中身が「水匠」か「Háo」かを気にしない。これが分業エコシステムを成立させる工学的な工夫です。

2.1 4ブロックの役割

ブロック仕事担当者
探索部 木をどこまで深く・どの手を読むかを決める やねうら王本体(やねうらお氏)
評価関数 1局面を1つの評価値に変換する 水匠・Háo・tanuki- など別チーム
定跡 序盤の手を DB から即決 各エンジン同梱 / コミュニティ作成
並列化 マルチコアで木を並列展開 やねうら王本体

3. α-β木探索とは何か — 詳細

やねうら王の心臓は α-β木探索。Minimax の改良版で、明らかに悪い枝を早めに刈り取ることで 同じ深さでも遥かに少ないノードで読めるアルゴリズムです。

3.1 Minimax の発想(前提)

Minimax は「自分は評価値を最大化、相手は最小化」と仮定して、 木を末端まで読み、葉ノードの評価値を上に伝播させる:

function minimax(node, depth, maximizing):
    if depth == 0 or node が終局:
        return evaluate(node)
    if maximizing:  // 自分の手番
        best = -∞
        for child in children(node):
            val = minimax(child, depth-1, false)
            best = max(best, val)
        return best
    else:           // 相手の手番
        best = +∞
        for child in children(node):
            val = minimax(child, depth-1, true)
            best = min(best, val)
        return best

問題:将棋は1局面あたり約80手の候補があるので、深さ d 読むと 80d ノード。 d=10 で約 1019 ノード。到底読み切れない

3.2 α-β枝刈りの直感

α-β は、Minimax と 同じ答え を出しつつ、「もう調べる必要のない枝」を読まずに飛ばします。 直感は「相手が選ばない手を読んでも仕方ない」

α-β木探索の例 — 斜線の枝は「読まなくていい」枝 MAX root(自分が選ぶ) MIN MIN MIN 3 5 7 2 ? ? ? ? ? 左の MIN :3,5,7 を読んで結果 3(相手は最小化) 中央の MIN :1手目で 2 を見つけた → 既に「左の 3」より悪い → 残りはβ枝刈りでスキップ 右の MIN :左の 3 が確定しているので、それを下回らない限り意味なし → 条件次第で全部スキップ

3.3 α-β の擬似コード(JS風)

// 自分(max)の手番から探索を開始
function alphaBeta(node, depth, alpha, beta, maximizing) {
    if (depth === 0 || isTerminal(node)) {
        return evaluate(node);  // ← 評価関数を呼ぶのはここ(NNUEなど)
    }

    if (maximizing) {
        let value = -Infinity;
        for (const child of moveOrder(node)) {
            value = Math.max(value, alphaBeta(child, depth-1, alpha, beta, false));
            alpha = Math.max(alpha, value);
            if (alpha >= beta) break;  // ★β枝刈り:これ以上読んでも無駄
        }
        return value;
    } else {
        let value = +Infinity;
        for (const child of moveOrder(node)) {
            value = Math.min(value, alphaBeta(child, depth-1, alpha, beta, true));
            beta = Math.min(beta, value);
            if (alpha >= beta) break;  // ★α枝刈り
        }
        return value;
    }
}

// 反復深化(Iterative Deepening)
function search(root, maxDepth) {
    let best;
    for (let d = 1; d <= maxDepth; d++) {
        best = alphaBeta(root, d, -Infinity, +Infinity, true);
        // ★ 浅い結果を moveOrder のヒントに使う → 枝刈り効率UP
    }
    return best;
}

反復深化 がポイント:いきなり深さ10を狙わず、深さ1, 2, 3, ... と順に読む。 浅い読みの結果を moveOrder(指し手の並べ替え)に流用すると、 「最善手から先に試す」ことになり α-β の枝刈り効率が劇的に上がる

📚 補足:α-β の効率 — 「同じ答え」で「ノード数 √ になる」(クリックで展開)

最良の手順序で枝刈りすると、α-β のノード数は Minimax の 平方根オーダーになります:

$$ N_\text{Minimax} = b^d \quad\Rightarrow\quad N_\text{αβ最良} \approx b^{d/2} $$

将棋(b ≈ 80)で d=10 の場合:

  • Minimax:8010 ≈ 1019 ノード(不可能)
  • α-β(最良):805 ≈ 3.3×109 ノード(現代CPU で数秒〜数分)

つまり「同じ深さ d を読むコスト」が一気に現実的になります。

4. 高速化テクニック

やねうら王が世界トップ級になれるのは、α-β を「賢く・速く」走らせる多数のテクニックの積み重ねです。 ここでは主要4つを擬似コードで示します。

4.1 LMR — Late Move Reductions

候補手を「良さそうな順」に並べたあと、遅い順位の手は浅い深さで読む。 悪い手はどうせ評価値が悪いはずなので、深く読むコストを節約:

// 各子ノードを評価するループの中で
for (let i = 0; i < children.length; i++) {
    const child = children[i];
    let reduction = 0;
    if (i >= 3 && depth >= 3 && !isCheck(child)) {
        reduction = 1 + Math.floor(Math.log(i) / Math.log(2));
        // ★ 「i 番目以降」「王手じゃない」「ある程度深い」とき、深さを削る
    }
    let val = -alphaBeta(child, depth - 1 - reduction, -beta, -alpha, !max);
    if (reduction > 0 && val > alpha) {
        // 削った結果が良すぎたら、フルの深さでもう一度読み直す
        val = -alphaBeta(child, depth - 1, -beta, -alpha, !max);
    }
}

4.2 Null Move Pruning — パスしても勝てるなら読み切らない

「もし自分が手番をパスして、それでも局面が良かったら、もう先は読まなくていい」という発想。 将棋では「パス」はルール上できませんが、探索木のアイデアとして使えます:

function alphaBeta(node, depth, alpha, beta, maximizing) {
    // ... 標準処理 ...

    // ★ Null Move Pruning
    if (depth >= 3 && !inCheck(node) && hasNonPawnMaterial(node)) {
        // 自分の手をパスして相手に渡す
        const nullNode = makeNullMove(node);
        const val = -alphaBeta(nullNode, depth - 3, -beta, -beta + 1, !maximizing);
        if (val >= beta) {
            return beta;  // パスしても勝てる → これ以上読まない
        }
    }

    // ... 通常の子探索 ...
}

4.3 置換表(Transposition Table)— 同じ局面を二度読まない

将棋では 違う手順から同じ局面に到達することが頻繁にあります(指し手の入れ替え可能性)。 一度評価した局面はハッシュ表に保存し、再訪したら即返す:

const TT = new Map();  // 置換表(実装では巨大な配列+Zobrist hash)

function alphaBeta(node, depth, alpha, beta, maximizing) {
    const key = zobristHash(node);
    const cached = TT.get(key);
    if (cached && cached.depth >= depth) {
        // ★ 既に十分深く読んだ結果がある → 即返却
        return cached.value;
    }

    // ... 通常の探索 ...

    TT.set(key, { value, depth, bestMove });  // 結果をキャッシュ
    return value;
}

4.4 並列探索 — 複数スレッドで木を分担

やねうら王は マルチスレッド・NUMA に対応。複数CPUで木を並列展開し、 置換表を共有することで「同じ局面の重複探索」を避けつつスケールします:

// 概念図:ルート分割並列(Lazy SMP)
function parallelSearch(root, numThreads) {
    const sharedTT = new ConcurrentMap();

    const workers = [];
    for (let t = 0; t < numThreads; t++) {
        workers.push(spawn(() => {
            // 各スレッドが少しずらした深さ・ヒューリスティクスで同じ木を探索
            // 置換表を共有することで知見が伝播する
            alphaBetaWithSharedTT(root, baseDepth + (t % 2), sharedTT);
        }));
    }
    waitAll(workers);
    return sharedTT.get(zobristHash(root)).bestMove;
}
📚 補足:その他の枝刈り — Futility / Razoring / SEE(クリックで展開)
  • Futility Pruning:浅い末端付近で「評価値 + マージン < α」なら、その手は読まない
  • Razoring:評価値が極端に悪いノードは静止探索(駒得駒損だけを追う)にショートカット
  • SEE(Static Exchange Evaluation):駒交換が静的に得か損かを高速判定し、明らかに損な取り合いは読まない
  • Killer Heuristic / History Heuristic:過去に良かった手を優先して試す → 早期β枝刈りを誘発

これらは すべて同じ答えを近似的に保ったまま速度を稼ぐ 工夫。やねうら王には全部入っています。

5. 評価関数の差し替え — 分業エコシステムの鍵

やねうら王の最大の発明(と言ってもいいくらいの)特徴は、評価関数を外部ファイルで差し替えられること。 これにより、探索の研究評価関数の研究が完全に分離されました。

5.1 関数境界 — search() と evaluate() の分離

やねうら王本体(探索部)は、評価関数の中身を知らない。「局面を渡したら数値が返ってくる関数」としてしか扱わない:

// ===== やねうら王本体(探索部) =====
function alphaBeta(node, depth, alpha, beta, max) {
    if (depth === 0) {
        return evaluate(node);  // ★ ここだけが評価関数とのインターフェース
    }
    // ... α-β の標準処理 ...
}

// ===== 評価関数(差し替え可能) =====
// 起動時に nn.bin を読み込んで evaluator を構築
const evaluator = loadNNUE("suisho10.nn.bin");
// または
const evaluator = loadNNUE("hao.nn.bin");
// または
const evaluator = loadNNUE("tanuki-wcsc33.nn.bin");

function evaluate(node) {
    // node の HalfKP特徴を抽出して、浅いMLPを通すだけ
    return evaluator.forward(node);
}

この evaluate() の中身だけ差し替える」設計が、エコシステム全体を可能にしました。

5.2 「やねうら王 + ◯◯」エコシステム

組み合わせ評価関数の作者特徴
やねうら王 + 水匠 たややん氏(杉村達也氏) 長年 WCSC・電竜戦の上位常連。NNUE 系評価関数の代表格
やねうら王 + Háo Hao 開発者ら 自己対局による教師生成で精度向上。最新世代のNNUE
やねうら王 + tanuki- たぬきチーム 独自の特徴量とハイブリッド学習
やねうら王 + elmo 瀧澤誠氏 2017年 WCSC 優勝(当時)。歴史的な組み合わせ
ふかうら王(DL系) やねうらお氏 +dlshogi モデル MCTS + 深いCNN。NNUE系とは別系統
🧠 上級補足:なぜ「分業」が決定的に効くのか(クリックで展開)

探索と評価関数は、求められる職能が まったく違う

  • 探索:C++・低レベル最適化・SIMD・並列化・アルゴリズム設計
  • 評価関数:PyTorch・GPU学習・教師データ生成・ハイパーパラメータ調整

一人で全部やるよりも、それぞれの専門家が分業した方が 進化が速い。 やねうら王はそのインターフェースを整備することで、コミュニティ全体の知能を集約する装置になりました。

まっしー視点:これは「API設計が組織を作る」の好例。優れた境界線が、エコシステムを生む。

6. ふかうら王 — やねうら王の DL バージョン

やねうら王ブランドは、NNUE 系(CPU・α-β)だけでなく、DL 系(GPU・MCTS)もカバーします。 それが ふかうら王

同じ「やねうら王」ブランドの下に NNUE型・DL型の両方が存在する。 ユーザーは用途に応じて使い分けられる。

📚 補足:NNUE型 vs DL型 — どちらを選ぶか(クリックで展開)
観点NNUE型(やねうら王+水匠)DL型(ふかうら王+dlshogi)
ハードCPU(多コアほど良い)GPU(VRAM多いほど良い)
秒間ノード数数百万〜1億数千〜数万(深い評価)
序盤・中盤強い(読みが深い)強い(戦略パターン認識)
終盤・詰み非常に強い(深く読み切る)苦手な場合がある
初期コスト低い(PC1台で動く)高い(GPU必要)

まっしーは macOS Apple Silicon 機なので、現状は やねうら王 V9.00 + Háo(NNUE型)が主戦力。

7. やねうら王が将棋AI界に与えた影響

影響 1

🔗 探索と評価関数の分業

インターフェースを整備し、研究の並列化を可能にした。 評価関数チームは探索の細部を知らなくてよく、その逆も成立。

影響 2

👤 個人開発者の時代を作った

GitHub OSS とブログ解説により、個人開発者でも世界トップを狙えるエコシステムが成立。 巨大企業 AI と対極の文化を育てた。

影響 3

🏆 評価関数チームの誕生

水匠」「Háo」「tanuki-」「elmo」など、 評価関数特化型のチームが続々と参戦。WCSC・電竜戦の常連勢力に。

影響 4

📖 教育的価値

ソースコードが世界中の将棋AI開発者・研究者の 必読書に。 α-β・LMR・置換表・並列化の実装例として、教育素材としても価値が高い。

影響 5

🇯🇵 NNUE の世界輸出

将棋発の NNUE が、やねうら王での実装を経て Stockfish(チェス)に輸出。 日本発の発明が世界標準になる現象を実現した。

影響 6

🌳 探索研究の継続発展

Stockfish 由来の探索を将棋に最適化し、独自の枝刈り・並列化を継続的に改良。 探索アルゴリズム単体でも研究フロンティアであり続けている。

💡 まとめ: やねうら王は単なる「強い将棋AI」ではなく、「将棋AI開発の社会インフラ」。 探索と評価関数の境界を整備することで、個人・チーム・コミュニティが 並走しながら全体として進化する仕組みを作った。 これが日本将棋AIが世界を引き続きリードできる理由です。

8. 関連リンク

このサイト内の関連ページ

参考にした概念(このサイト内)

外部リソース

まとめ

  1. やねうら王は 日本の将棋AI探索エンジンのデファクトスタンダード
  2. 2015年 GitHub 公開以降、個人開発者でも参加できるエコシステムを構築
  3. アーキテクチャは 探索部・評価関数(差し替え可能)・定跡・並列化の4ブロック
  4. 探索の心臓は α-β木探索 + 反復深化。LMR・Null Move・置換表・並列化で高速化
  5. 評価関数を nn.bin ファイルで差し替え可能 にしたことが分業エコシステムを生んだ
  6. NNUE 系の「水匠」「Háo」「tanuki-」、DL 系の「ふかうら王」など 派生が豊富
  7. 将棋AI界に 「探索と評価関数の分業」「個人参加可能性」「日本発の世界輸出」という構造変化をもたらした

もっと深く知るには

やねうら王の上で動く NNUE 評価関数の中身を詳しく知りたい人は:

→ 詳細ページ「NNUE」へ進む

対抗馬の DL 系(MCTS + 深いCNN)を見たい人は:

→ 詳細ページ「dlshogi」へ進む

開発者本人(やねうらお氏・たややん氏)の言葉で歴史と技術を聞きたい人は:

→ 第8章「CEDEC2024講演で深堀り」へ進む