対称

小宮日記 なぜBona4はdv==0のときに特徴を更新するのか?
恐らく、強さはほとんど変わらないだろうと予想。確認していないので断定はできないけれど。
それではどうして調べたのかというと、単に原因が気になったからというのが一つの理由。
もう一つは、Bonanzaのコード全体を読んで受けた印象が理由。
Bonanzaというのは、プログラムが強ければ良いというだけではなく、真理を探求するという要素も持っている感じがする。評価関数の部分だけを見てもわかるが、将棋固有のヒューリスティックが極力少なくなるように書かれている。その理由には、作者の将棋の棋力が低いということもあるだろうが、それだけとは思えない。


これも強さには大して影響がないかもしれないが、前から気になっていたことを思い出した。
学習で得られた更新量を実際のパラメタに反映する前に、盤の左右反転に対するパラメタの対称性を考慮して、param_sym()という関数を実行している。
この関数は、位置(k0l,il,jl)と、それを反転した位置(k0r,ir,jr)の値を、両者の和の値に置き換える。それは良いのだが、全ての位置が反転しても同じ位置の組み合わせだった場合(k0l==k0r, il==ir, jl==jr、三つの駒が全て五筋にいる、または持駒状態の位置)に、何もしないのは間違いではないだろうか?
通常のケースでは平均ではなく和にしているのだから、k0l==k0r, il==ir, jl==jrの場合には値を二倍に更新しないと過小評価することになってしまう。

param_sym( param_t *p )
{
  int q, r, il, ir, ir0, jl, jr, k0l, k0r, k1l, k1r;

  for ( k0l = 0; k0l < nsquare; k0l++ ) {
    q = k0l / nfile;
    r = k0l % nfile;
    k0r = q*nfile + nfile-1-r;
    if ( k0l > k0r ) { continue; }

    for ( il = 0; il < fe_end; il++ ) {
      if ( il < fe_hand_end ) { ir0 = il; }
      else {
	q = ( il- fe_hand_end ) / nfile;
	r = ( il- fe_hand_end ) % nfile;
	ir0 = q*nfile + nfile-1-r + fe_hand_end;
      }

      for ( jl = 0; jl <= il; jl++ ) {
	if ( jl < fe_hand_end )
	  {
	    ir = ir0;
	    jr = jl;
	  }
	else {
	  q = ( jl - fe_hand_end ) / nfile;
	  r = ( jl - fe_hand_end ) % nfile;
	  jr = q*nfile + nfile-1-r + fe_hand_end;
	  if ( jr > ir0 )
	    {
	      ir = jr;
	      jr = ir0;
	    }
	  else { ir = ir0; }
	}
	if ( k0l == k0r && il*(il+1)/2+jl >= ir*(ir+1)/2+jr ) { continue; }

	p->PcPcOnSq(k0l,il,jl)
	  = p->PcPcOnSq(k0r,ir,jr)
	  = p->PcPcOnSq(k0l,il,jl) + p->PcPcOnSq(k0r,ir,jr);
      }
    }
  }
  以下略