彩の評価関数について 2004/04/17 CGF例会 山下 宏 かかっている時間(VC++だと「ビルド」「プロファイル」で調べられます) 手の生成 5% 評価関数 73% 連の死活 (60%) 評価関数に含まれるので重複してます。 石を進める(25%) 石を戻す (10%) 全体の時間の73%は評価関数が使っている。 探索局面速度は19路盤で300局面/秒。遅いのは連の死活探索を含んでいるため。 連の死活探索の速度は380,000局面/秒 (Pentium3M 1.13GHz) 実際、囲碁プログラムの棋力を決める8割以上は評価関数の精度に依存する?と思われます。 ・彩の評価関数の全体(下の4段階に大きく分けられます) (1).地の認識 (2).群の認識(連と地を含む石の集合) (3).群の強さを認識(0%で死、100%で活) (4).数値に変換 (1).地の認識 1. 全ての石のポテンシャルを計算する(差分) ・石から距離4で下がっていく数値。中央では距離2まで。終盤になると中央でも距離4まで 序盤、終盤の判定は石の盤面に占める割合で(序盤 0-10%、中盤 10%-25%、終盤 25%-) 2.連の死活で死んでいる石を盤上からいったん消す。(差分、探索) 3.確定地を計算 ・ポテンシャルを元に計算。 ・相手の石の周り4マスは自分の地にならない。 ・相手の石から桂馬で見える範囲は自分の地にはならない。 4.2.で消した石を復活 (2).群の認識(連と地を含む石の集合) 5.接続ポイントを調べる(確定地ではなく、そこに打たれた敵が石を打てば殺せる位置)(差分、探索) 6.繋がっている確定地を、一つ一つ「地」として認識する(色を塗っていくペイント処理みたいな) 7.確定地に接している連を認識 8.連同士の接続を調べる(ダメを2つ共有。接続ポイントで接続) ・3x3、3x4の特定の形での接続を調べる(20種類ぐらい) 例: +○● ---> この石(○)のダメが3以上であること!割りこみが当たりだと話が違う。 +++ ○○● ・2間、さるすべりでの連絡 9.連の接続を元に群を形成 (3).群の強さを認識(0%で死、100%で活) 10.確定地の眼数を計算 11.2眼で生きている群を最初に認識 12.1手で取れる2個以上の石があれば+0.5眼 13.次に打てば1眼になる場所は+0.5眼 14.生きている群に次に打てば接続できる状態は1眼 (2つあれば2眼。1眼の群と4箇所接続できれば2眼。自分が1.5眼で1眼の石と接続できるなら2眼など) 15.群の周囲の連を先手で殺せるなら、そこも接続可能位置に 16. 石の自由度を計算(4x4で敵の確定地でない空間がある場所に接続できる場合) 17. 群の周囲を囲っている敵の連との攻め合いを判定。 18.攻め合い判定で生き返った石があるため、再度攻め合いを判定。(セキ崩れの認識) 19.先手で打たれて死ぬ群は50%以上の安全度にしない。 20.セキに見える1眼しかない石を死に 21. 大きな単眼に1子放り込まれた形の死を不明にする。 (4).数値に変換 22.群が死ぬ前の確定地をコピー(手の生成などに使う) 23.死んでいる群のポテンシャルを全て消す。 24. 復活する死連のポテンシャルを全て書く 25. 確定地を求める(部分更新用) 26. 大きく囲われた場合にだけ地になるように、中央の石に接していない空点から確定地を削る。 27. 不安定な群をマイナスに 28.不安定な連をマイナスに(先手で死に、先手で生きる場合)1個の連が1つの群の場合は無視 29.大きな単眼だけで生きている軍をマイナスに 30.取られた石を計算 31.死んだ群を戻す 32.また死に石を戻す。 33. 盤上にある石を実際に取る方が少しだけ得なように調整する。(コウ材を減らす意味で。また取った方がすっきりするし) // root_flag は全面更新させるときにオン 1...全面更新、2...群のデータで止める int eval::hyouka_inc_sub(int root_flag) { renraku_2ken_search(); // 2間飛び連絡を探索で検証 // ポテンシャルの部分変更(影響力関数、石の近くほど点数が高い) // 連の死活の部分変更。ポテンシャルの変更部分と、手順中に打った石(ポテンシャルの値が変わっている場所)シチョウ当たりは無視 // 再探索リストを作る // 手順中に打った石 ---> 自分自身の位置にもポテンシャルを追加してるので不要? // 連の死活で、生死の着手候補に既に石がある場合--->連の部分更新ミスなので追加する // 変更連を再探索 // 死石のポテンシャルを削除(同時に石を消す) // 確定地の計算へ k = make_ban_area(); // 確定地を求める(部分更新用) k = del_ban_area(); // 大きく囲われた場合にだけ地になるように、中央の石に接していない空点から確定地を削る。2回。 // 死石を戻す。 research_setsuzoku(root_flag); // 1手で取れる接続ポイントを調べる // また盤上から死に石を消去 paint_area(); // ペイントルーチンで個々の確定地の大きさ、状態を調べる ren_in_area(); // 確定地に接している連を見つける check_near_ren(); // 接続している連を数える。(ダメを2つ共有、接続ポイントで接続) research_make_group(); // 群の形成 get_minmax_ren(); // 群の最小と最大の連を探す area_to_eye(); // その地の形が何眼に相当するか、を計算する。 group_2eye_alive(); // 2眼あれば活。それ以外は全部死で初期化 sente_kill_ren(); // 1手で取れる2個以上の石の連があれば+0.5眼する。 kakujitsu_1gan(); // 確定地ではないが、1手打てば1眼できる場所を探す group_renraku_check(); // 生きている群との接続度合いを計算 shuui_rentori_setuzoku(); // 群の周囲の連を先手で取れるなら、そこでも接続可能 make_runaway_map(); // 自由度を計算 group_semeai_check(); // 外を囲っている群との攻め合い判断 ---> ここで周囲の群を計算している。 group_semeai_check_again(); // 再度計算 ---> 攻め合い判定で死んだ石を取って生き返った群がいるため sente_death_gun_minus();// 先手で打たれて死ぬ群は50%以上の安全度にしない。 seki_group_check(); // セキに見える1眼しかない石を死に tangan_1si_hourikomi(); // 大きな単眼に1子放り込まれた形の死を不明にする。 unknown_gun_around(); // 外周の群を計算していない不安定な群のみを再計算 ---> 評価値としては不要だが、探索で必須なので // 前処理が終了。死んでいる群のポテンシャルを全て消して、復活する死連のポテンシャルを全て書いて確定地の計算をする ---> これで基本となる評価値が得られる。 copy_ban_area(); // 群が死ぬ前の確定地をコピー erase_group(); // 死んでいる群のポテンシャルを全て消す。 reverse_death_ren(); // 復活する死連のポテンシャルを全て書く sum = make_ban_area(); // 確定地を求める(部分更新用)//PRT("確定地=%d\n",sum); sum = del_ban_area(); // 大きく囲われた場合にだけ地になるように、中央の石に接していない空点から確定地を削る。2回。 sum += fuantei_gun_minus(root_flag); // 不安定な群をマイナスに sum += fuantei_ren_minus(); // 不安定な連をマイナスに(先手で死に、先手で生きる場合) sum += big_tangan_minus(); // 大きな単眼だけで生きている軍をマイナスに sum += (agehama[1] - agehama[2])*100; // 取られた石を計算 reset_erase_group(); // 死んだ群を戻す // また死に石を戻す。 // 盤上にある石を実際に取る方が少しだけ得なように調整する。(コウ材を減らす意味で。また取った方がすっきりするし) hozon_ban_gun_map(); // 群の地図と現在の盤面を保存をコピー return sum; } // 外を囲っている群との攻め合い判断 void eval::group_semeai_check(void) { ・ダメが大きい群が安全(基本) ・周囲を囲っている一番ダメが小さい敵の群と比較(不安定な大きさ2以上の群のみ)。 ・ダメの差5以上なら安全。ダメが3足りないとほとんど死。 -5 -4 -3 -2 -1 0 1 2 3 4 5 { 0, 0, 5, 20, 30, 50, 70, 80, 87, 95,100 }; ・自由度がある石は手数が3手伸びる(適当) ・1.5眼の場合は50%、安全度を上げる。 ・活きている石に次に接続できる場合は50%安全度を上げる。(現在が50%なら75%に) ・1子の死にやすく(安全度-5%) ・眼数が多ければ安全度+10% ・先手で死ぬ単独の連は死にやすく(接続、自由度もなく、周囲の敵の連を殺せず、ダメの差が2以上あるなら死ぬ) ・生き群に接続は最低でも50% ・1.5眼は死にはしない。 }