Pyaq(囲碁ソフト)の調査
目次
1 概要
- Deep Learningで学習できる、囲碁ソフト
- Pythonベース
- MITライセンス
2 リンク
- Pyaq 公式サイト https://github.com/ymgaq/Pyaq
- Pyaq-custom 公式サイト https://github.com/Hidetomi/pyaq-custom
3 Boardクラスをちょっと試してみる
- Dockerイメージで構築します。
- Docker Hub の tensorflow/tensorflowイメージをベースに行います。
- tensorflow/tensorflowのイメージを拡張その2(GNU GLobal入り)https://www.youtube.com/watch?v=FFWRbgJjekoを利用します。
3.1 以下の操作を行っている動画
3.2 GNU Globalでソースを読みやすくなるようにする
- terminalを起動し以下を実行
- 作業用のディレクトリを作成し、ソースをゲット、GNU Globalで処理して、よみやすくなったHTMLを生成し、w3mで開く
sudo su - user cd /tf/notebooks/ mkdir -p Pyaq cd Pyaq git clone https://github.com/ymgaq/Pyaq.git cd Pyaq # gtags --gtagslabel=pygments htags -afFIsngov --gtagslabel=pygments w3m HTML/index.html
- w3mでみたら、Shift+Fで、より読みやすくなる
3.3 他の端末を開いて、board.pyの中にはいっている、関数やBoardクラスを使ってみる
3.3.1 以下でipython3を起動
sudo su - user
cd /tf/notebooks/Pyaq/Pyaq/
ipython3
3.3.2 ipython3内部で以下を実行
- ボードを生成して、いろいろやってみる
import board b=board.Board() # ボードを作成 b.random_play() # ランダムに1手 b.showboard() # ボードを表示 b.clear() # ボードをクリア b.showboard() board.ev2str(81) # 内部で81が何か? => 'D7' board.ev2xy(81) # 内部で81が何か? => (4, 7) board.ev2rv(81) # 内部で81が何か? => 57 board.str2ev("D7") # => 81 b.place_stone(board.str2ev("D7")) # D7に石を置く b.showboard() # ボードを表示 b.place_stone(board.str2ev("E7")) # E7に石を置く b.showboard() # ボードを表示 b.place_stone(board.str2ev("F8")) # F8に石を置く b.showboard() # ボードを表示 b.place_stone(board.str2ev("E9")) # E9に石を置く b.showboard() # ボードを表示 b.place_stone(board.str2ev("D8")) # D8に石を置く b.showboard() # ボードを表示 b.play(board.str2ev("F7")) # playとしてF7に石を置く b.showboard() # ボードを表示 b.legal(board.str2ev("E8")) # E8に石を置けるかチェック => False b.legal(board.str2ev("F6")) # F6に石を置けるかチェック => True b.play(board.str2ev("F6")) # playとしてF6に石を置く b.showboard() # ボードを表示 b.play(board.str2ev("F5")) # playとしてF5に石を置く b.showboard() # ボードを表示 b.feature() # 評価関数(search.py evaluate)に渡されているものをみてみる type(b.feature()) # タイプ確認 b.feature().ndim # 次元数確認 => 2 b.feature().shape # 次元数確認 => (81, 7) b.feature().size # 次元数確認 => 567 len(b.feature()) # len => 81
3.4 この章のまとめ
- Pyaqのソースをゲットしてきて、GNU Globalで読みやすく加工
- IPythonを利用して、board.pyにはいっている関数や、Boardクラスを試してみた
4 Boardクラスをちょっと試してみる2
- ボードの指定座標の状態を知る(白か黒か空か)
- 一つ前の手を確認
- 1つ前のボードの状態を確認
- どちらの手番か確認
- tensorflow/tensorflowのイメージを拡張その2(GNU GLobal入り)https://www.youtube.com/watch?v=FFWRbgJjekoを利用します。
4.1 以下の操作を行っている動画
4.2 今回の操作をやるために調べたソースの部分
4.2.1 Boardクラスのshowboadメソッド
- ループまわして、それぞれの座標の状態を表示している
- 330行に調べる部分がある
- このソースから、指定座標の状態を知る方法が簡単に調べられる
- 333行目から、一つ前の手がどれかを調べる方法が確認可能
315 def showboard(self): 316 317 def pirnt_xlabel(): 318 line_str = " " 319 for x in range(BSIZE): 320 line_str += " " + x_labels[x] + " " 321 stderr.write(line_str + "\n") 322 323 pirnt_xlabel() 324 325 for y in range(1, BSIZE + 1)[::-1]: # 9, 8, ..., 1 326 line_str = str(y) if y >= 10 else " " + str(y) 327 for x in range(1, BSIZE + 1): 328 v = xy2ev(x, y) 329 x_str = " . " 330 color = self.color[v] 331 if color <= 1: 332 stone_str = "O" if color == 0 else "X" 333 if v == self.prev_move: 334 x_str = "[" + stone_str + "]" 335 else: 336 x_str = " " + stone_str + " " 337 line_str += x_str 338 line_str += str(y) if y >= 10 else " " + str(y) 339 stderr.write(line_str + "\n") 340 341 pirnt_xlabel() 342 stderr.write("\n")
4.2.2 Boardクラスの clearメソッド
- 116行目に、prev_colorへの代入文がある。これから、KEEP_PREV_CNTの数の分前の盤の状態を保持することがわかる
110 def clear(self): 111 self.color[rv_list] = 2 # empty 112 self.id = np.arange(EBVCNT) # id of stone group 113 self.next = np.arange(EBVCNT) # next position in the same group 114 for i in range(EBVCNT): 115 self.sg[i].clear(stone=False) 116 self.prev_color = [np.copy(self.color) for _ in range(KEEP_PREV_CNT)] 117 118 self.ko = VNULL # illegal position due to Ko 119 self.turn = 1 # black 120 self.move_cnt = 0 # move count 121 self.prev_move = VNULL # previous move 122 self.remove_cnt = 0 # removed stones count 123 self.history = []
4.3 手順
- 前の章のやり方でDocker imageを起動
- 他の端末を開いて、IPythonを起動
4.3.1 以下でipython3を起動
sudo su - user
cd /tf/notebooks/Pyaq/Pyaq/
ipython3
- IPython内で以下を実行しボードクラスを使ってみる2
import board b=board.Board() # ボードを作成 b.showboard() # ボードを表示 b.turn # => 1 b.prev_color b.prev_color[0]==b.prev_color[1] b.color.reshape(11,11) # ボード情報を格納しているcolorをreshapeして表示 0:O 1:X 2:空 3:壁 b.play(board.str2ev("F7")) # playとしてF7に石を置く b.showboard() # ボードを表示 b.color.reshape(11,11) b.prev_color b.prev_color[0]==b.prev_color[1] b.turn # => 0 b.play(board.str2ev("A1")) # playとしてA1に石を置く b.showboard() # ボードを表示 b.color.reshape(11,11) b.color[board.str2ev("F7")] # F7 の状態 => 1 b.color[board.str2ev("A1")] # A1 の状態 => 0 b.color[board.str2ev("A2")] # A2 の状態 => 2 b.color[1] # 壁 の状態 => 3 type(b.prev_color) # => list b.prev_move board.ev2str(b.prev_move) # => A1 import numpy as np b.prev_color b.prev_color[0]==b.prev_color[1] x=(b.prev_color[0]==b.prev_color[1]) np.where( x == False ) # どこが変化したか確認 => (arrya[83]) board.ev2str(83) # => F7 board.KEEP_PREV_CNT=3 # KEEP_PREV_CNTを変更してみる b=board.Board() # Boardを再度生成 b.prev_color # prev_colorを確認、要素数が増えている len(b.prev_color) # => 3
4.4 この章のまとめ
- Boardクラスで、指定座標の状態の調べ方がわかった
- 手番、一つ前のコマの状態、一つ前の盤の状態の調べ方がわかった
- 一つ前の手の調べ方がわかった
- 何手前まで、盤の状態を保持させるかの設定を変更してみた
5 評価関数で、好きな盤の状態を評価させてみた
- 今までの章でボードクラスの扱いはだいたいわかったので、その盤の状態を現在の評価関数で評価させてみた
- TensorFlow 2.1.0 で動かすと AttributeError: module ‘tensorflow’ has no attribute ‘get_default_graph’ というエラーが
- 上の2.1.0で動かした時にエラー、これを使えば解決できそうだが? tf.compat.v1.get_default_graph https://www.tensorflow.org/api_docs/python/tf/compat/v1/get_default_graph
- tensorflow/tensorflowのイメージを拡張その2(GNU GLobal入り)https://www.youtube.com/watch?v=FFWRbgJjekoを利用します。
5.1 以下の操作を行っている動画
5.2 評価関数を直接使ってみる操作手順
5.2.1 イメージ起動
- 以下を実行して表示される一番下のhttp://127.0.0.1 …. をコピペしてブラウザで開く
docker run -it --rm -v $(realpath ~/notebooks):/tf/notebooks -p 8888:8888 mytensorflow
5.2.2 シェル起動
- New から terminalを選択して、ターミナル起動
5.2.3 シェルで以下のコマンドを実行
sudo su - user cd /tf/notebooks/Pyaq/Pyaq cp pre_train/model.ckpt . # 学習済みモデルを利用できるように pip3 install tensorflow==1.4 # 古いバージョンに下げて、問題回避 ipython3 # ipython3起動
5.2.4 IPython内で以下を実行
from collections import Counter import sys from board import * import gtp import learn import search use_gpu = False b = Board() #ボード生成 tree = search.Tree("model.ckpt", use_gpu) tree.evaluate(b) # bのボードを評価 (a1,a2)=tree.evaluate(b) # bのボードを評価を(a1,a2)に保存 a1.shape # a1 shape確認 => (1, 82) a2.shape # a2 shape確認 => (1,) type(a1) # a1 type確認 => numpy.ndarray type(a2) # a2 type確認 => numpy.ndarray a1 # a1 確認 => 大きいので省略 a2 # a2 確認 => array([0.02216651], dtype=float32)
5.3 この章でのまとめ
- 評価関数に、作成した盤の状態をわたして、評価してみた
- 返ってくるのは要素数82個の配列と、要素数1個の配列のタプル
- この評価部分を差し替えれば、好きな評価関数での囲碁ソフトエンジン作成可能であろう(多分)
- 9×9の盤なのに、なぜ82個なのか?調査継続
6 任意の盤を与えてお勧めの手をゲット
- 前の章では、任意の盤を評価関数かけて、返り値をゲット出来た
- この章では、任意の盤を与えて、一番お勧めの手をゲットしてみる
- なぜ9×9=81の盤なのに、評価関数の返り値の配列の要素が82で1個多いのかも、理由判明(passがあるためでした)
- search.pyの中を調べた
- tensorflow/tensorflowのイメージを拡張その2(GNU GLobal入り)https://www.youtube.com/watch?v=FFWRbgJjekoを利用します。
6.1 以下の操作を行っている動画
6.2 任意の盤を与えてお勧めの手をゲットする手順
6.2.1 イメージ起動
- tensorflow/tensorflowのイメージを拡張その2(GNU GLobal入り)https://www.youtube.com/watch?v=FFWRbgJjekoを利用します。
- 以下を実行して表示される一番下のhttp://127.0.0.1 …. をコピペしてブラウザで開く
docker run -it --rm -v $(realpath ~/notebooks):/tf/notebooks -p 8888:8888 mytensorflow
6.2.2 シェル起動
- New から terminalを選択して、ターミナル起動
6.2.3 シェルで以下のコマンドを実行
sudo su - user cd /tf/notebooks/Pyaq/Pyaq cp pre_train/model.ckpt . # 学習済みモデルを利用できるように pip3 install tensorflow==1.4 # 古いバージョンに下げて、問題回避 ipython3 # ipython3起動
6.2.4 IPython内で以下を実行
from collections import Counter import sys from board import * import gtp import learn import search use_gpu = False b = Board() #ボード生成 tree = search.Tree("model.ckpt", use_gpu) tree.evaluate(b) # bのボードを評価 (a1,a2)=tree.evaluate(b) # bのボードを評価を(a1,a2)に保存 rv2ev(np.argmax(tree.evaluate(b)[0][0])) # お勧めの手のev値ゲット np.argmax(tree.evaluate(b)[0][0]) # np.argmax(tree.evaluate(b)[0][0]) の確認 => 40 tree.evaluate(b)[0][0] # tree.evaluate(b)[0][0] の確認 ev2str(rv2ev(np.argmax(tree.evaluate(b)[0][0]))) # strでお勧めの手を確認 => 'E5' b.showboard() # ボード表示 ev2str(rv2ev(0)) # 0の場合のstr確認 => 'A1' ev2str(rv2ev(1)) # 1の場合のstr確認 => 'B1' ev2str(rv2ev(81)) # 81の場合のstr確認 => 'pass' ev2str(rv2ev(82)) # 82の場合のstr確認 => 'B10' 0->81で82個だから、この値にはならない
6.3 この章でのまとめ
- 任意の盤でのお勧めの手を得る手順を確認
- 9×9=81個のおける場所にたいして82個の配列がかえってくる理由を確認(passがあるからでした)
7 StoneGroupクラスの調査
- tensorflow/tensorflowのイメージを拡張その2(GNU GLobal入り)https://www.youtube.com/watch?v=FFWRbgJjekoを利用します。
7.1 以下の操作を行っている動画
7.2 任意の盤を与えてお勧めの手をゲットする手順
7.2.1 イメージ起動
- tensorflow/tensorflowのイメージを拡張その2(GNU GLobal入り)https://www.youtube.com/watch?v=FFWRbgJjekoを利用します。
- 以下を実行して表示される一番下のhttp://127.0.0.1 …. をコピペしてブラウザで開く
docker run -it --rm -v $(realpath ~/notebooks):/tf/notebooks -p 8888:8888 mytensorflow
7.2.2 シェル起動
- New から terminalを選択して、ターミナル起動
7.2.3 シェルで以下のコマンドを実行
sudo su - user cd /tf/notebooks/Pyaq/Pyaq cp pre_train/model.ckpt . # 学習済みモデルを利用できるように pip3 install tensorflow==1.4 # 古いバージョンに下げて、問題回避 ipython3 # ipython3起動
7.2.4 以前の章でPyaqのソースをゲットしてないなら
- ディレクトリ作成
cd /tf/notebooks/ sudo mkdir Pyaq
- 作成したPyaqディレクトリの所有権変更
sudo chown user.user Pyaq cd Pyaq
- Pyaq ソースゲット
git clone https://github.com/ymgaq/Pyaq.git
- Pyaq ソースゲット
- GNU GLobalでソースを読みやすくしたHTMLファイル作成
- ホスト側でホームディレクトリのnotebooks/Pyaq/Pyaq/HTML/index.htmlをブラウザで開く
cd Pyaq htags -afFIsngov --gtagslabel=pygments
- 以下を実行し、IPython3を起動
cd /tf/notebooks/Pyaq/Pyaq cp pre_train/model.ckpt . # 学習済みモデルを利用できるように pip3 install tensorflow==1.4 # 古いバージョンに下げて、問題回避 ipython3 # ipython3起動
7.2.5 IPython内で以下を実行
- StoneGroup のメンバ変数 lib_cnt が 隣接の空いているあるいは、味方の石の数
- StoneGroup のメンバ変数 size が縦横で接続されている石の数の場合もあるし、他の数値になっているケースも(追加調査必用)
- StoneGroup のメンバ変数 v_atr が当たりになっているケースあり
- StoneGroup のメンバ変数 libs が隣接の空座標や、先に存在している仲間の石の座標の場合も
from collections import Counter import sys from board import * import gtp import learn import search use_gpu = False # ある座標のStoneGroupのメンバ変数の中身表示用関数 def myShowSg(x): print(">>>>>>>: "+x) print("lib_cnt: ", end=" ") print(b.sg[str2ev(x)].lib_cnt) print("size : ", end=" ") print(b.sg[str2ev(x)].size) print("v_atr : ", end=" ") print(str(b.sg[str2ev(x)].v_atr)+" : "+ev2str(b.sg[str2ev(x)].v_atr)) print("libs : ", end=" ") print(b.sg[str2ev(x)].libs) for i in b.sg[str2ev(x)].libs: print(ev2str(i), end=", ") print("") b = Board() #ボード生成 b.place_stone(str2ev("E7")) # E7に石を置く b.showboard() # ボードを表示 b.place_stone(str2ev("F8")) # F8に石を置く b.showboard() # ボードを表示 b.place_stone(str2ev("E9")) # E9に石を置く b.showboard() # ボードを表示 b.place_stone(str2ev("D8")) # D8に石を置く b.showboard() # ボードを表示 b.turn=0 b.place_stone(str2ev("F9")) # F9に石を置く b.showboard() # ボードを表示 b.place_stone(str2ev("F7")) # F7に石を置く b.showboard() # ボードを表示 b.place_stone(str2ev("G8")) # G8に石を置く b.showboard() # ボードを表示 b.legal(str2ev("E8")) # E8に石を置ける? => True b.sg # ボードのsgメンバーの内容 type(b.sg) # b.sgのタイプは? => list len(b.sg) # b.sgの長さは? => 121 b.color.shape # b.colorのshapeは? => (121,) b.sgの長さと同じつまり、"b.sgは、evで希望のStoneGroupeにアクセス可能" b.showboard() # ボードを表示 # この時点での盤の状態 # A B C D E F G H J # 9 . . . . X O . . . 9 # 8 . . . X . X O . . 8 # 7 . . . . X O . . . 7 # 6 . . . . . . . . . 6 # 5 . . . . . . . . . 5 # 4 . . . . . . . . . 4 # 3 . . . . . . . . . 3 # 2 . . . . . . . . . 2 # 1 . . . . . . . . . 1 # A B C D E F G H J myShowSg("E9") myShowSg("E7") myShowSg("D8") myShowSg("F8") # >>>>>>>: E9 # lib_cnt: 2 # size : 1 # v_atr : 93 : E8 # libs : {93, 103} # E8, D9, # >>>>>>>: E7 # lib_cnt: 3 # size : 1 # v_atr : 71 : E6 # libs : {81, 93, 71} # D7, E8, E6, # >>>>>>>: D8 # lib_cnt: 4 # size : 1 # v_atr : 81 : D7 # libs : {81, 91, 93, 103} # D7, C8, E8, D9, # >>>>>>>: F8 # lib_cnt: 1 # size : 1 # v_atr : 83 : F7 # libs : {93} # E8, b.showboard() # ボードを表示 # この時点での盤の状態 # A B C D E F G H J # 9 . . . . X O . . . 9 # 8 . . . X . X O . . 8 # 7 . . . . X O . . . 7 # 6 . . . . . . . . . 6 # 5 . . . . . . . . . 5 # 4 . . . . . . . . . 4 # 3 . . . . . . . . . 3 # 2 . . . . . . . . . 2 # 1 . . . . . . . . . 1 # A B C D E F G H J myShowSg("F9") myShowSg("F7") myShowSg("G8") # >>>>>>>: F9 # lib_cnt: 1 # size : 1 # v_atr : 106 : G9 # libs : {106} # G9, # >>>>>>>: F7 # lib_cnt: 2 # size : 1 # v_atr : 72 : F6 # libs : {72, 84} # F6, G7, # >>>>>>>: G8 # lib_cnt: 3 # size : 1 # v_atr : 84 : G7 # libs : {96, 106, 84} # H8, G9, G7, b.place_stone(str2ev("G9")) # G9に石を置く b.showboard() # ボードを表示 # この時点での盤の状態 # A B C D E F G H J # 9 . . . . X O O . . 9 # 8 . . . X . X O . . 8 # 7 . . . . X O . . . 7 # 6 . . . . . . . . . 6 # 5 . . . . . . . . . 5 # 4 . . . . . . . . . 4 # 3 . . . . . . . . . 3 # 2 . . . . . . . . . 2 # 1 . . . . . . . . . 1 # A B C D E F G H J myShowSg("F9") myShowSg("F7") myShowSg("G8") myShowSg("G9") # >>>>>>>: F9 # lib_cnt: 0 # size : 1 # v_atr : 106 : G9 # libs : set() # # >>>>>>>: F7 # lib_cnt: 2 # size : 1 # v_atr : 72 : F6 # libs : {72, 84} # F6, G7, # >>>>>>>: G8 # lib_cnt: 2 # size : 1 # v_atr : 84 : G7 # libs : {96, 84} # H8, G7, # >>>>>>>: G9 # lib_cnt: 3 # size : 3 # v_atr : 107 : H9 # libs : {96, 107, 84} # H8, H9, G7, b.play(str2ev("E8")) # E8に石を置く(playモード) F8の石取れた! b.showboard() # ボードを表示 # この時点での盤の状態 # A B C D E F G H J # 9 . . . . X O O . . 9 # 8 . . . X [O] . O . . 8 # 7 . . . . X O . . . 7 # 6 . . . . . . . . . 6 # 5 . . . . . . . . . 5 # 4 . . . . . . . . . 4 # 3 . . . . . . . . . 3 # 2 . . . . . . . . . 2 # 1 . . . . . . . . . 1 # A B C D E F G H J myShowSg("F9") myShowSg("F7") myShowSg("G8") myShowSg("G9") myShowSg("E8") # >>>>>>>: F9 # lib_cnt: 0 # size : 1 # v_atr : 106 : G9 # libs : set() # # >>>>>>>: F7 # lib_cnt: 3 # size : 1 # v_atr : 94 : F8 # libs : {72, 84, 94} # F6, G7, F8, # >>>>>>>: G8 # lib_cnt: 2 # size : 1 # v_atr : 84 : G7 # libs : {96, 84} # H8, G7, # >>>>>>>: G9 # lib_cnt: 4 # size : 3 # v_atr : 94 : F8 # libs : {96, 107, 84, 94} # H8, H9, G7, F8, # >>>>>>>: E8 # lib_cnt: 1 # size : 1 # v_atr : 94 : F8 # libs : {94} # F8, b.turn = 0 b.play(str2ev("H9")) # E9に石を置く(playモード) b.showboard() # ボードを表示 # この時点での盤の状態 # A B C D E F G H J # 9 . . . . X O O [O] . 9 # 8 . . . X O . O . . 8 # 7 . . . . X O . . . 7 # 6 . . . . . . . . . 6 # 5 . . . . . . . . . 5 # 4 . . . . . . . . . 4 # 3 . . . . . . . . . 3 # 2 . . . . . . . . . 2 # 1 . . . . . . . . . 1 # A B C D E F G H J myShowSg("F9") myShowSg("F7") myShowSg("G8") myShowSg("G9") myShowSg("E8") myShowSg("H9") # >>>>>>>: F9 # lib_cnt: 0 # size : 1 # v_atr : 106 : G9 # libs : set() # >>>>>>>: F7 # lib_cnt: 3 # size : 1 # v_atr : 94 : F8 # libs : {72, 84, 94} # F6, G7, F8, # >>>>>>>: G8 # lib_cnt: 2 # size : 1 # v_atr : 84 : G7 # libs : {96, 84} # H8, G7, # >>>>>>>: G9 # lib_cnt: 4 # size : 4 # v_atr : 94 : F8 # libs : {96, 84, 108, 94} # H8, G7, J9, F8, # >>>>>>>: E8 # lib_cnt: 1 # size : 1 # v_atr : 94 : F8 # libs : {94} # F8, # >>>>>>>: H9 # lib_cnt: 2 # size : 1 # v_atr : 96 : H8 # libs : {96, 108} # H8, J9, b.turn = 0 b.play(str2ev("J9")) # J9に石を置く(playモード) F8の石取れた! b.showboard() # ボードを表示 # この時点での盤の状態 # A B C D E F G H J # 9 . . . . X O O O [O] 9 # 8 . . . X O . O . . 8 # 7 . . . . X O . . . 7 # 6 . . . . . . . . . 6 # 5 . . . . . . . . . 5 # 4 . . . . . . . . . 4 # 3 . . . . . . . . . 3 # 2 . . . . . . . . . 2 # 1 . . . . . . . . . 1 # A B C D E F G H J myShowSg("F9") myShowSg("F7") myShowSg("G8") myShowSg("G9") myShowSg("E8") myShowSg("H9") myShowSg("J9") # >>>>>>>: F9 # lib_cnt: 0 # size : 1 # v_atr : 106 : G9 # libs : set() # # >>>>>>>: F7 # lib_cnt: 3 # size : 1 # v_atr : 94 : F8 # libs : {72, 84, 94} # F6, G7, F8, # >>>>>>>: G8 # lib_cnt: 2 # size : 1 # v_atr : 84 : G7 # libs : {96, 84} # H8, G7, # >>>>>>>: G9 # lib_cnt: 4 # size : 5 # v_atr : 94 : F8 # libs : {96, 97, 84, 94} # H8, J8, G7, F8, # >>>>>>>: E8 # lib_cnt: 1 # size : 1 # v_atr : 94 : F8 # libs : {94} # F8, # >>>>>>>: H9 # lib_cnt: 2 # size : 1 # v_atr : 96 : H8 # libs : {96, 108} # H8, J9, # >>>>>>>: J9 # lib_cnt: 1 # size : 1 # v_atr : 97 : J8 # libs : {97} # J8,
7.3 この章でのまとめ
- StoneGroupeのメンバ変数の内容を調べてみた
- 取れるか否かのチェックに利用されているはず
- 石のグループ全部が同じlibsになっておらず、グループの1つの座標が、そのグループの全体の情報を持っているようであった
- StoneGroupeは取れる石の判定に利用されていると推測
8 Boardクラスのscore関数の調査
- tensorflow/tensorflowのイメージを拡張その2(GNU GLobal入り)https://www.youtube.com/watch?v=FFWRbgJjekoを利用します。
8.1 以下の操作を行っている動画
8.2 任意の盤を与えてお勧めの手をゲットする手順
8.2.1 イメージ起動
- tensorflow/tensorflowのイメージを拡張その2(GNU GLobal入り)https://www.youtube.com/watch?v=FFWRbgJjekoを利用します。
- 以下を実行して表示される一番下のhttp://127.0.0.1 …. をコピペしてブラウザで開く
docker run -it --rm -v $(realpath ~/notebooks):/tf/notebooks -p 8888:8888 mytensorflow
8.2.2 シェル起動
- New から terminalを選択して、ターミナル起動
8.2.3 シェルで以下のコマンドを実行
sudo su - user cd /tf/notebooks/Pyaq/Pyaq cp pre_train/model.ckpt . # 学習済みモデルを利用できるように pip3 install tensorflow==1.4 # 古いバージョンに下げて、問題回避 ipython3 # ipython3起動
8.2.4 以前の章でPyaqのソースをゲットしてないなら
- ディレクトリ作成
cd /tf/notebooks/ sudo mkdir Pyaq
- 作成したPyaqディレクトリの所有権変更
sudo chown user.user Pyaq cd Pyaq
- Pyaq ソースゲット
git clone https://github.com/ymgaq/Pyaq.git
- Pyaq ソースゲット
- GNU GLobalでソースを読みやすくしたHTMLファイル作成
- ホスト側でホームディレクトリのnotebooks/Pyaq/Pyaq/HTML/index.htmlをブラウザで開く
cd Pyaq htags -afFIsngov --gtagslabel=pygments
- 以下を実行し、IPython3を起動
cd /tf/notebooks/Pyaq/Pyaq cp pre_train/model.ckpt . # 学習済みモデルを利用できるように pip3 install tensorflow==1.4 # 古いバージョンに下げて、問題回避 ipython3 # ipython3起動
8.2.5 board.pyのBoardクラスに以下の関数を追加
- scoreの内容を確認するための補助メソッド
- score クラスの下あたりに追加がお勧め(Boardクラスのメソッドとして定義できてればOK)
- 4つの要素をかえし、[Xの石の数、Oの石の数、空きの目でXのみ隣接している目の数, 空きの目でOのみ隣接している目の数, score関数と同じ答]を返す。
def bscore(self): stone_cnt = [0, 0, 0, 0, 0] for rv in range(BVCNT): v = rv2ev(rv) c = self.color[v] if c <= 1: stone_cnt[c] += 1 else: nbr_cnt = [0, 0, 0, 0] for d in dir4: nbr_cnt[self.color[v + d]] += 1 if nbr_cnt[0] > 0 and nbr_cnt[1] == 0: stone_cnt[0+2] += 1 elif nbr_cnt[1] > 0 and nbr_cnt[0] == 0: stone_cnt[1+2] += 1 stone_cnt[4]= stone_cnt[1] - stone_cnt[0] - KOMI + stone_cnt[1+2] - stone_cnt[0+2] return stone_cnt
8.2.6 IPython内で以下を実行
- 色々な盤面でscore関数、bscore関数を呼び出す
- 下からすると、石がある目は、その石の陣営に+1, 石がない目は、周囲4方向に一方の陣営の石のみある場合その陣営に+1
- 空き目で、周囲(上下4方向)に両方の陣営の石がある場合は、足さない
- ハンデとして、board.py内のKOMIで設定(初期値-7.0)
from collections import Counter import sys from board import * import gtp import learn import search use_gpu = False # ある座標のStoneGroupのメンバ変数の中身表示用関数 def myShowSg(x): print(">>>>>>>: "+x) print("lib_cnt: ", end=" ") print(b.sg[str2ev(x)].lib_cnt) print("size : ", end=" ") print(b.sg[str2ev(x)].size) print("v_atr : ", end=" ") print(str(b.sg[str2ev(x)].v_atr)+" : "+ev2str(b.sg[str2ev(x)].v_atr)) print("libs : ", end=" ") print(b.sg[str2ev(x)].libs) for i in b.sg[str2ev(x)].libs: print(ev2str(i), end=", ") print("") b = Board() #ボード生成 b.showboard() # ボードを表示 # この時点での盤の状態 # A B C D E F G H J # 9 . . . . . . . . . 9 # 8 . . . . . . . . . 8 # 7 . . . . . . . . . 7 # 6 . . . . . . . . . 6 # 5 . . . . . . . . . 5 # 4 . . . . . . . . . 4 # 3 . . . . . . . . . 3 # 2 . . . . . . . . . 2 # 1 . . . . . . . . . 1 # A B C D E F G H J (b.bscore(),b.score()) # ([0, 0, 0, 0, -7.0], -7.0) b.place_stone(str2ev("E7")) # E7に石を置く b.showboard() # ボードを表示 # この時点での盤の状態 # A B C D E F G H J # 9 . . . . . . . . . 9 # 8 . . . . . . . . . 8 # 7 . . . . X . . . . 7 # 6 . . . . . . . . . 6 # 5 . . . . . . . . . 5 # 4 . . . . . . . . . 4 # 3 . . . . . . . . . 3 # 2 . . . . . . . . . 2 # 1 . . . . . . . . . 1 # A B C D E F G H J (b.bscore(),b.score()) # ([0, 1, 0, 4, -2.0], -2.0) b.score() b.place_stone(str2ev("F8")) # F8に石を置く b.showboard() # ボードを表示 # この時点での盤の状態 # A B C D E F G H J # 9 . . . . . . . . . 9 # 8 . . . . . X . . . 8 # 7 . . . . X . . . . 7 # 6 . . . . . . . . . 6 # 5 . . . . . . . . . 5 # 4 . . . . . . . . . 4 # 3 . . . . . . . . . 3 # 2 . . . . . . . . . 2 # 1 . . . . . . . . . 1 # A B C D E F G H J (b.bscore(),b.score()) # ([0, 2, 0, 6, 1.0], 1.0) b.play(str2ev("D6")) # D6に石を置く b.showboard() # ボードを表示 # この時点での盤の状態 # A B C D E F G H J # 9 . . . . . . . . . 9 # 8 . . . . . X . . . 8 # 7 . . . . X . . . . 7 # 6 . . . [X] . . . . . 6 # 5 . . . . . . . . . 5 # 4 . . . . . . . . . 4 # 3 . . . . . . . . . 3 # 2 . . . . . . . . . 2 # 1 . . . . . . . . . 1 # A B C D E F G H J (b.bscore(),b.score()) # ([0, 3, 0, 8, 4.0], 4.0) b.play(str2ev("G8")) # G8に石を置 b.showboard() # ボードを表示 # この時点での盤の状態 # A B C D E F G H J # 9 . . . . . . . . . 9 # 8 . . . . . X [O] . . 8 # 7 . . . . X . . . . 7 # 6 . . . X . . . . . 6 # 5 . . . . . . . . . 5 # 4 . . . . . . . . . 4 # 3 . . . . . . . . . 3 # 2 . . . . . . . . . 2 # 1 . . . . . . . . . 1 # A B C D E F G H J (b.bscore(),b.score()) # ([1, 3, 3, 7, -1.0], -1.0) b.play(str2ev("J8")) # J8に石を置 b.showboard() # ボードを表示 # この時点での盤の状態 # A B C D E F G H J # 9 . . . . . . . . . 9 # 8 . . . . . X O . [X] 8 # 7 . . . . X . . . . 7 # 6 . . . X . . . . . 6 # 5 . . . . . . . . . 5 # 4 . . . . . . . . . 4 # 3 . . . . . . . . . 3 # 2 . . . . . . . . . 2 # 1 . . . . . . . . . 1 # A B C D E F G H J (b.bscore(),b.score()) # ([1, 4, 2, 9, 3.0], 3.0)
8.3 この章のまとめ
- 点数計算方法の確認を、複数の盤面を作ってみて確認
9 Boardクラスのコピー
- tensorflow/tensorflowのイメージを拡張その2(GNU GLobal入り)https://www.youtube.com/watch?v=FFWRbgJjekoを利用します。
9.1 以下の操作を行っている動画
9.2 Boardクラスオブジェクトのコピーをする手順
9.2.1 イメージ起動
- tensorflow/tensorflowのイメージを拡張その2(GNU GLobal入り)https://www.youtube.com/watch?v=FFWRbgJjekoを利用します。
- 以下を実行して表示される一番下のhttp://127.0.0.1 …. をコピペしてブラウザで開く
docker run -it --rm -v $(realpath ~/notebooks):/tf/notebooks -p 8888:8888 mytensorflow
9.2.2 シェル起動
- New から terminalを選択して、ターミナル起動
9.2.3 シェルで以下のコマンドを実行
sudo su - user cd /tf/notebooks/Pyaq/Pyaq cp pre_train/model.ckpt . # 学習済みモデルを利用できるように pip3 install tensorflow==1.4 # 古いバージョンに下げて、問題回避 ipython3 # ipython3起動
9.2.4 以前の章でPyaqのソースをゲットしてないなら
- ディレクトリ作成
cd /tf/notebooks/ sudo mkdir Pyaq
- 作成したPyaqディレクトリの所有権変更
sudo chown user.user Pyaq cd Pyaq
- Pyaq ソースゲット
git clone https://github.com/ymgaq/Pyaq.git
- Pyaq ソースゲット
- GNU GLobalでソースを読みやすくしたHTMLファイル作成
- ホスト側でホームディレクトリのnotebooks/Pyaq/Pyaq/HTML/index.htmlをブラウザで開く
cd Pyaq htags -afFIsngov --gtagslabel=pygments
- 以下を実行し、IPython3を起動
cd /tf/notebooks/Pyaq/Pyaq cp pre_train/model.ckpt . # 学習済みモデルを利用できるように pip3 install tensorflow==1.4 # 古いバージョンに下げて、問題回避 ipython3 # ipython3起動
9.2.5 IPython内で以下を実行
- Boardオブジェクトb を Boardオブジェクトc にコピーするには、b.copy(c)で可能
from board import * b=Board() c=Board() b.place_stone(str2ev("E7")) # E7に石を置く b.copy(c) b.showboard() # ボードを表示
9.3 この章でのまとめ
- ボードクラスのコピー方法について( bをcにコピーするなら、b.copy(c) で可能 )
10 幾つかの調査関数をBoardクラスのメンバ関数に組み込み
- tensorflow/tensorflowのイメージを拡張その2(GNU GLobal入り)https://www.youtube.com/watch?v=FFWRbgJjekoを利用します。
10.1 以下の操作を行っている動画
10.2 幾つかの調査関数をBoardクラスのメンバ関数に組み込む手順
10.2.1 イメージ起動
- tensorflow/tensorflowのイメージを拡張その2(GNU GLobal入り)https://www.youtube.com/watch?v=FFWRbgJjekoを利用します。
- 以下を実行して表示される一番下のhttp://127.0.0.1 …. をコピペしてブラウザで開く
docker run -it --rm -v $(realpath ~/notebooks):/tf/notebooks -p 8888:8888 mytensorflow
10.2.2 シェル起動
- New から terminalを選択して、ターミナル起動
10.2.3 シェルで以下のコマンドを実行
sudo su - user cd /tf/notebooks/Pyaq/Pyaq cp pre_train/model.ckpt . # 学習済みモデルを利用できるように # pip3 install tensorflow==1.4 # AVX拡張命令の使えないCPUの場合, 古いバージョンに下げて、問題回避 # ipython3 # ipython3起動
10.2.4 以前の章でPyaqのソースをゲットしてないなら
- ディレクトリ作成
cd /tf/notebooks/ sudo mkdir Pyaq
- 作成したPyaqディレクトリの所有権変更
sudo chown user.user Pyaq cd Pyaq
- Pyaq ソースゲット
git clone https://github.com/ymgaq/Pyaq.git
- Pyaq ソースゲット
- GNU GLobalでソースを読みやすくしたHTMLファイル作成
- ホスト側でホームディレクトリのnotebooks/Pyaq/Pyaq/HTML/index.htmlをブラウザで開く
cd Pyaq htags -afFIsngov --gtagslabel=pygments
- 以下を実行し、IPython3を起動
cd /tf/notebooks/Pyaq/Pyaq cp pre_train/model.ckpt . # 学習済みモデルを利用できるように # pip3 install tensorflow==1.4 # AVX拡張命令の使えないCPUの場合, 古いバージョンに下げて、問題回避 # ipython3 # ipython3起動
10.2.5 board.pyを編集
- ホスト側なら~/notebooks/Pyaq/Pyaq/board.py を編集
- Dockerイメージ内部なら /tf/notebooks/Pyaq/Pyaq/board.py を編集
- Boardクラスのメンバ関数を追加
- score関数の後に以下を追加する
- bscore関数は前の章で追加したものと同じ、score関数内部の計算集計の詳細をゲットできる
- myShowSg関数は指定した座標(strタイプ ex. “A1″)のStoneGroupeのメンバ変数の状態表示
- myShowSgAll関数は、全ての石が置かれている目に対して、myShowSg関数を実行
- listUpStoneEv関数は石が置かれているev値を配列にして返す(白石、黒石それぞれ)
- listUpAtr関数は全ての盤面の石がおかれている所をチェックし、その目のStoneGroupのAtr値(あたり目かもしれない)をリストアップ。(その目が空の場合のみ集める)
- listUpNeedCheckEvs関数は全ての盤面の石がおかれている所をチェックし、その目のStoneGroupのAtr値(あたり目かもしれない)をリストアップ。(StoneGroupeのlibsの数が1でその目が空の場合のみ集める)
.....省略 def bscore(self): .....省略 return stone_cnt[1] - stone_cnt[0] - KOMI def bscore(self): stone_cnt = [0, 0, 0, 0, 0] for rv in range(BVCNT): v = rv2ev(rv) c = self.color[v] if c <= 1: stone_cnt[c] += 1 else: nbr_cnt = [0, 0, 0, 0] for d in dir4: nbr_cnt[self.color[v + d]] += 1 if nbr_cnt[0] > 0 and nbr_cnt[1] == 0: stone_cnt[0+2] += 1 elif nbr_cnt[1] > 0 and nbr_cnt[0] == 0: stone_cnt[1+2] += 1 stone_cnt[4]= stone_cnt[1] - stone_cnt[0] - KOMI + stone_cnt[1+2] - stone_cnt[0+2] return stone_cnt def myShowSg(self, x): print(">>>>>>>: "+x) print("lib_cnt: ", end=" ") print(self.sg[str2ev(x)].lib_cnt) print("size : ", end=" ") print(self.sg[str2ev(x)].size) print("v_atr : ", end=" ") print(str(self.sg[str2ev(x)].v_atr)+" : "+ev2str(self.sg[str2ev(x)].v_atr)) print("libs : ", end=" ") print(self.sg[str2ev(x)].libs) for i in self.sg[str2ev(x)].libs: print(ev2str(i), end=", ") print("") def myShowSgAll(self): ans = [[],[]] print("************ X ") for rv in range(BVCNT): v = rv2ev(rv) c = self.color[v] if c == 1: self.myShowSg(ev2str(v)) print("************ O ") for rv in range(BVCNT): v = rv2ev(rv) c = self.color[v] if c == 0: self.myShowSg(ev2str(v)) def listUpStoneEv(self): ans = [[],[]] for rv in range(BVCNT): v = rv2ev(rv) c = self.color[v] if c == 0: ans[0].append(v) else: if c == 1: ans[1].append(v) return ans def listUpAtr(self): ans = [[],[]] for rv in range(BVCNT): v = rv2ev(rv) c = self.color[v] v2 = self.sg[v].v_atr if self.color[v2]==2 : if c == 0: ans[0].append(v2) else: if c == 1: ans[1].append(v2) return ans def listUpNeedCheckEvs(self): ans = [[],[]] for rv in range(BVCNT): v = rv2ev(rv) c = self.color[v] c2 = self.sg[v].lib_cnt if c2 == 1 : v2 = list(self.sg[v].libs)[0] if c == 0: ans[0].append(v2) else: if c == 1: ans[1].append(v2) return ans .....省略
10.2.6 IPythonを起動
ipython3
10.2.7 IPython内で以下を実行
from board import * b=Board() # ボードを作成 b.place_stone(str2ev("E5")) # E5に石を置く print(b.bscore()) b.myShowSgAll() print(b.listUpStoneEv()) print(b.listUpNeedCheckEvs()) b.showboard() # [0, 1, 0, 4, -2.0] # ************ X # >>>>>>>: E5 # lib_cnt: 4 # size : 1 # v_atr : 49 : E4 # libs : {49, 59, 61, 71} # E4, D5, F5, E6, # ************ O # [[], [60]] # [[], []] # A B C D E F G H J # 9 . . . . . . . . . 9 # 8 . . . . . . . . . 8 # 7 . . . . . . . . . 7 # 6 . . . . . . . . . 6 # 5 . . . . X . . . . 5 # 4 . . . . . . . . . 4 # 3 . . . . . . . . . 3 # 2 . . . . . . . . . 2 # 1 . . . . . . . . . 1 # A B C D E F G H J b.place_stone(str2ev("D6")) # D6に石を置く print(b.bscore()) b.myShowSgAll() print(b.listUpStoneEv()) print(b.listUpNeedCheckEvs()) b.showboard() # [0, 2, 0, 6, 1.0] # ************ X # >>>>>>>: E5 # lib_cnt: 4 # size : 1 # v_atr : 49 : E4 # libs : {49, 59, 61, 71} # E4, D5, F5, E6, # >>>>>>>: D6 # lib_cnt: 4 # size : 1 # v_atr : 59 : D5 # libs : {81, 59, 69, 71} # D7, D5, C6, E6, # ************ O # [[], [60, 70]] # [[], []] # A B C D E F G H J # 9 . . . . . . . . . 9 # 8 . . . . . . . . . 8 # 7 . . . . . . . . . 7 # 6 . . . X . . . . . 6 # 5 . . . . X . . . . 5 # 4 . . . . . . . . . 4 # 3 . . . . . . . . . 3 # 2 . . . . . . . . . 2 # 1 . . . . . . . . . 1 # A B C D E F G H J b.place_stone(str2ev("F6")) # F6に石を置く print(b.bscore()) b.myShowSgAll() print(b.listUpStoneEv()) print(b.listUpNeedCheckEvs()) b.showboard() # [0, 3, 0, 8, 4.0] # ************ X # >>>>>>>: E5 # lib_cnt: 4 # size : 1 # v_atr : 49 : E4 # libs : {49, 59, 61, 71} # E4, D5, F5, E6, # >>>>>>>: D6 # lib_cnt: 4 # size : 1 # v_atr : 59 : D5 # libs : {81, 59, 69, 71} # D7, D5, C6, E6, # >>>>>>>: F6 # lib_cnt: 4 # size : 1 # v_atr : 61 : F5 # libs : {73, 83, 61, 71} # G6, F7, F5, E6, # ************ O # [[], [60, 70, 72]] # [[], []] # A B C D E F G H J # 9 . . . . . . . . . 9 # 8 . . . . . . . . . 8 # 7 . . . . . . . . . 7 # 6 . . . X . X . . . 6 # 5 . . . . X . . . . 5 # 4 . . . . . . . . . 4 # 3 . . . . . . . . . 3 # 2 . . . . . . . . . 2 # 1 . . . . . . . . . 1 # A B C D E F G H J b.place_stone(str2ev("E7")) # E7に石を置く print(b.bscore()) b.myShowSgAll() print(b.listUpStoneEv()) print(b.listUpNeedCheckEvs()) b.showboard() # [0, 4, 0, 9, 6.0] # ************ X # >>>>>>>: E5 # lib_cnt: 4 # size : 1 # v_atr : 49 : E4 # libs : {49, 59, 61, 71} # E4, D5, F5, E6, # >>>>>>>: D6 # lib_cnt: 4 # size : 1 # v_atr : 59 : D5 # libs : {81, 59, 69, 71} # D7, D5, C6, E6, # >>>>>>>: F6 # lib_cnt: 4 # size : 1 # v_atr : 61 : F5 # libs : {73, 83, 61, 71} # G6, F7, F5, E6, # >>>>>>>: E7 # lib_cnt: 4 # size : 1 # v_atr : 71 : E6 # libs : {81, 83, 93, 71} # D7, F7, E8, E6, # ************ O # [[], [60, 70, 72, 82]] # [[], []] # A B C D E F G H J # 9 . . . . . . . . . 9 # 8 . . . . . . . . . 8 # 7 . . . . X . . . . 7 # 6 . . . X . X . . . 6 # 5 . . . . X . . . . 5 # 4 . . . . . . . . . 4 # 3 . . . . . . . . . 3 # 2 . . . . . . . . . 2 # 1 . . . . . . . . . 1 # A B C D E F G H J b.turn=0 b.place_stone(str2ev("F7")) # E7に石を置く print(b.bscore()) b.myShowSgAll() print(b.listUpStoneEv()) print(b.listUpNeedCheckEvs()) b.showboard() # [1, 4, 2, 8, 2.0] # ************ X # >>>>>>>: E5 # lib_cnt: 4 # size : 1 # v_atr : 49 : E4 # libs : {49, 59, 61, 71} # E4, D5, F5, E6, # >>>>>>>: D6 # lib_cnt: 4 # size : 1 # v_atr : 59 : D5 # libs : {81, 59, 69, 71} # D7, D5, C6, E6, # >>>>>>>: F6 # lib_cnt: 3 # size : 1 # v_atr : 61 : F5 # libs : {73, 61, 71} # G6, F5, E6, # >>>>>>>: E7 # lib_cnt: 3 # size : 1 # v_atr : 71 : E6 # libs : {81, 93, 71} # D7, E8, E6, # ************ O # >>>>>>>: F7 # lib_cnt: 2 # size : 1 # v_atr : 94 : F8 # libs : {84, 94} # G7, F8, # [[83], [60, 70, 72, 82]] # [[], []] # A B C D E F G H J # 9 . . . . . . . . . 9 # 8 . . . . . . . . . 8 # 7 . . . . X O . . . 7 # 6 . . . X . X . . . 6 # 5 . . . . X . . . . 5 # 4 . . . . . . . . . 4 # 3 . . . . . . . . . 3 # 2 . . . . . . . . . 2 # 1 . . . . . . . . . 1 # A B C D E F G H J b.place_stone(str2ev("G6")) # E7に石を置く print(b.bscore()) b.myShowSgAll() print(b.listUpStoneEv()) print(b.listUpNeedCheckEvs()) b.showboard() # [2, 4, 4, 7, -2.0] # ************ X # >>>>>>>: E5 # lib_cnt: 4 # size : 1 # v_atr : 49 : E4 # libs : {49, 59, 61, 71} # E4, D5, F5, E6, # >>>>>>>: D6 # lib_cnt: 4 # size : 1 # v_atr : 59 : D5 # libs : {81, 59, 69, 71} # D7, D5, C6, E6, # >>>>>>>: F6 # lib_cnt: 2 # size : 1 # v_atr : 61 : F5 # libs : {61, 71} # F5, E6, # >>>>>>>: E7 # lib_cnt: 3 # size : 1 # v_atr : 71 : E6 # libs : {81, 93, 71} # D7, E8, E6, # ************ O # >>>>>>>: G6 # lib_cnt: 3 # size : 1 # v_atr : 62 : G5 # libs : {74, 84, 62} # H6, G7, G5, # >>>>>>>: F7 # lib_cnt: 2 # size : 1 # v_atr : 94 : F8 # libs : {84, 94} # G7, F8, # [[73, 83], [60, 70, 72, 82]] # [[], []] # A B C D E F G H J # 9 . . . . . . . . . 9 # 8 . . . . . . . . . 8 # 7 . . . . X O . . . 7 # 6 . . . X . X O . . 6 # 5 . . . . X . . . . 5 # 4 . . . . . . . . . 4 # 3 . . . . . . . . . 3 # 2 . . . . . . . . . 2 # 1 . . . . . . . . . 1 # A B C D E F G H J b.place_stone(str2ev("F5")) # E7に石を置く print(b.bscore()) b.myShowSgAll() print(b.listUpStoneEv()) print(b.listUpNeedCheckEvs()) b.showboard() # [3, 4, 5, 6, -5.0] # ************ X # >>>>>>>: E5 # lib_cnt: 3 # size : 1 # v_atr : 49 : E4 # libs : {49, 59, 71} # E4, D5, E6, # >>>>>>>: D6 # lib_cnt: 4 # size : 1 # v_atr : 59 : D5 # libs : {81, 59, 69, 71} # D7, D5, C6, E6, # >>>>>>>: F6 # lib_cnt: 1 # size : 1 # v_atr : 61 : F5 # libs : {71} # E6, # >>>>>>>: E7 # lib_cnt: 3 # size : 1 # v_atr : 71 : E6 # libs : {81, 93, 71} # D7, E8, E6, # ************ O # >>>>>>>: F5 # lib_cnt: 2 # size : 1 # v_atr : 50 : F4 # libs : {50, 62} # F4, G5, # >>>>>>>: G6 # lib_cnt: 3 # size : 1 # v_atr : 62 : G5 # libs : {74, 84, 62} # H6, G7, G5, # >>>>>>>: F7 # lib_cnt: 2 # size : 1 # v_atr : 94 : F8 # libs : {84, 94} # G7, F8, # [[61, 73, 83], [60, 70, 72, 82]] # [[], [71]] # A B C D E F G H J # 9 . . . . . . . . . 9 # 8 . . . . . . . . . 8 # 7 . . . . X O . . . 7 # 6 . . . X . X O . . 6 # 5 . . . . X O . . . 5 # 4 . . . . . . . . . 4 # 3 . . . . . . . . . 3 # 2 . . . . . . . . . 2 # 1 . . . . . . . . . 1 # A B C D E F G H J print(ev2str(71)) # E6 # E6に石を置けば取れる可能性があることをチェックできている
10.3 この章でのまとめ
- 幾つかの調査関数をBoardクラスの中に組み込んで使ってみた
- StoneGroupの中身が調べやすくなった
- アタリになっている可能性のあるev値のリストアップが出来た
11 playした時に取り除いた石のev値を保持するように改造
- tensorflow/tensorflowのイメージを拡張その2(GNU GLobal入り)https://www.youtube.com/watch?v=FFWRbgJjekoを利用します。
11.1 以下の操作を行っている動画
11.2 playした時に取り除いた石のev値を保持するように改造 する手順
11.2.1 イメージ起動
- tensorflow/tensorflowのイメージを拡張その2(GNU GLobal入り)https://www.youtube.com/watch?v=FFWRbgJjekoを利用します。
- 以下を実行して表示される一番下のhttp://127.0.0.1 …. をコピペしてブラウザで開く
docker run -it --rm -v $(realpath ~/notebooks):/tf/notebooks -p 8888:8888 mytensorflow
11.2.2 シェル起動
- New から terminalを選択して、ターミナル起動
11.2.3 シェルで以下のコマンドを実行
sudo su - user cd /tf/notebooks/Pyaq/Pyaq cp pre_train/model.ckpt . # 学習済みモデルを利用できるように # pip3 install tensorflow==1.4 # AVX拡張命令の使えないCPUの場合, 古いバージョンに下げて、問題回避 # ipython3 # ipython3起動
11.2.4 以前の章でPyaqのソースをゲットしてないなら
- ディレクトリ作成
cd /tf/notebooks/ sudo mkdir Pyaq
- 作成したPyaqディレクトリの所有権変更
sudo chown user.user Pyaq cd Pyaq
- Pyaq ソースゲット
git clone https://github.com/ymgaq/Pyaq.git
- Pyaq ソースゲット
- GNU GLobalでソースを読みやすくしたHTMLファイル作成
- ホスト側でホームディレクトリのnotebooks/Pyaq/Pyaq/HTML/index.htmlをブラウザで開く
cd Pyaq htags -afFIsngov --gtagslabel=pygments
- 以下を実行し、IPython3を起動
cd /tf/notebooks/Pyaq/Pyaq cp pre_train/model.ckpt . # 学習済みモデルを利用できるように # pip3 install tensorflow==1.4 # AVX拡張命令の使えないCPUの場合, 古いバージョンに下げて、問題回避 # ipython3 # ipython3起動
11.2.5 board.pyを編集
- ホスト側なら~/notebooks/Pyaq/Pyaq/board.py を編集
- Dockerイメージ内部なら /tf/notebooks/Pyaq/Pyaq/board.py を編集
- Boardクラスに remove_ev_list を追加
- self.remove_ev_list=[] を追加
.....省略 class Board(object): def __init__(self): # 1-d array ([EBVCNT]) of stones or empty or exterior # 0: white 1: black # 2: empty 3: exterior self.color = np.full(EBVCNT, 3) self.sg = [StoneGroup() for _ in range(EBVCNT)] # stone groups self.clear() self.remove_ev_list=[]
- Boardクラスの remove メソッドを以下に改造
- print(“remove call:”
str(v)“=”+ev2str(v)) 追加 - print(“remove:”
str(v_tmp)“=”+ev2str(v_tmp)) 追加 - self.remove_ev_list.append(v_tmp) 追加
.....省略 def remove(self, v): print("remove call:"+str(v)+"="+ev2str(v)) # remove stone group including stone at v v_tmp = v while 1: self.remove_cnt += 1 self.color[v_tmp] = 2 # empty print("remove:"+str(v_tmp)+"="+ev2str(v_tmp)) self.remove_ev_list.append(v_tmp) self.id[v_tmp] = v_tmp # reset id for d in dir4: nv = v_tmp + d # add liberty to neighbor groups self.sg[self.id[nv]].add(v_tmp) v_next = self.next[v_tmp] self.next[v_tmp] = v_tmp v_tmp = v_next if v_tmp == v: break # finish when all stones are removed
- print(“remove call:”
11.2.6 IPythonを起動
python3
11.2.7 IPython内で以下を実行
from board import * b=Board() # ボードを作成 b.place_stone(str2ev("E5")) # E5に石を置く print(b.remove_ev_list) b.place_stone(str2ev("D6")) # D6に石を置く print(b.remove_ev_list) b.place_stone(str2ev("F6")) # F6に石を置く print(b.remove_ev_list) b.place_stone(str2ev("E7")) # E7に石を置く print(b.remove_ev_list) b.showboard() # ボードを表示 # [] # [] # [] # [] # A B C D E F G H J # 9 . . . . . . . . . 9 # 8 . . . . . . . . . 8 # 7 . . . . X . . . . 7 # 6 . . . X . X . . . 6 # 5 . . . . X . . . . 5 # 4 . . . . . . . . . 4 # 3 . . . . . . . . . 3 # 2 . . . . . . . . . 2 # 1 . . . . . . . . . 1 # A B C D E F G H J b.turn=0 b.place_stone(str2ev("F7")) # E7に石を置く print(b.remove_ev_list) b.place_stone(str2ev("G6")) # G6に石を置く print(b.remove_ev_list) b.place_stone(str2ev("F5")) # F5に石を置く print(b.remove_ev_list) b.showboard() # ボードを表示 # [] # [] # [] # A B C D E F G H J # 9 . . . . . . . . . 9 # 8 . . . . . . . . . 8 # 7 . . . . X O . . . 7 # 6 . . . X . X O . . 6 # 5 . . . . X O . . . 5 # 4 . . . . . . . . . 4 # 3 . . . . . . . . . 3 # 2 . . . . . . . . . 2 # 1 . . . . . . . . . 1 # A B C D E F G H J b.play(str2ev("E6")) # F5に石を置く print(b.remove_ev_list) # 取り除いた石のEV値表示 print(ev2str(72)) # ev値72のstr形式は => F6 ##################### from board import * b=Board() # ボードを作成 b.clear() # 盤の初期化 b.remove_ev_list.clear() # b.remove_ev_listをクリア print(b.remove_ev_list) b.place_stone(str2ev("E5")) # E5に石を置く print(b.remove_ev_list) b.place_stone(str2ev("D5")) # D5に石を置く b.showboard() # ボードを表示 # [] # [] # A B C D E F G H J # 9 . . . . . . . . . 9 # 8 . . . . . . . . . 8 # 7 . . . . . . . . . 7 # 6 . . . . . . . . . 6 # 5 . . . X X . . . . 5 # 4 . . . . . . . . . 4 # 3 . . . . . . . . . 3 # 2 . . . . . . . . . 2 # 1 . . . . . . . . . 1 # A B C D E F G H J b.turn=0 b.place_stone(str2ev("C5")) # C5に石を置く print(b.remove_ev_list) b.place_stone(str2ev("D6")) # D6に石を置く print(b.remove_ev_list) b.place_stone(str2ev("E6")) # E6に石を置く print(b.remove_ev_list) b.place_stone(str2ev("F5")) # F5に石を置く print(b.remove_ev_list) b.place_stone(str2ev("D4")) # F5に石を置く print(b.remove_ev_list) b.showboard() # ボードを表示 # [] # [] # [] # [] # [] # A B C D E F G H J # 9 . . . . . . . . . 9 # 8 . . . . . . . . . 8 # 7 . . . . . . . . . 7 # 6 . . . O O . . . . 6 # 5 . . O X X O . . . 5 # 4 . . . O . . . . . 4 # 3 . . . . . . . . . 3 # 2 . . . . . . . . . 2 # 1 . . . . . . . . . 1 # A B C D E F G H J b.play(str2ev("E4")) # E4に石を置いてXを取る print(b.remove_ev_list) # 取った石のev値のリストゲット # [59, 60] for i in b.remove_ev_list: #ev値はわかりにくいから、ループまわしてstr型に変換 print(str(i)+":"+ev2str(i)) # 59:D5 # 60:E5
11.3 この章でのまとめ
- 取り除いた石のev値のリストをゲットできるように改造してみた
- 取る石が複数個でも上手く動いていることを確認
12 Boardクラスのメンバ関数拡張
- tensorflow/tensorflowのイメージを拡張その2(GNU GLobal入り)https://www.youtube.com/watch?v=FFWRbgJjekoを利用します。
12.1 以下の操作を行っている動画
12.2 Boardクラスのメンバ関数拡張 手順
12.2.1 イメージ起動
- tensorflow/tensorflowのイメージを拡張その2(GNU GLobal入り)https://www.youtube.com/watch?v=FFWRbgJjekoを利用します。
- 以下を実行して表示される一番下のhttp://127.0.0.1 …. をコピペしてブラウザで開く
docker run -it --rm -v $(realpath ~/notebooks):/tf/notebooks -p 8888:8888 mytensorflow
12.2.2 シェル起動
- New から terminalを選択して、ターミナル起動
12.2.3 シェルで以下のコマンドを実行
sudo su - user cd /tf/notebooks/Pyaq/Pyaq cp pre_train/model.ckpt . # 学習済みモデルを利用できるように # pip3 install tensorflow==1.4 # AVX拡張命令の使えないCPUの場合, 古いバージョンに下げて、問題回避 # ipython3 # ipython3起動
12.2.4 以前の章でPyaqのソースをゲットしてないなら
- ディレクトリ作成
cd /tf/notebooks/ sudo mkdir Pyaq
- 作成したPyaqディレクトリの所有権変更
sudo chown user.user Pyaq cd Pyaq
- Pyaq ソースゲット
git clone https://github.com/ymgaq/Pyaq.git
- Pyaq ソースゲット
- GNU GLobalでソースを読みやすくしたHTMLファイル作成
- ホスト側でホームディレクトリのnotebooks/Pyaq/Pyaq/HTML/index.htmlをブラウザで開く
cd Pyaq htags -afFIsngov --gtagslabel=pygments
- 以下を実行し、IPython3を起動
cd /tf/notebooks/Pyaq/Pyaq cp pre_train/model.ckpt . # 学習済みモデルを利用できるように # pip3 install tensorflow==1.4 # AVX拡張命令の使えないCPUの場合, 古いバージョンに下げて、問題回避 # ipython3 # ipython3起動
12.2.5 board.pyを編集
- ホスト側なら~/notebooks/Pyaq/Pyaq/board.py を編集
- Dockerイメージ内部なら /tf/notebooks/Pyaq/Pyaq/board.py を編集
- Boardクラスのメンバ関数を追加
- 前の章の石を取り除いたものをremove_ev_listにいれる修正もした方が良いhttps://www.youtube.com/embed/CbW21FVp_yc
- Boardクラスのscore関数の定義の後に以下を追加
- 昔の章で追加した関数も含まれているので、昔のboardクラスにメンバ関数を追加された方は def listUpLibsEvs(self): 以下を追加してください。
- listUpLibsEvsは石のある目のStoneGroupeのlibsを集めて返す関数
- filterEmpty(self,listorset) は listorset のev値が空の時(2)のものだけフィルターしてリストでかえす
- getDeadStonesEv(self,ev) は ev値に石を置いた時に取れる石のev値を返す
- place_stones(self,evs) は、evsにstr形式で与えた目に石を置く関数(ルール上置けない場所には置けない)
- place_stones10(self,evs1,evs0) は X(先手)の目をevs1に O(後手)の目をevs0に置く
- place_stones01(self,evs0,evs1) は O(後手)の目をevs0に置く は X(先手)の目をevs1に置く(置く順番が異なる)
- evs2strs(self,evs) は evの配列等を、str形式の配列で返す
.....省略 def bscore(self): stone_cnt = [0, 0, 0, 0, 0] for rv in range(BVCNT): v = rv2ev(rv) c = self.color[v] if c <= 1: stone_cnt[c] += 1 else: nbr_cnt = [0, 0, 0, 0] for d in dir4: nbr_cnt[self.color[v + d]] += 1 if nbr_cnt[0] > 0 and nbr_cnt[1] == 0: stone_cnt[0+2] += 1 elif nbr_cnt[1] > 0 and nbr_cnt[0] == 0: stone_cnt[1+2] += 1 stone_cnt[4]= stone_cnt[1] - stone_cnt[0] - KOMI + stone_cnt[1+2] - stone_cnt[0+2] return stone_cnt def myShowSg(self, x): print(">>>>>>>: "+x) print("lib_cnt: ", end=" ") print(self.sg[str2ev(x)].lib_cnt) print("size : ", end=" ") print(self.sg[str2ev(x)].size) print("v_atr : ", end=" ") print(str(self.sg[str2ev(x)].v_atr)+" : "+ev2str(self.sg[str2ev(x)].v_atr)) print("libs : ", end=" ") print(self.sg[str2ev(x)].libs) for i in self.sg[str2ev(x)].libs: print(ev2str(i), end=", ") print("") def myShowSgAll(self): ans = [[],[]] print("************ X ") for rv in range(BVCNT): v = rv2ev(rv) c = self.color[v] if c == 1: self.myShowSg(ev2str(v)) print("************ O ") for rv in range(BVCNT): v = rv2ev(rv) c = self.color[v] if c == 0: self.myShowSg(ev2str(v)) def listUpStoneEv(self): ans = [[],[]] for rv in range(BVCNT): v = rv2ev(rv) c = self.color[v] if c == 0: ans[0].append(v) else: if c == 1: ans[1].append(v) return ans def listUpAtr(self): ans = [[],[]] for rv in range(BVCNT): v = rv2ev(rv) c = self.color[v] v2 = self.sg[v].v_atr if self.color[v2]==2 : if c == 0: ans[0].append(v2) else: if c == 1: ans[1].append(v2) return ans def listUpNeedCheckEvs(self): ans = [[],[]] for rv in range(BVCNT): v = rv2ev(rv) c = self.color[v] c2 = self.sg[v].lib_cnt if c2 == 1 : v2 = list(self.sg[v].libs)[0] if c == 0: ans[0].append(v2) else: if c == 1: ans[1].append(v2) return ans def listUpLibsEvs(self): ans = [set([]),set([])] for rv in range(BVCNT): v = rv2ev(rv) c = self.color[v] if c == 0 or c == 1: ans[c] = ans[c] | self.sg[v].libs ans=[set(self.filterEmpty(ans[0])),set(self.filterEmpty(ans[1]))] ans.append(ans[0]|ans[1]) return ans def filterEmpty(self,listorset): ans=[] for v in listorset: c = self.color[v] if c == 2 : ans.append(v) return ans def getDeadStonesEv(self,ev): c=Board() self.copy(c) ans1=c.legal(ev) c.play(ev) return (ans1,c.remove_ev_list) def place_stones(self,evs): for v in evs: self.place_stone(str2ev(v)) def place_stones10(self,evs1,evs0): orgturn=self.turn self.turn=1 self.place_stones(evs1) self.turn=0 self.place_stones(evs0) self.turn=self.turn def place_stones01(self,evs0,evs1): orgturn=self.turn self.turn=0 self.place_stones(evs0) self.turn=1 self.place_stones(evs1) self.turn=self.turn def evs2strs(self,evs): ans=[] for v in evs: ans.append(ev2str(v)) return ans .....省略
12.2.6 IPythonを起動
ipython3
12.2.7 IPython内で以下を実行
from board import * b=Board() # ボードを作成 b.place_stones10(["E5","E6"],["E7","D6","D5","E4","F6"]) # 石を置く # F5に石を置いたら、どこが取れるか (True, [60, 71]) # 最初のTrueは置ける場所を示す b.getDeadStonesEv(str2ev("F5")) # F5に石を置いたら、どこが取れるかをstr形式で ['E5', 'E6'] b.evs2strs(b.getDeadStonesEv(str2ev("F5"))[1]) b.showboard() # ボードを表示 # A B C D E F G H J # 9 . . . . . . . . . 9 # 8 . . . . . . . . . 8 # 7 . . . . O . . . . 7 # 6 . . . O X O . . . 6 # 5 . . . O X . . . . 5 # 4 . . . . O . . . . 4 # 3 . . . . . . . . . 3 # 2 . . . . . . . . . 2 # 1 . . . . . . . . . 1 # A B C D E F G H J b.turn # 手番確認 => 0 b.turn=1 b.getDeadStonesEv(str2ev("F5")) # F5にXをおいても取れない => (True, []) b.listUpLibsEvs() # 石に上下で隣接してて置ける場所をリストアップ # [{38, 48, 50, 58, 61, 69, 73, 81, 83, 93}, # {61}, # {38, 48, 50, 58, 61, 69, 73, 81, 83, 93}] b.evs2strs(b.listUpLibsEvs()[2]) # 石に隣接している空の目の座標をstr形式に変換 # ['C6', 'E3', 'G6', 'D4', 'D7', 'F4', 'F7', 'F5', 'C5', 'E8']
12.3 この章でのまとめ
- Boardクラスのメンバ関数の拡張を行った
- 事前に取れる石のチェックを出来るようになった
13 今後
- こんぱ今後も文書追加していきます。
14 この文書のチェンジログ
- 2020/02/03 初版
- 2020/02/05 Boardクラスの調査2の章を追加
- 2020/02/09 評価関数で、好きな盤の状態を評価させてみた の章追加
- 2020/02/10 任意の盤を与えてお勧めの手をゲット の章追加
- 2020/03/05 Groupクラスの調査 の章追加
- 2020/03/06 Boardクラスのscore関数の調査 の章追加
- 2020/03/06 Boardクラスのコピー方法について調査 の章追加
- 2020/03/13 幾つかの調査関数をBoardクラスのメンバ関数に組み込み の章追加
- 2020/03/14 playした時に取り除いた石のev値を保持するように改造 の章追加
- 2020/03/14 Boardクラスのメンバ関数拡張 の章追加
- 2020/03/15 Boardクラスのメンバ関数拡張2(わかりやすいStoneGroup機能追加) の章追加
- 2020/04/04 Boardクラスのメンバ関数拡張2(わかりやすいStoneGroup機能追加) の章削除(バグがありました)
Created: 2020-04-04 土 20:52