「 👆 この動画の 最初の30分が アルファベータ探索の説明になってるわよ」
「 👆 アルファベータ探索は、よく こんな絵で 説明されるな」
「 説明すると お父んが寝てしまうので 手順を進めながら やってみよう」
「 👆 まず こっちの枝で 一番大きな数は 15 なんで、 わたしは 15 を選ぶぜ」
「 👆 そっちの枝で 一番大きな数は 40 なんで、 わたしは 40 を選ぶぜ」
「 👆 相手プレイヤーは いじわる をして、 一番小さな数 15 を選ぶぜ」
「 👆 こうして わたしの枝の1つは 15点 だと分かったわけだぜ」
「 これは ミニマックス法 の説明なんで。
アルファとか ベータとか まだなんで」
「 👆 一番 小さな数 を、できるかぎり 大きくしよう、 というのが ミニマックス だぜ」
「 👆 赤い箱の中身を確認しなくても、 6以上 は確定しているぜ」
「 👆 じゃあ 相手プレイヤーは 赤い箱の中身が何であろうと 5 を選ぶぜ」
「 👆 アルファーカットは、よく こんな絵で 説明されるな」
「 👆 赤い箱の中身を確認しなくても、 5以下 は確定しているぜ」
「 👆 じゃあ わたしは 赤い箱の中身が何であろうと 6 を選ぶぜ」
「 手番と 大小関係が ひっくり返っているだけで 同じことでは?」
「 👆 あれっ?
えっ??
どっちが アルファーカットで どっちが ベーターカット???」
「 お父ん(以下 甲とする)、きふわらべ(以下 乙とする) みたいなやつだぜ」
「 利益を増やそうとしている わたしは アルファー さん、
アルファーさんになるべく利益が出ないようにしている相手が ベーター さんだぜ」
「 日本語では 甲乙(こうおつ)、 英語では AB(エービー)、 数式ではギリシャ文字を使うので αβ(アルファー、ベーター)よね」
「 👆 ベーターさんにとって要らないものをカットするから ベーターカット、 アルファーさんにとって要らないものをカットするから アルファーカットよ」
「 カットは 2つある。
ベーターカットと アルファーカットは 違う所をカットしている」
「 👆 アルファーカットしているのは 負の無限大に近い方、
ベーターカットしているのは 正の無限大に近い方だぜ」
「 全部一気に アルファーカットと ベーターカットして 0 にしたったらどうだぜ?」
「 👆 アルファー値とか、ベーター値とか、いろんなとこに いっぱいあるんじゃないのかだぜ?」
「 カットオフしようとしている わたしは、兄 だけ見ろだぜ。それが ベーター値だし、
カットオフしようとしている相手は 兄 だけ見ろだぜ。それが アルファ―値 だぜ」
「 👆 じゃあ 仮に 葉局面の盤面評価値(Value)が 10 だったとしようぜ。
きふわらべ、他の手も選んでくれだぜ」
「 👆 おっと その前に アルファー値 も右にずらして 10 だな」
「 👆 じゃあ仮に 好手 だったとしようぜ。 評価値(Value)に 50点付けよう」
「 👆 じゃあ仮に これが あんまり良くない手で 3点 だったとしようぜ?」
「 アルファー値が 50点 なのに、 評価値(Value)が 3点 なんで、
アルファー値を 評価値が下回ったから、この指し手は不採用だぜ。
アルファー・アップデートなし だぜ」
「 アルファー・アップデートなし なことに 何か名前はないの? 何とかカットとか」
「 もう指しちゃった からな。 指したあとに この手は 低い点だな、と 不採用 を決めただろ。
そんなの ただの 選別 だぜ。 これは カット とは違う。
アルファー・カットや、ベーター・カットは 指す前 にやらないと、そう言わない。
こういうの 前向き枝刈り探索 。
根っこから 葉っぱに向かってるときにやるから 前向き という。
アルファー・アップデートなし は、葉っぱから根っこに向かってるときにやるから、 後ろ向き という」
「 👆 きふわらべは 1番大きな点数の 1二きりん を選ぶぜ」
「 👆 すると アルファー値は 戻って……。
相手は この指し手が きふわらべから見て 50 点だと分かったんで、
50点より低い 評価値になる指し手を探したいな」
「 👆 相手は 別の手も指してみるが、まだ評価値は分かんないぜ。
他の枝と同じ深さまで指そうぜ。
きふわらべ、次の手を選んでくれだぜ」
「 👆 じゃあ 仮に 絶妙な手で 70点 だったとしようぜ?」
「 相手は 50点以下の手を探しているので、それ以上の 良い点 を見つけても 採用されないぜ。
ベーター値によってカットされるから、 これ、 ベーターカット」
「 👆 じゃあ こんな手 考えるの 止め止め! 探索を打ち切りだぜ!」
「 それでも 相手さんは もっと ベーター値を下げれないかな、と別の手を探すぜ。
きふわらべ、次の手を選んでくれだぜ」
「 👆 40 点の手があったが、これは すでに見つけてある 50点の手より点数が低いんで 採用したくないんだが……」
「 43 点。
50点を下回っているから ベータカット されないし、
40点を上回ったから アルファー・アップデート だぜ」
「 結局 わたしが選べる枝になるときには 50点を下回る点になってるということだろ。
ベータカット されないと 嬉しくないな。
アルファー値で 底を上げてはいるけど。
これが ミニマックス なんだろうけど」
「 👆 アルファー値以上の手にしたいし、ベータ値を超えると 採用されないし、
アルファー値と ベーター値の間で 手を探すことになるのねえ」
「 分かったぜ!
これが コンピューター将棋プログラミングのお題の鉄板、 アルファーベーター探索 かだぜ!」
「 コンピューター将棋では、強いソフトが アルファーベーター探索を そのまま使うことは ほぼ無く、
もう一工夫している」
「 説明すると お父んが寝てしまうので 手順を進めながら やってみよう」
「 👆 ネガマックスは、絵で説明しにくいが、相手番も 自分の手番として考えようということだぜ」
「 コーディングが簡単になるから だぜ。
自分の番と 相手の番の2つを コーディングしなくてはいけないところを、
ネガマックス にすることで 自分の番 だけコーディングすれば よくなるんだぜ」
「 2つやらなくちゃいけないことが 1つになったら 楽よねえ」
「 ネガマックスじゃなかったときは、 評価値は、わたしから見たものだぜ」
「 将棋は 二人零和ゲームなので、自分が良ければ相手が悪く、自分が悪ければ相手が良いぜ。
だから 手番が変わるときに 評価値の正負を入れ替えれば どちらの手番でも
自分から見た評価値(Value)になるぜ」
「 プラス、マイナスを ひっくり返せばいいのは 評価値だけじゃないわよね。
あと 2つある」
「 👆 わたしのとき ベーターさんに ベーター値より大きな値は ベーターカットされるが、
相手のとき わたしに アルファー値より小さな値は アルファーカットされるから、
うーん、
アルファー値と ベーター値は 交互になる……??」
「 お父ん、 アルファー値とベーター値が交互になる んだったら、ちゃんとそのような図を描けだぜ。
その図は 言葉通りに描けてないぜ」
「 👆 こんなとこ入れ替わって どうすんだぜ?
アルファー値と ベーター値を入れ替えたいのに、1段上の緑色のおっさんと入れ替わっていいのかだぜ?」
「 お父んが苦手な、 シコーリョク というやつだな。
お父んは 頭の中で あれと これは 別の物だから 同じようにしてはいけないと考えるから シコー が停まるんだぜ。
別の物でも 同じように使えるなら 同じように使おうというのが シコー だぜ」
「 じゃあ 評価値(Value)のプラス・マイナスをひっくり返して、
アルファー値と ベーター値を 入れ替えたらいいのかだぜ?」
「 👆 初期配置は 変わんないだろ。
先手は最初から 10点 有利としようぜ。
あと 評価値バーのデザインを 一新したぜ」
「 👆 ここで知識だぜ。丸いとこを ノード(節;Node)、 線を エッジ(辺;Edge) と呼ぶぜ。
別の呼び方もあるが、この記事では これで行くぜ」
「 👆 そして ネガマックス(Negamax)を理解するための 知識のパズルピースとして、
エッジに 箱を作ろう。 これが工夫」
「 👆 そして 手番変更。
評価値バーの青いところを見てくれだぜ。
イラストを描き直すのが めんどくさいので バー自体を 180°回転するぜ」
「 検証しようぜ。 先手が +10点 なら、後手から見れば ー10点 だな。合ってるな」
「 アルファー値と ベーター値の入れ替わりも確認したいのよ。これじゃ分かんないわよ」
「 👆 はい、手番変更。
評価値バーの青いところを見てくれだぜ」
「 👆 はい、手番変更。
局面評価値(Value)は 先手の得も込みで 20点 だったとしようぜ。
そして 後手から見た評価値だから、
評価値バーの青いところを見てくれだぜ。ひっくり返ってるな」
「 👆 評価値(Value)というのは 先手番が有利だから最初から 10点 付いているというものではなく、
端っこの 葉の局面で計算されて 枝を戻っていく帰り道に付くものだぜ」
「 プラス・マイナスをひっくり返して 箱に 20 を入れたのね」
「 アルファー・アップデート は、エッジの箱の中の方の評価値を使うぜ」
「 👆 評価値(Value)は -60
点。
アルファー値 -∞
以上、 ベーター値 -20
以下だから、いけるな」
「 それだと 悪い手、もっと悪い手 を探していかないかだぜ?
ネガマックスは 自分がいいと思っている手を探すんだろ」
「 自分の手番のときは 自分にとって 良い手、良い手 を 探している し、
相手番のときは 自分にとって 悪い手、悪い手を 探している し、
物は言いようだな、
相手番のときは あとでプラス・マイナスがひっくり返るから いつでも自分にとって 良い手、良い手 を 探しているように説明できる んだぜ」
「 相手番のとき 自分のアルファーが 相手のベーターになっていて、
自分のベーターが 相手のアルファーになってるな。
ベーターを右に動かすことがなくなって、アルファ―を左に動かしているだけ。
評価値(Value)が アルファーを下回るのは ただの アルファー・アップデートしない なので、
アルファーカットは無くなったな。
じゃあ、アルファーカットは無くなって、ベータカットだけが有るようになるのかだぜ?」
「 ノード(丸いところ)の評価値ではなく、エッジ(線のところ)の評価値を見て 比較するのか。
ややこし!」
「 バーを180°回転させてるとこ、うまく コーディングできんの?」
search(alpha, beta, depth):
if depth == 0:
# 葉ノード
node_value = 局面評価値計算( )
return (node_value, _)
bestmove = 投了
move_list = 合法手生成( )
for m in move_list:
# バーが180°回転していることを実感しなさい(^~^)
(node_value, _) = search(-beta, -alpha, depth-1)
# エッジの箱を思い出しなさい(^~^)
edge_value = -node_value
if alpha <= edge_value:
# アルファーアップデート
bestmove = m
alpha = edge_value
if beta < alpha:
# ベータカット
break
return (alpha, bestmove)
main( ):
# 無限大とか使わず、十分大きな値で十分
search(-30000, 30000, 4)
「 👆 これが ネガマックスのアルファー・ベーター探索部 の雰囲気だぜ。
そのままコピー貼り付けしても動かないから、感じろ」
<おわり>
Crieitは個人で開発中です。
興味がある方は是非記事の投稿をお願いします! どんな軽い内容でも嬉しいです。
なぜCrieitを作ろうと思ったか
また、「こんな記事が読みたいけど見つからない!」という方は是非記事投稿リクエストボードへ!
こじんまりと作業ログやメモ、進捗を書き残しておきたい方はボード機能をご利用ください!