Moved the nnue folder.

This commit is contained in:
nodchip
2020-08-07 22:34:53 +09:00
parent c0e1235fef
commit 1c23465383
44 changed files with 0 additions and 0 deletions
+73
View File
@@ -0,0 +1,73 @@
//Definition of input feature quantity K of NNUE evaluation function
#if defined(EVAL_NNUE)
#include "castling_right.h"
#include "index_list.h"
namespace Eval {
namespace NNUE {
namespace Features {
// Get a list of indices with a value of 1 among the features
void CastlingRight::AppendActiveIndices(
const Position& pos, Color perspective, IndexList* active) {
// do nothing if array size is small to avoid compiler warning
if (RawFeatures::kMaxActiveDimensions < kMaxActiveDimensions) return;
int castling_rights = pos.state()->castlingRights;
int relative_castling_rights;
if (perspective == WHITE) {
relative_castling_rights = castling_rights;
}
else {
// Invert the perspective.
relative_castling_rights = ((castling_rights & 3) << 2)
& ((castling_rights >> 2) & 3);
}
for (int i = 0; i <kDimensions; ++i) {
if (relative_castling_rights & (i << 1)) {
active->push_back(i);
}
}
}
// Get a list of indices whose values have changed from the previous one in the feature quantity
void CastlingRight::AppendChangedIndices(
const Position& pos, Color perspective,
IndexList* removed, IndexList* added) {
int previous_castling_rights = pos.state()->previous->castlingRights;
int current_castling_rights = pos.state()->castlingRights;
int relative_previous_castling_rights;
int relative_current_castling_rights;
if (perspective == WHITE) {
relative_previous_castling_rights = previous_castling_rights;
relative_current_castling_rights = current_castling_rights;
}
else {
// Invert the perspective.
relative_previous_castling_rights = ((previous_castling_rights & 3) << 2)
& ((previous_castling_rights >> 2) & 3);
relative_current_castling_rights = ((current_castling_rights & 3) << 2)
& ((current_castling_rights >> 2) & 3);
}
for (int i = 0; i < kDimensions; ++i) {
if ((relative_previous_castling_rights & (i << 1)) &&
(relative_current_castling_rights & (i << 1)) == 0) {
removed->push_back(i);
}
}
}
} // namespace Features
} // namespace NNUE
} // namespace Eval
#endif // defined(EVAL_NNUE)
+48
View File
@@ -0,0 +1,48 @@
//Definition of input feature quantity K of NNUE evaluation function
#ifndef _NNUE_FEATURES_CASTLING_RIGHT_H_
#define _NNUE_FEATURES_CASTLING_RIGHT_H_
#if defined(EVAL_NNUE)
#include "../../../evaluate.h"
#include "features_common.h"
namespace Eval {
namespace NNUE {
namespace Features {
// Feature K: Ball position
class CastlingRight {
public:
// feature quantity name
static constexpr const char* kName = "CastlingRight";
// Hash value embedded in the evaluation function file
static constexpr std::uint32_t kHashValue = 0x913968AAu;
// number of feature dimensions
static constexpr IndexType kDimensions = 4;
// The maximum value of the number of indexes whose value is 1 at the same time among the feature values
static constexpr IndexType kMaxActiveDimensions = 4;
// Timing of full calculation instead of difference calculation
static constexpr TriggerEvent kRefreshTrigger = TriggerEvent::kNone;
// Get a list of indices with a value of 1 among the features
static void AppendActiveIndices(const Position& pos, Color perspective,
IndexList* active);
// Get a list of indices whose values ??have changed from the previous one in the feature quantity
static void AppendChangedIndices(const Position& pos, Color perspective,
IndexList* removed, IndexList* added);
};
} // namespace Features
} // namespace NNUE
} // namespace Eval
#endif // defined(EVAL_NNUE)
#endif
+47
View File
@@ -0,0 +1,47 @@
//Definition of input feature quantity K of NNUE evaluation function
#if defined(EVAL_NNUE)
#include "enpassant.h"
#include "index_list.h"
namespace Eval {
namespace NNUE {
namespace Features {
// Get a list of indices with a value of 1 among the features
void EnPassant::AppendActiveIndices(
const Position& pos, Color perspective, IndexList* active) {
// do nothing if array size is small to avoid compiler warning
if (RawFeatures::kMaxActiveDimensions < kMaxActiveDimensions) return;
auto epSquare = pos.state()->epSquare;
if (epSquare == SQ_NONE) {
return;
}
if (perspective == BLACK) {
epSquare = Inv(epSquare);
}
auto file = file_of(epSquare);
active->push_back(file);
}
// Get a list of indices whose values ??have changed from the previous one in the feature quantity
void EnPassant::AppendChangedIndices(
const Position& pos, Color perspective,
IndexList* removed, IndexList* added) {
// Not implemented.
assert(false);
}
} // namespace Features
} // namespace NNUE
} // namespace Eval
#endif // defined(EVAL_NNUE)
+48
View File
@@ -0,0 +1,48 @@
//Definition of input feature quantity K of NNUE evaluation function
#ifndef _NNUE_FEATURES_ENPASSANT_H_
#define _NNUE_FEATURES_ENPASSANT_H_
#if defined(EVAL_NNUE)
#include "../../../evaluate.h"
#include "features_common.h"
namespace Eval {
namespace NNUE {
namespace Features {
// Feature K: Ball position
class EnPassant {
public:
// feature quantity name
static constexpr const char* kName = "EnPassant";
// Hash value embedded in the evaluation function file
static constexpr std::uint32_t kHashValue = 0x02924F91u;
// number of feature dimensions
static constexpr IndexType kDimensions = 8;
// The maximum value of the number of indexes whose value is 1 at the same time among the feature values
static constexpr IndexType kMaxActiveDimensions = 1;
// Timing of full calculation instead of difference calculation
static constexpr TriggerEvent kRefreshTrigger = TriggerEvent::kAnyPieceMoved;
// Get a list of indices with a value of 1 among the features
static void AppendActiveIndices(const Position& pos, Color perspective,
IndexList* active);
// Get a list of indices whose values ??have changed from the previous one in the feature quantity
static void AppendChangedIndices(const Position& pos, Color perspective,
IndexList* removed, IndexList* added);
};
} // namespace Features
} // namespace NNUE
} // namespace Eval
#endif // defined(EVAL_NNUE)
#endif
+249
View File
@@ -0,0 +1,249 @@
// A class template that represents the input feature set of the NNUE evaluation function
#ifndef _NNUE_FEATURE_SET_H_
#define _NNUE_FEATURE_SET_H_
#if defined(EVAL_NNUE)
#include "features_common.h"
#include <array>
namespace Eval {
namespace NNUE {
namespace Features {
// A class template that represents a list of values
template <typename T, T... Values>
struct CompileTimeList;
template <typename T, T First, T... Remaining>
struct CompileTimeList<T, First, Remaining...> {
static constexpr bool Contains(T value) {
return value == First || CompileTimeList<T, Remaining...>::Contains(value);
}
static constexpr std::array<T, sizeof...(Remaining) + 1>
kValues = {{First, Remaining...}};
};
template <typename T, T First, T... Remaining>
constexpr std::array<T, sizeof...(Remaining) + 1>
CompileTimeList<T, First, Remaining...>::kValues;
template <typename T>
struct CompileTimeList<T> {
static constexpr bool Contains(T /*value*/) {
return false;
}
static constexpr std::array<T, 0> kValues = {{}};
};
// Class template that adds to the beginning of the list
template <typename T, typename ListType, T Value>
struct AppendToList;
template <typename T, T... Values, T AnotherValue>
struct AppendToList<T, CompileTimeList<T, Values...>, AnotherValue> {
using Result = CompileTimeList<T, AnotherValue, Values...>;
};
// Class template for adding to a sorted, unique list
template <typename T, typename ListType, T Value>
struct InsertToSet;
template <typename T, T First, T... Remaining, T AnotherValue>
struct InsertToSet<T, CompileTimeList<T, First, Remaining...>, AnotherValue> {
using Result = std::conditional_t<
CompileTimeList<T, First, Remaining...>::Contains(AnotherValue),
CompileTimeList<T, First, Remaining...>,
std::conditional_t<(AnotherValue <First),
CompileTimeList<T, AnotherValue, First, Remaining...>,
typename AppendToList<T, typename InsertToSet<
T, CompileTimeList<T, Remaining...>, AnotherValue>::Result,
First>::Result>>;
};
template <typename T, T Value>
struct InsertToSet<T, CompileTimeList<T>, Value> {
using Result = CompileTimeList<T, Value>;
};
// Base class of feature set
template <typename Derived>
class FeatureSetBase {
public:
// Get a list of indices with a value of 1 among the features
template <typename IndexListType>
static void AppendActiveIndices(
const Position& pos, TriggerEvent trigger, IndexListType active[2]) {
for (const auto perspective :Colors) {
Derived::CollectActiveIndices(
pos, trigger, perspective, &active[perspective]);
}
}
// Get a list of indices whose values have changed from the previous one in the feature quantity
template <typename PositionType, typename IndexListType>
static void AppendChangedIndices(
const PositionType& pos, TriggerEvent trigger,
IndexListType removed[2], IndexListType added[2], bool reset[2]) {
const auto& dp = pos.state()->dirtyPiece;
if (dp.dirty_num == 0) return;
for (const auto perspective :Colors) {
reset[perspective] = false;
switch (trigger) {
case TriggerEvent::kNone:
break;
case TriggerEvent::kFriendKingMoved:
reset[perspective] =
dp.pieceNo[0] == PIECE_NUMBER_KING + perspective;
break;
case TriggerEvent::kEnemyKingMoved:
reset[perspective] =
dp.pieceNo[0] == PIECE_NUMBER_KING + ~perspective;
break;
case TriggerEvent::kAnyKingMoved:
reset[perspective] = dp.pieceNo[0] >= PIECE_NUMBER_KING;
break;
case TriggerEvent::kAnyPieceMoved:
reset[perspective] = true;
break;
default:
assert(false);
break;
}
if (reset[perspective]) {
Derived::CollectActiveIndices(
pos, trigger, perspective, &added[perspective]);
} else {
Derived::CollectChangedIndices(
pos, trigger, perspective,
&removed[perspective], &added[perspective]);
}
}
}
};
// Class template that represents the feature set
// do internal processing in reverse order of template arguments in order to linearize the amount of calculation at runtime
template <typename FirstFeatureType, typename... RemainingFeatureTypes>
class FeatureSet<FirstFeatureType, RemainingFeatureTypes...> :
public FeatureSetBase<
FeatureSet<FirstFeatureType, RemainingFeatureTypes...>> {
private:
using Head = FirstFeatureType;
using Tail = FeatureSet<RemainingFeatureTypes...>;
public:
// Hash value embedded in the evaluation function file
static constexpr std::uint32_t kHashValue =
Head::kHashValue ^ (Tail::kHashValue << 1) ^ (Tail::kHashValue >> 31);
// number of feature dimensions
static constexpr IndexType kDimensions =
Head::kDimensions + Tail::kDimensions;
// The maximum value of the number of indexes whose value is 1 at the same time among the feature values
static constexpr IndexType kMaxActiveDimensions =
Head::kMaxActiveDimensions + Tail::kMaxActiveDimensions;
// List of timings to perform all calculations instead of difference calculation
using SortedTriggerSet = typename InsertToSet<TriggerEvent,
typename Tail::SortedTriggerSet, Head::kRefreshTrigger>::Result;
static constexpr auto kRefreshTriggers = SortedTriggerSet::kValues;
// Get the feature quantity name
static std::string GetName() {
return std::string(Head::kName) + "+" + Tail::GetName();
}
private:
// Get a list of indices with a value of 1 among the features
template <typename IndexListType>
static void CollectActiveIndices(
const Position& pos, const TriggerEvent trigger, const Color perspective,
IndexListType* const active) {
Tail::CollectActiveIndices(pos, trigger, perspective, active);
if (Head::kRefreshTrigger == trigger) {
const auto start = active->size();
Head::AppendActiveIndices(pos, perspective, active);
for (auto i = start; i < active->size(); ++i) {
(*active)[i] += Tail::kDimensions;
}
}
}
// Get a list of indices whose values have changed from the previous one in the feature quantity
template <typename IndexListType>
static void CollectChangedIndices(
const Position& pos, const TriggerEvent trigger, const Color perspective,
IndexListType* const removed, IndexListType* const added) {
Tail::CollectChangedIndices(pos, trigger, perspective, removed, added);
if (Head::kRefreshTrigger == trigger) {
const auto start_removed = removed->size();
const auto start_added = added->size();
Head::AppendChangedIndices(pos, perspective, removed, added);
for (auto i = start_removed; i < removed->size(); ++i) {
(*removed)[i] += Tail::kDimensions;
}
for (auto i = start_added; i < added->size(); ++i) {
(*added)[i] += Tail::kDimensions;
}
}
}
// Make the base class and the class template that recursively uses itself a friend
friend class FeatureSetBase<FeatureSet>;
template <typename... FeatureTypes>
friend class FeatureSet;
};
// Class template that represents the feature set
// Specialization with one template argument
template <typename FeatureType>
class FeatureSet<FeatureType> : public FeatureSetBase<FeatureSet<FeatureType>> {
public:
// Hash value embedded in the evaluation function file
static constexpr std::uint32_t kHashValue = FeatureType::kHashValue;
// number of feature dimensions
static constexpr IndexType kDimensions = FeatureType::kDimensions;
// The maximum value of the number of indexes whose value is 1 at the same time among the feature values
static constexpr IndexType kMaxActiveDimensions =
FeatureType::kMaxActiveDimensions;
// List of timings to perform all calculations instead of difference calculation
using SortedTriggerSet =
CompileTimeList<TriggerEvent, FeatureType::kRefreshTrigger>;
static constexpr auto kRefreshTriggers = SortedTriggerSet::kValues;
// Get the feature quantity name
static std::string GetName() {
return FeatureType::kName;
}
private:
// Get a list of indices with a value of 1 among the features
static void CollectActiveIndices(
const Position& pos, const TriggerEvent trigger, const Color perspective,
IndexList* const active) {
if (FeatureType::kRefreshTrigger == trigger) {
FeatureType::AppendActiveIndices(pos, perspective, active);
}
}
// Get a list of indices whose values have changed from the previous one in the feature quantity
static void CollectChangedIndices(
const Position& pos, const TriggerEvent trigger, const Color perspective,
IndexList* const removed, IndexList* const added) {
if (FeatureType::kRefreshTrigger == trigger) {
FeatureType::AppendChangedIndices(pos, perspective, removed, added);
}
}
// Make the base class and the class template that recursively uses itself a friend
friend class FeatureSetBase<FeatureSet>;
template <typename... FeatureTypes>
friend class FeatureSet;
};
} // namespace Features
} // namespace NNUE
} // namespace Eval
#endif // defined(EVAL_NNUE)
#endif
+47
View File
@@ -0,0 +1,47 @@
//Common header of input features of NNUE evaluation function
#ifndef _NNUE_FEATURES_COMMON_H_
#define _NNUE_FEATURES_COMMON_H_
#if defined(EVAL_NNUE)
#include "../../../evaluate.h"
#include "../nnue_common.h"
namespace Eval {
namespace NNUE {
namespace Features {
// Index list type
class IndexList;
// Class template that represents the feature set
template <typename... FeatureTypes>
class FeatureSet;
// Type of timing to perform all calculations instead of difference calculation
enum class TriggerEvent {
kNone, // Calculate the difference whenever possible
kFriendKingMoved, // calculate all when own ball moves
kEnemyKingMoved, // do all calculations when enemy balls move
kAnyKingMoved, // do all calculations if either ball moves
kAnyPieceMoved, // always do all calculations
};
// turn side or other side
enum class Side {
kFriend, // turn side
kEnemy, // opponent
};
} // namespace Features
} // namespace NNUE
} // namespace Eval
#endif // defined(EVAL_NNUE)
#endif
+84
View File
@@ -0,0 +1,84 @@
//Definition of input features HalfKP of NNUE evaluation function
#if defined(EVAL_NNUE)
#include "half_kp.h"
#include "index_list.h"
namespace Eval {
namespace NNUE {
namespace Features {
// Find the index of the feature quantity from the ball position and BonaPiece
template <Side AssociatedKing>
inline IndexType HalfKP<AssociatedKing>::MakeIndex(Square sq_k, BonaPiece p) {
return static_cast<IndexType>(fe_end) * static_cast<IndexType>(sq_k) + p;
}
// Get the piece information
template <Side AssociatedKing>
inline void HalfKP<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) % SQUARE_NB);
}
// Get a list of indices with a value of 1 among the features
template <Side AssociatedKing>
void HalfKP<AssociatedKing>::AppendActiveIndices(
const Position& pos, Color perspective, IndexList* active) {
// do nothing if array size is small to avoid compiler warning
if (RawFeatures::kMaxActiveDimensions < kMaxActiveDimensions) return;
BonaPiece* pieces;
Square sq_target_k;
GetPieces(pos, perspective, &pieces, &sq_target_k);
for (PieceNumber i = PIECE_NUMBER_ZERO; i < PIECE_NUMBER_KING; ++i) {
if (pieces[i] != Eval::BONA_PIECE_ZERO) {
active->push_back(MakeIndex(sq_target_k, pieces[i]));
}
}
}
// Get a list of indices whose values have changed from the previous one in the feature quantity
template <Side AssociatedKing>
void HalfKP<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]);
if (old_p != Eval::BONA_PIECE_ZERO) {
removed->push_back(MakeIndex(sq_target_k, old_p));
}
const auto new_p = static_cast<BonaPiece>(
dp.changed_piece[i].new_piece.from[perspective]);
if (new_p != Eval::BONA_PIECE_ZERO) {
added->push_back(MakeIndex(sq_target_k, new_p));
}
}
}
template class HalfKP<Side::kFriend>;
template class HalfKP<Side::kEnemy>;
} // namespace Features
} // namespace NNUE
} // namespace Eval
#endif // defined(EVAL_NNUE)
+62
View File
@@ -0,0 +1,62 @@
//Definition of input features HalfKP of NNUE evaluation function
#ifndef _NNUE_FEATURES_HALF_KP_H_
#define _NNUE_FEATURES_HALF_KP_H_
#if defined(EVAL_NNUE)
#include "../../../evaluate.h"
#include "features_common.h"
namespace Eval {
namespace NNUE {
namespace Features {
// Feature HalfKP: Combination of the position of own ball or enemy ball and the position of pieces other than balls
template <Side AssociatedKing>
class HalfKP {
public:
// feature quantity name
static constexpr const char* kName =
(AssociatedKing == Side::kFriend) ? "HalfKP(Friend)" : "HalfKP(Enemy)";
// Hash value embedded in the evaluation function file
static constexpr std::uint32_t kHashValue =
0x5D69D5B9u ^ (AssociatedKing == Side::kFriend);
// number of feature dimensions
static constexpr IndexType kDimensions =
static_cast<IndexType>(SQUARE_NB) * static_cast<IndexType>(fe_end);
// The maximum value of the number of indexes whose value is 1 at the same time among the feature values
static constexpr IndexType kMaxActiveDimensions = PIECE_NUMBER_KING;
// Timing of full calculation instead of difference calculation
static constexpr TriggerEvent kRefreshTrigger =
(AssociatedKing == Side::kFriend) ?
TriggerEvent::kFriendKingMoved : TriggerEvent::kEnemyKingMoved;
// Get a list of indices with a value of 1 among the features
static void AppendActiveIndices(const Position& pos, Color perspective,
IndexList* active);
// Get a list of indices whose values have changed from the previous one in the feature quantity
static void AppendChangedIndices(const Position& pos, Color perspective,
IndexList* removed, IndexList* added);
// Find the index of the feature quantity from the ball position and BonaPiece
static IndexType MakeIndex(Square sq_k, BonaPiece p);
private:
// Get the piece information
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
+97
View File
@@ -0,0 +1,97 @@
//Definition of input features HalfRelativeKP of NNUE evaluation function
#if defined(EVAL_NNUE)
#include "half_relative_kp.h"
#include "index_list.h"
namespace Eval {
namespace NNUE {
namespace Features {
// Find the index of the feature quantity from the ball position and BonaPiece
template <Side AssociatedKing>
inline IndexType HalfRelativeKP<AssociatedKing>::MakeIndex(
Square sq_k, BonaPiece p) {
constexpr IndexType W = kBoardWidth;
constexpr IndexType H = kBoardHeight;
const IndexType piece_index = (p - fe_hand_end) / SQUARE_NB;
const Square sq_p = static_cast<Square>((p - fe_hand_end) % SQUARE_NB);
const IndexType relative_file = file_of(sq_p) - file_of(sq_k) + (W / 2);
const IndexType relative_rank = rank_of(sq_p) - rank_of(sq_k) + (H / 2);
return H * W * piece_index + H * relative_file + relative_rank;
}
// Get the piece information
template <Side AssociatedKing>
inline void HalfRelativeKP<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) % SQUARE_NB);
}
// Get a list of indices with a value of 1 among the features
template <Side AssociatedKing>
void HalfRelativeKP<AssociatedKing>::AppendActiveIndices(
const Position& pos, Color perspective, IndexList* active) {
// do nothing if array size is small to avoid compiler warning
if (RawFeatures::kMaxActiveDimensions < kMaxActiveDimensions) return;
BonaPiece* pieces;
Square sq_target_k;
GetPieces(pos, perspective, &pieces, &sq_target_k);
for (PieceNumber i = PIECE_NUMBER_ZERO; i < PIECE_NUMBER_KING; ++i) {
if (pieces[i] >= fe_hand_end) {
if (pieces[i] != Eval::BONA_PIECE_ZERO) {
active->push_back(MakeIndex(sq_target_k, pieces[i]));
}
}
}
}
// Get a list of indices whose values have changed from the previous one in the feature quantity
template <Side AssociatedKing>
void HalfRelativeKP<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]);
if (old_p >= fe_hand_end) {
if (old_p != Eval::BONA_PIECE_ZERO) {
removed->push_back(MakeIndex(sq_target_k, old_p));
}
}
const auto new_p = static_cast<BonaPiece>(
dp.changed_piece[i].new_piece.from[perspective]);
if (new_p >= fe_hand_end) {
if (new_p != Eval::BONA_PIECE_ZERO) {
added->push_back(MakeIndex(sq_target_k, new_p));
}
}
}
}
template class HalfRelativeKP<Side::kFriend>;
template class HalfRelativeKP<Side::kEnemy>;
} // namespace Features
} // namespace NNUE
} // namespace Eval
#endif // defined(EVAL_NNUE)
+68
View File
@@ -0,0 +1,68 @@
//Definition of input features HalfRelativeKP of NNUE evaluation function
#ifndef _NNUE_FEATURES_HALF_RELATIVE_KP_H_
#define _NNUE_FEATURES_HALF_RELATIVE_KP_H_
#if defined(EVAL_NNUE)
#include "../../../evaluate.h"
#include "features_common.h"
namespace Eval {
namespace NNUE {
namespace Features {
// Feature HalfRelativeKP: Relative position of each piece other than the ball based on own ball or enemy ball
template <Side AssociatedKing>
class HalfRelativeKP {
public:
// feature quantity name
static constexpr const char* kName = (AssociatedKing == Side::kFriend) ?
"HalfRelativeKP(Friend)" : "HalfRelativeKP(Enemy)";
// Hash value embedded in the evaluation function file
static constexpr std::uint32_t kHashValue =
0xF9180919u ^ (AssociatedKing == Side::kFriend);
// Piece type excluding balls
static constexpr IndexType kNumPieceKinds = (fe_end - fe_hand_end) / SQUARE_NB;
// width of the virtual board with the ball in the center
static constexpr IndexType kBoardWidth = FILE_NB * 2 - 1;
// height of a virtual board with balls in the center
static constexpr IndexType kBoardHeight = RANK_NB * 2 - 1;
// number of feature dimensions
static constexpr IndexType kDimensions =
kNumPieceKinds * kBoardHeight * kBoardWidth;
// The maximum value of the number of indexes whose value is 1 at the same time among the feature values
static constexpr IndexType kMaxActiveDimensions = PIECE_NUMBER_KING;
// Timing of full calculation instead of difference calculation
static constexpr TriggerEvent kRefreshTrigger =
(AssociatedKing == Side::kFriend) ?
TriggerEvent::kFriendKingMoved : TriggerEvent::kEnemyKingMoved;
// Get a list of indices with a value of 1 among the features
static void AppendActiveIndices(const Position& pos, Color perspective,
IndexList* active);
// Get a list of indices whose values have changed from the previous one in the feature quantity
static void AppendChangedIndices(const Position& pos, Color perspective,
IndexList* removed, IndexList* added);
// Find the index of the feature quantity from the ball position and BonaPiece
static IndexType MakeIndex(Square sq_k, BonaPiece p);
private:
// Get the piece information
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
+55
View File
@@ -0,0 +1,55 @@
// Definition of index list of input features
#ifndef _NNUE_FEATURES_INDEX_LIST_H_
#define _NNUE_FEATURES_INDEX_LIST_H_
#if defined(EVAL_NNUE)
#include "../../../position.h"
#include "../nnue_architecture.h"
namespace Eval {
namespace NNUE {
namespace Features {
// Class template used for feature index list
template <typename T, std::size_t MaxSize>
class ValueList {
public:
std::size_t size() const { return size_; }
void resize(std::size_t size) { size_ = size; }
void push_back(const T& value) { values_[size_++] = value; }
T& operator[](std::size_t index) { return values_[index]; }
T* begin() { return values_; }
T* end() { return values_ + size_; }
const T& operator[](std::size_t index) const { return values_[index]; }
const T* begin() const { return values_; }
const T* end() const { return values_ + size_; }
void swap(ValueList& other) {
const std::size_t max_size = std::max(size_, other.size_);
for (std::size_t i = 0; i < max_size; ++i) {
std::swap(values_[i], other.values_[i]);
}
std::swap(size_, other.size_);
}
private:
T values_[MaxSize];
std::size_t size_ = 0;
};
//Type of feature index list
class IndexList
: public ValueList<IndexType, RawFeatures::kMaxActiveDimensions> {
};
} // namespace Features
} // namespace NNUE
} // namespace Eval
#endif // defined(EVAL_NNUE)
#endif
+49
View File
@@ -0,0 +1,49 @@
//Definition of input feature quantity K of NNUE evaluation function
#if defined(EVAL_NNUE)
#include "k.h"
#include "index_list.h"
namespace Eval {
namespace NNUE {
namespace Features {
// Get a list of indices with a value of 1 among the features
void K::AppendActiveIndices(
const Position& pos, Color perspective, IndexList* active) {
// do nothing if array size is small to avoid compiler warning
if (RawFeatures::kMaxActiveDimensions < kMaxActiveDimensions) return;
const BonaPiece* pieces = (perspective == BLACK) ?
pos.eval_list()->piece_list_fb() :
pos.eval_list()->piece_list_fw();
assert(pieces[PIECE_NUMBER_BKING] != BONA_PIECE_ZERO);
assert(pieces[PIECE_NUMBER_WKING] != BONA_PIECE_ZERO);
for (PieceNumber i = PIECE_NUMBER_KING; i < PIECE_NUMBER_NB; ++i) {
active->push_back(pieces[i] - fe_end);
}
}
// Get a list of indices whose values have changed from the previous one in the feature quantity
void K::AppendChangedIndices(
const Position& pos, Color perspective,
IndexList* removed, IndexList* added) {
const auto& dp = pos.state()->dirtyPiece;
if (dp.pieceNo[0] >= PIECE_NUMBER_KING) {
removed->push_back(
dp.changed_piece[0].old_piece.from[perspective] - fe_end);
added->push_back(
dp.changed_piece[0].new_piece.from[perspective] - fe_end);
}
}
} // namespace Features
} // namespace NNUE
} // namespace Eval
#endif // defined(EVAL_NNUE)
+48
View File
@@ -0,0 +1,48 @@
//Definition of input feature quantity K of NNUE evaluation function
#ifndef _NNUE_FEATURES_K_H_
#define _NNUE_FEATURES_K_H_
#if defined(EVAL_NNUE)
#include "../../../evaluate.h"
#include "features_common.h"
namespace Eval {
namespace NNUE {
namespace Features {
// Feature K: Ball position
class K {
public:
// feature quantity name
static constexpr const char* kName = "K";
// Hash value embedded in the evaluation function file
static constexpr std::uint32_t kHashValue = 0xD3CEE169u;
// number of feature dimensions
static constexpr IndexType kDimensions = SQUARE_NB * 2;
// The maximum value of the number of indexes whose value is 1 at the same time among the feature values
static constexpr IndexType kMaxActiveDimensions = 2;
// Timing of full calculation instead of difference calculation
static constexpr TriggerEvent kRefreshTrigger = TriggerEvent::kNone;
// Get a list of indices with a value of 1 among the features
static void AppendActiveIndices(const Position& pos, Color perspective,
IndexList* active);
// Get a list of indices whose values have changed from the previous one in the feature quantity
static void AppendChangedIndices(const Position& pos, Color perspective,
IndexList* removed, IndexList* added);
};
} // namespace Features
} // namespace NNUE
} // namespace Eval
#endif // defined(EVAL_NNUE)
#endif
+52
View File
@@ -0,0 +1,52 @@
//Definition of input feature P of NNUE evaluation function
#if defined(EVAL_NNUE)
#include "p.h"
#include "index_list.h"
namespace Eval {
namespace NNUE {
namespace Features {
// Get a list of indices with a value of 1 among the features
void P::AppendActiveIndices(
const Position& pos, Color perspective, IndexList* active) {
// do nothing if array size is small to avoid compiler warning
if (RawFeatures::kMaxActiveDimensions < kMaxActiveDimensions) return;
const BonaPiece* pieces = (perspective == BLACK) ?
pos.eval_list()->piece_list_fb() :
pos.eval_list()->piece_list_fw();
for (PieceNumber i = PIECE_NUMBER_ZERO; i < PIECE_NUMBER_KING; ++i) {
if (pieces[i] != Eval::BONA_PIECE_ZERO) {
active->push_back(pieces[i]);
}
}
}
// Get a list of indices whose values have changed from the previous one in the feature quantity
void P::AppendChangedIndices(
const Position& pos, Color perspective,
IndexList* removed, IndexList* added) {
const auto& dp = pos.state()->dirtyPiece;
for (int i = 0; i < dp.dirty_num; ++i) {
if (dp.pieceNo[i] >= PIECE_NUMBER_KING) continue;
if (dp.changed_piece[i].old_piece.from[perspective] != Eval::BONA_PIECE_ZERO) {
removed->push_back(dp.changed_piece[i].old_piece.from[perspective]);
}
if (dp.changed_piece[i].new_piece.from[perspective] != Eval::BONA_PIECE_ZERO) {
added->push_back(dp.changed_piece[i].new_piece.from[perspective]);
}
}
}
} // namespace Features
} // namespace NNUE
} // namespace Eval
#endif // defined(EVAL_NNUE)
+48
View File
@@ -0,0 +1,48 @@
//Definition of input feature P of NNUE evaluation function
#ifndef _NNUE_FEATURES_P_H_
#define _NNUE_FEATURES_P_H_
#if defined(EVAL_NNUE)
#include "../../../evaluate.h"
#include "features_common.h"
namespace Eval {
namespace NNUE {
namespace Features {
// Feature P: BonaPiece of pieces other than balls
class P {
public:
// feature quantity name
static constexpr const char* kName = "P";
// Hash value embedded in the evaluation function file
static constexpr std::uint32_t kHashValue = 0x764CFB4Bu;
// number of feature dimensions
static constexpr IndexType kDimensions = fe_end;
// The maximum value of the number of indexes whose value is 1 at the same time among the feature values
static constexpr IndexType kMaxActiveDimensions = PIECE_NUMBER_KING;
// Timing of full calculation instead of difference calculation
static constexpr TriggerEvent kRefreshTrigger = TriggerEvent::kNone;
// Get a list of indices with a value of 1 among the features
static void AppendActiveIndices(const Position& pos, Color perspective,
IndexList* active);
// Get a list of indices whose values have changed from the previous one in the feature quantity
static void AppendChangedIndices(const Position& pos, Color perspective,
IndexList* removed, IndexList* added);
};
} // namespace Features
} // namespace NNUE
} // namespace Eval
#endif // defined(EVAL_NNUE)
#endif