Skip to content

Commit

Permalink
HalfKPE4_256x2-32-32
Browse files Browse the repository at this point in the history
  • Loading branch information
tttak committed Jul 21, 2024
1 parent 8906f25 commit 101e633
Show file tree
Hide file tree
Showing 6 changed files with 263 additions and 3 deletions.
1 change: 1 addition & 0 deletions source/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -503,6 +503,7 @@ ifneq (,$(findstring YANEURAOU_ENGINE_NNUE,$(YANEURAOU_EDITION)))
eval/nnue/features/pe9.cpp \
eval/nnue/features/king_safety_distinguishgolds.cpp \
eval/nnue/features/kk.cpp \
eval/nnue/features/half_kpe4.cpp \
engine/yaneuraou-engine/yaneuraou-search.cpp

ifneq (,$(findstring em++,$(COMPILER)))
Expand Down
35 changes: 35 additions & 0 deletions source/eval/nnue/architectures/halfkpe4_256x2-32-32.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
// NNUE評価関数で用いる入力特徴量とネットワーク構造の定義

#include "../features/feature_set.h"
#include "../features/half_kpe4.h"

#include "../layers/input_slice.h"
#include "../layers/affine_transform.h"
#include "../layers/clipped_relu.h"

namespace Eval {

namespace NNUE {

// 評価関数で用いる入力特徴量
using RawFeatures = Features::FeatureSet<
Features::HalfKPE4<Features::Side::kFriend>>;

// 変換後の入力特徴量の次元数
constexpr IndexType kTransformedFeatureDimensions = 256;

namespace Layers {

// ネットワーク構造の定義
using InputLayer = InputSlice<kTransformedFeatureDimensions * 2>;
using HiddenLayer1 = ClippedReLU<AffineTransform<InputLayer, 32>>;
using HiddenLayer2 = ClippedReLU<AffineTransform<HiddenLayer1, 32>>;
using OutputLayer = AffineTransform<HiddenLayer2, 1>;

} // namespace Layers

using Network = Layers::OutputLayer;

} // namespace NNUE

} // namespace Eval
154 changes: 154 additions & 0 deletions source/eval/nnue/features/half_kpe4.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,154 @@
// NNUE評価関数の入力特徴量HalfKPE4の定義

#include "../../../config.h"

#if defined(EVAL_NNUE) && defined(LONG_EFFECT_LIBRARY) && defined(USE_BOARD_EFFECT_PREV)

#include "half_kpe4.h"
#include "index_list.h"

namespace Eval {

namespace NNUE {

namespace Features {

inline Square GetSquareFromBonaPiece(BonaPiece p) {
if (p < fe_hand_end) {
return SQ_NB;
}
else {
return static_cast<Square>((p - fe_hand_end) % SQ_NB);
}
}

inline int GetEffectCount(const Position& pos, Square sq_p, Color perspective_org, Color perspective, bool prev_effect) {
if (sq_p == SQ_NB) {
return 0;
}
else {
if (perspective_org == WHITE) {
sq_p = Inv(sq_p);
}

if (prev_effect) {
return std::min(int(pos.board_effect_prev[perspective].effect(sq_p)), 1);
}
else {
return std::min(int(pos.board_effect[perspective].effect(sq_p)), 1);
}
}
}

inline bool IsDirty(const Eval::DirtyPiece& dp, PieceNumber pn) {
for (int i = 0; i < dp.dirty_num; ++i) {
if (pn == dp.pieceNo[i]) {
return true;
}
}
return false;
}

// 玉の位置とBonaPieceと利き数から特徴量のインデックスを求める
template <Side AssociatedKing>
inline IndexType HalfKPE4<AssociatedKing>::MakeIndex(Square sq_k, BonaPiece p, int effect1, int effect2) {
return (static_cast<IndexType>(fe_end) * static_cast<IndexType>(sq_k) + p)
+ (static_cast<IndexType>(fe_end) * static_cast<IndexType>(SQ_NB) * (effect1 * 2 + effect2));
}

// 駒の情報を取得する
template <Side AssociatedKing>
inline void HalfKPE4<AssociatedKing>::GetPieces(
const Position& pos, Color perspective,
BonaPiece** pieces, Square* sq_target_k) {
*pieces = (perspective == BLACK) ?
pos.eval_list()->piece_list_fb() :
pos.eval_list()->piece_list_fw();
const PieceNumber target = (AssociatedKing == Side::kFriend) ?
static_cast<PieceNumber>(PIECE_NUMBER_KING + perspective) :
static_cast<PieceNumber>(PIECE_NUMBER_KING + ~perspective);
*sq_target_k = static_cast<Square>(((*pieces)[target] - f_king) % SQ_NB);
}

// 特徴量のうち、値が1であるインデックスのリストを取得する
template <Side AssociatedKing>
void HalfKPE4<AssociatedKing>::AppendActiveIndices(
const Position& pos, Color perspective, IndexList* active) {
// コンパイラの警告を回避するため、配列サイズが小さい場合は何もしない
if (RawFeatures::kMaxActiveDimensions < kMaxActiveDimensions) return;

BonaPiece* pieces;
Square sq_target_k;
GetPieces(pos, perspective, &pieces, &sq_target_k);
auto& board_effect = pos.board_effect;

for (PieceNumber i = PIECE_NUMBER_ZERO; i < PIECE_NUMBER_KING; ++i) {
BonaPiece p = pieces[i];
Square sq_p = GetSquareFromBonaPiece(p);

active->push_back(MakeIndex(sq_target_k, p
, GetEffectCount(pos, sq_p, perspective, perspective, false)
, GetEffectCount(pos, sq_p, perspective, ~perspective, false)
));
}
}

// 特徴量のうち、一手前から値が変化したインデックスのリストを取得する
template <Side AssociatedKing>
void HalfKPE4<AssociatedKing>::AppendChangedIndices(
const Position& pos, Color perspective,
IndexList* removed, IndexList* added) {
BonaPiece* pieces;
Square sq_target_k;
GetPieces(pos, perspective, &pieces, &sq_target_k);
const auto& dp = pos.state()->dirtyPiece;

for (int i = 0; i < dp.dirty_num; ++i) {
if (dp.pieceNo[i] >= PIECE_NUMBER_KING) continue;

const auto old_p = static_cast<BonaPiece>(dp.changed_piece[i].old_piece.from[perspective]);
Square old_sq_p = GetSquareFromBonaPiece(old_p);
removed->push_back(MakeIndex(sq_target_k, old_p
, GetEffectCount(pos, old_sq_p, perspective, perspective, true)
, GetEffectCount(pos, old_sq_p, perspective, ~perspective, true)
));

const auto new_p = static_cast<BonaPiece>(dp.changed_piece[i].new_piece.from[perspective]);
Square new_sq_p = GetSquareFromBonaPiece(new_p);
added->push_back(MakeIndex(sq_target_k, new_p
, GetEffectCount(pos, new_sq_p, perspective, perspective, false)
, GetEffectCount(pos, new_sq_p, perspective, ~perspective, false)
));
}

for (PieceNumber i = PIECE_NUMBER_ZERO; i < PIECE_NUMBER_KING; ++i) {
if (IsDirty(dp, i)) {
continue;
}

BonaPiece p = pieces[i];
Square sq_p = GetSquareFromBonaPiece(p);

int effectCount_prev_1 = GetEffectCount(pos, sq_p, perspective, perspective, true);
int effectCount_prev_2 = GetEffectCount(pos, sq_p, perspective, ~perspective, true);
int effectCount_now_1 = GetEffectCount(pos, sq_p, perspective, perspective, false);
int effectCount_now_2 = GetEffectCount(pos, sq_p, perspective, ~perspective, false);

if ( effectCount_prev_1 != effectCount_now_1
|| effectCount_prev_2 != effectCount_now_2) {
removed->push_back(MakeIndex(sq_target_k, p, effectCount_prev_1, effectCount_prev_2));
added->push_back(MakeIndex(sq_target_k, p, effectCount_now_1, effectCount_now_2));
}
}
}

template class HalfKPE4<Side::kFriend>;
template class HalfKPE4<Side::kEnemy>;

} // namespace Features

} // namespace NNUE

} // namespace Eval

#endif // defined(EVAL_NNUE)
66 changes: 66 additions & 0 deletions source/eval/nnue/features/half_kpe4.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
// NNUE評価関数の入力特徴量HalfKPE4の定義

#ifndef _NNUE_FEATURES_HALF_KPE4_H_
#define _NNUE_FEATURES_HALF_KPE4_H_

#include "../../../config.h"

#if defined(EVAL_NNUE)

#include "../../../evaluate.h"
#include "features_common.h"

namespace Eval {

namespace NNUE {

namespace Features {

// 特徴量HalfKPE4:自玉または敵玉の位置と、玉以外の駒の位置と、利き数の組み合わせ
// ・利き数は先後各々最大1までに制限。0~1で2通り。先後で2*2=4通り。なお、持ち駒の場合は利き数0とする。
template <Side AssociatedKing>
class HalfKPE4 {
public:
// 特徴量名
static constexpr const char* kName =
(AssociatedKing == Side::kFriend) ? "HalfKPE4(Friend)" : "HalfKPE4(Enemy)";
// 評価関数ファイルに埋め込むハッシュ値
static constexpr std::uint32_t kHashValue =
0x5D69D5B9u ^ (AssociatedKing == Side::kFriend);
// 特徴量の次元数
static constexpr IndexType kDimensions =
static_cast<IndexType>(SQ_NB) * static_cast<IndexType>(fe_end) * 2 * 2;
// 特徴量のうち、同時に値が1となるインデックスの数の最大値
static constexpr IndexType kMaxActiveDimensions = PIECE_NUMBER_KING;

// 差分計算の代わりに全計算を行うタイミング
static constexpr TriggerEvent kRefreshTrigger =
(AssociatedKing == Side::kFriend) ?
TriggerEvent::kFriendKingMoved : TriggerEvent::kEnemyKingMoved;

// 特徴量のうち、値が1であるインデックスのリストを取得する
static void AppendActiveIndices(const Position& pos, Color perspective,
IndexList* active);

// 特徴量のうち、一手前から値が変化したインデックスのリストを取得する
static void AppendChangedIndices(const Position& pos, Color perspective,
IndexList* removed, IndexList* added);

// 玉の位置とBonaPieceと利き数から特徴量のインデックスを求める
static IndexType MakeIndex(Square sq_k, BonaPiece p, int effect1, int effect2);

private:
// 駒の情報を取得する
static void GetPieces(const Position& pos, Color perspective,
BonaPiece** pieces, Square* sq_target_k);
};

} // namespace Features

} // namespace NNUE

} // namespace Eval

#endif // defined(EVAL_NNUE)

#endif
7 changes: 5 additions & 2 deletions source/eval/nnue/nnue_architecture.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,12 +29,15 @@

#elif defined(EVAL_NNUE_HALFKPE9)

// halfkpe9型
// Halfkpe9型
//#include "architectures/halfkpe9_256x2-32-32.h"

// HalfKP-KSDG型
//#include "architectures/halfkp-kingsafety_distinguishgolds_256x2-32-32.h"
#include "architectures/halfkp-kingsafety_distinguishgolds_512x2-8-96.h"
//#include "architectures/halfkp-kingsafety_distinguishgolds_512x2-8-96.h"

// HalfKPE4型
#include "architectures/halfkpe4_256x2-32-32.h"

#elif defined(YANEURAOU_ENGINE_NNUE_HALFKP_512X2_16_32)

Expand Down
3 changes: 2 additions & 1 deletion source/misc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -193,7 +193,8 @@ const string engine_info() {

// << EVAL_TYPE_NAME << ' '
// << "NNUE HalfKP-KSDG_512x2-8-96" << ' '
<< "NNUE HalfKP-KK_512x2-8-96" << ' '
// << "NNUE HalfKP-KK_512x2-8-96" << ' '
<< "NNUE HalfKPE4_256x2-32-32" << ' '

<< ENGINE_VERSION << std::setfill('0')
<< (Is64Bit ? " 64" : " 32")
Expand Down

0 comments on commit 101e633

Please sign in to comment.