Bonanza6からKKPテーブルを抜き出す

Bonanza6からKKPテーブルだけを抜き出す方法について書いておきます。

Bonanza6ではKKPはmake_listのなかで行なっています。
持ち駒もKKPのPの一種と考えられ、以下のところで計算しています。

  sq_bk0 = SQ_BKING;
  sq_wk0 = SQ_WKING;
  sq_bk1 = Inv(SQ_WKING);
  sq_wk1 = Inv(SQ_BKING);

  score += kkp[sq_bk0][sq_wk0][ kkp_hand_pawn   + I2HandPawn(HAND_B) ];
  score += kkp[sq_bk0][sq_wk0][ kkp_hand_lance  + I2HandLance(HAND_B) ];
  score += kkp[sq_bk0][sq_wk0][ kkp_hand_knight + I2HandKnight(HAND_B) ];
  score += kkp[sq_bk0][sq_wk0][ kkp_hand_silver + I2HandSilver(HAND_B) ];
  score += kkp[sq_bk0][sq_wk0][ kkp_hand_gold   + I2HandGold(HAND_B) ];
  score += kkp[sq_bk0][sq_wk0][ kkp_hand_bishop + I2HandBishop(HAND_B) ];
  score += kkp[sq_bk0][sq_wk0][ kkp_hand_rook   + I2HandRook(HAND_B) ];

  score -= kkp[sq_bk1][sq_wk1][ kkp_hand_pawn   + I2HandPawn(HAND_W) ];
  score -= kkp[sq_bk1][sq_wk1][ kkp_hand_lance  + I2HandLance(HAND_W) ];
  score -= kkp[sq_bk1][sq_wk1][ kkp_hand_knight + I2HandKnight(HAND_W) ];
  score -= kkp[sq_bk1][sq_wk1][ kkp_hand_silver + I2HandSilver(HAND_W) ];
  score -= kkp[sq_bk1][sq_wk1][ kkp_hand_gold   + I2HandGold(HAND_W) ];
  score -= kkp[sq_bk1][sq_wk1][ kkp_hand_bishop + I2HandBishop(HAND_W) ];
  score -= kkp[sq_bk1][sq_wk1][ kkp_hand_rook   + I2HandRook(HAND_W) ];

冒頭のsq_bk1の代入式のところにSQ_WKINGとなっていて、一瞬バグかと疑いますが、これはこれで正しく、KKPでは自駒しか評価できません。

すなわち、KKPをK1K2Pと書くとしたら、PはK1側の駒でなければなりません。そこで、相手の駒(K2側の駒)を評価するときは盤面を180度回転させて(Invマクロ)、この回転させたK1,K2をK1',K2'と書くとしたらK2'K1'Pを調べて、このスコアを引き算してやる必要があります。

それで、このときにK1K2とK2'K1'だと対称に見えにくいのでK1'K2'の順番で書きたいのですが、そのためには、K1'としてInv(K2)を代入しておこうというそういうトリックです。

そのあと、それぞれの駒のKKPの値を加算していきます。

    score += kkp[sq_bk0][sq_wk0][ kkp_pawn + sq ];

こういう感じですね。

ところがこうして計算したscoreは全く出鱈目で、このままですと大変弱くなります。

おかしいなーと思って、いろいろ検証してみたのですが、KPPのほうの値も拾ってくる必要があります。具体的に言いますとKPPをKP1P2と書くとして、P2 = 手駒のときのKPPの値も考慮する必要があります。

おそらく棋譜からの学習のときに、そっちにも値が散らばって学習されてしまっているのでしょう。KP1P2でP2が手駒無しのときはこの値が0になるように正規化(?)したほうがKKPの値だけ取り出すときに都合が良いのですが..

ともかくKP1P2でP2が手駒なしのときの値が0になっていないので、この分をKKPテーブルに対してオフセットをしてやる必要があると私は考えました。

そこで以下のようにfv.binの読み込み後にKKPテーブルを修正するようにしました。こうしますとひよこカルロ将棋neo1.12に対して勝率9割以上で勝ち越すようになりました(修正前はほぼ互角か負け越し)ので、そこそこ正しいであろうことがわかります。

しかし初代Bonanzaには追いついていないので、やはりこれでも正しくKKPテーブルを抽出出来ていないのではないかと思います。

このことに関して、もし何かお気づきの点がありましたら、コメント欄にて教えてください。

void Eval::setup_bona6_kkp()
{

  // KKPのPを評価するときに手駒0に対するPになっていないと評価値がおかしいのではなかろうかという疑問

  BonaPiece list0[52], list1[52];
  BoardPosition sq_bk, sq_wk;
  Score sum = 0;
  Score score = 0;

  // tree_macroを使うためのトリック
  Tree tree0;
  Tree* tree = &tree0;
  HAND_B = 0;
  HAND_W = 0;

  list0[ 0] = BonaEval::f_hand_pawn   + Hands::Pawn(HAND_B);
  list0[ 1] = BonaEval::e_hand_pawn   + Hands::Pawn(HAND_W);
  list0[ 2] = BonaEval::f_hand_lance  + Hands::Lance(HAND_B);
  list0[ 3] = BonaEval::e_hand_lance  + Hands::Lance(HAND_W);
  list0[ 4] = BonaEval::f_hand_knight + Hands::Knight(HAND_B);
  list0[ 5] = BonaEval::e_hand_knight + Hands::Knight(HAND_W);
  list0[ 6] = BonaEval::f_hand_silver + Hands::Silver(HAND_B);
  list0[ 7] = BonaEval::e_hand_silver + Hands::Silver(HAND_W);
  list0[ 8] = BonaEval::f_hand_gold   + Hands::Gold(HAND_B);
  list0[ 9] = BonaEval::e_hand_gold   + Hands::Gold(HAND_W);
  list0[10] = BonaEval::f_hand_bishop + Hands::Bishop(HAND_B);
  list0[11] = BonaEval::e_hand_bishop + Hands::Bishop(HAND_W);
  list0[12] = BonaEval::f_hand_rook   + Hands::Rook(HAND_B);
  list0[13] = BonaEval::e_hand_rook   + Hands::Rook(HAND_W);

  list1[ 0] = BonaEval::f_hand_pawn   + Hands::Pawn(HAND_W);
  list1[ 1] = BonaEval::e_hand_pawn   + Hands::Pawn(HAND_B);
  list1[ 2] = BonaEval::f_hand_lance  + Hands::Lance(HAND_W);
  list1[ 3] = BonaEval::e_hand_lance  + Hands::Lance(HAND_B);
  list1[ 4] = BonaEval::f_hand_knight + Hands::Knight(HAND_W);
  list1[ 5] = BonaEval::e_hand_knight + Hands::Knight(HAND_B);
  list1[ 6] = BonaEval::f_hand_silver + Hands::Silver(HAND_W);
  list1[ 7] = BonaEval::e_hand_silver + Hands::Silver(HAND_B);
  list1[ 8] = BonaEval::f_hand_gold   + Hands::Gold(HAND_W);
  list1[ 9] = BonaEval::e_hand_gold   + Hands::Gold(HAND_B);
  list1[10] = BonaEval::f_hand_bishop + Hands::Bishop(HAND_W);
  list1[11] = BonaEval::e_hand_bishop + Hands::Bishop(HAND_B);
  list1[12] = BonaEval::f_hand_rook   + Hands::Rook(HAND_W);
  list1[13] = BonaEval::e_hand_rook   + Hands::Rook(HAND_B);


  for(sq_bk = 0;sq_bk < nsquare ; ++sq_bk)
  {
    for(sq_wk = 0;sq_wk < nsquare ; ++sq_wk)
    {
      for(BoardPosition sq = 0; sq < nsquare; ++sq)
      {
        for(int i=0;i<14;++i)
        {
          // sq > list0[i] , sq > list1[i]
          if (sq >= 9)
          {
            BonaEval::kkp[sq_bk][sq_wk][ BonaEval::kkp_pawn + sq ] += PcPcOnSq( sq_bk , BonaEval::f_pawn + sq , list0[i] );
            BonaEval::kkp[sq_bk][sq_wk][ BonaEval::kkp_pawn + sq ] -= PcPcOnSq( BoardPositions::Inv(sq_wk) , BonaEval::e_pawn + BoardPositions::Inv(sq) , list1[i] );

            BonaEval::kkp[sq_bk][sq_wk][ BonaEval::kkp_lance + sq ] += PcPcOnSq( sq_bk , BonaEval::f_lance + sq , list0[i] );
            BonaEval::kkp[sq_bk][sq_wk][ BonaEval::kkp_lance + sq ] -= PcPcOnSq( BoardPositions::Inv(sq_wk) , BonaEval::e_lance + BoardPositions::Inv(sq) , list1[i] );
          }
          if (sq >= 18)
          {
            BonaEval::kkp[sq_bk][sq_wk][ BonaEval::kkp_knight + sq ] += PcPcOnSq( sq_bk , BonaEval::f_knight + sq , list0[i] );
            BonaEval::kkp[sq_bk][sq_wk][ BonaEval::kkp_knight + sq ] -= PcPcOnSq( BoardPositions::Inv(sq_wk) , BonaEval::e_knight + BoardPositions::Inv(sq) , list1[i] );
          }

          BonaEval::kkp[sq_bk][sq_wk][ BonaEval::kkp_silver + sq ] += PcPcOnSq( sq_bk , BonaEval::f_silver + sq , list0[i] );
          BonaEval::kkp[sq_bk][sq_wk][ BonaEval::kkp_silver + sq ] -= PcPcOnSq( BoardPositions::Inv(sq_wk) , BonaEval::e_silver + BoardPositions::Inv(sq) , list1[i] );

          BonaEval::kkp[sq_bk][sq_wk][ BonaEval::kkp_gold + sq ] += PcPcOnSq( sq_bk , BonaEval::f_gold + sq , list0[i] );
          BonaEval::kkp[sq_bk][sq_wk][ BonaEval::kkp_gold + sq ] -= PcPcOnSq( BoardPositions::Inv(sq_wk) , BonaEval::e_gold + BoardPositions::Inv(sq) , list1[i] );

          BonaEval::kkp[sq_bk][sq_wk][ BonaEval::kkp_bishop + sq ] += PcPcOnSq( sq_bk , BonaEval::f_bishop + sq , list0[i] );
          BonaEval::kkp[sq_bk][sq_wk][ BonaEval::kkp_bishop + sq ] -= PcPcOnSq( BoardPositions::Inv(sq_wk) , BonaEval::e_bishop + BoardPositions::Inv(sq) , list1[i] );

          BonaEval::kkp[sq_bk][sq_wk][ BonaEval::kkp_horse + sq ] += PcPcOnSq( sq_bk , BonaEval::f_horse + sq , list0[i] );
          BonaEval::kkp[sq_bk][sq_wk][ BonaEval::kkp_horse + sq ] -= PcPcOnSq( BoardPositions::Inv(sq_wk) , BonaEval::e_horse + BoardPositions::Inv(sq) , list1[i] );

          BonaEval::kkp[sq_bk][sq_wk][ BonaEval::kkp_rook + sq ] += PcPcOnSq( sq_bk , BonaEval::f_rook + sq , list0[i] );
          BonaEval::kkp[sq_bk][sq_wk][ BonaEval::kkp_rook + sq ] -= PcPcOnSq( BoardPositions::Inv(sq_wk) , BonaEval::e_rook + BoardPositions::Inv(sq) , list1[i] );

          BonaEval::kkp[sq_bk][sq_wk][ BonaEval::kkp_dragon + sq ] += PcPcOnSq( sq_bk , BonaEval::f_dragon + sq , list0[i] );
          BonaEval::kkp[sq_bk][sq_wk][ BonaEval::kkp_dragon + sq ] -= PcPcOnSq( BoardPositions::Inv(sq_wk) , BonaEval::e_dragon + BoardPositions::Inv(sq) , list1[i] );
        }
      }
    }
  }
}