mirror of
https://github.com/HChaZZY/Stockfish.git
synced 2025-12-24 19:16:49 +08:00
Add a HalfKA architecture (a product of K - king, and A - any piece) along with all required infrastructure. HalfKA doesn't discriminate kings compared to HalfKP. Keep old architecture as the default one.
This commit is contained in:
@@ -50,9 +50,12 @@ SRCS = benchmark.cpp bitbase.cpp bitboard.cpp endgame.cpp evaluate.cpp main.cpp
|
||||
nnue/evaluate_nnue.cpp \
|
||||
nnue/evaluate_nnue_learner.cpp \
|
||||
nnue/features/half_kp.cpp \
|
||||
nnue/features/half_ka.cpp \
|
||||
nnue/features/half_relative_kp.cpp \
|
||||
nnue/features/half_relative_ka.cpp \
|
||||
nnue/features/k.cpp \
|
||||
nnue/features/p.cpp \
|
||||
nnue/features/a.cpp \
|
||||
nnue/features/castling_right.cpp \
|
||||
nnue/features/enpassant.cpp \
|
||||
nnue/nnue_test_command.cpp \
|
||||
|
||||
54
src/nnue/architectures/halfka_256x2-32-32.h
Normal file
54
src/nnue/architectures/halfka_256x2-32-32.h
Normal file
@@ -0,0 +1,54 @@
|
||||
/*
|
||||
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
|
||||
Copyright (C) 2004-2020 The Stockfish developers (see AUTHORS file)
|
||||
|
||||
Stockfish is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Stockfish is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
// Definition of input features and network structure used in NNUE evaluation function
|
||||
|
||||
#ifndef NNUE_HALFKA_256X2_32_32_H_INCLUDED
|
||||
#define NNUE_HALFKA_256X2_32_32_H_INCLUDED
|
||||
|
||||
#include "nnue/features/feature_set.h"
|
||||
#include "nnue/features/half_ka.h"
|
||||
|
||||
#include "nnue/layers/input_slice.h"
|
||||
#include "nnue/layers/affine_transform.h"
|
||||
#include "nnue/layers/clipped_relu.h"
|
||||
|
||||
namespace Eval::NNUE {
|
||||
|
||||
// Input features used in evaluation function
|
||||
using RawFeatures = Features::FeatureSet<
|
||||
Features::HalfKA<Features::Side::kFriend>>;
|
||||
|
||||
// Number of input feature dimensions after conversion
|
||||
constexpr IndexType kTransformedFeatureDimensions = 256;
|
||||
|
||||
namespace Layers {
|
||||
|
||||
// Define network structure
|
||||
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 Eval::NNUE
|
||||
|
||||
#endif // #ifndef NNUE_HALFA_256X2_32_32_H_INCLUDED
|
||||
@@ -7,6 +7,7 @@
|
||||
|
||||
#include "trainer/features/factorizer_feature_set.h"
|
||||
#include "trainer/features/factorizer_half_kp.h"
|
||||
#include "trainer/features/factorizer_half_ka.h"
|
||||
#include "trainer/trainer_feature_transformer.h"
|
||||
#include "trainer/trainer_input_slice.h"
|
||||
#include "trainer/trainer_affine_transform.h"
|
||||
|
||||
50
src/nnue/features/a.cpp
Normal file
50
src/nnue/features/a.cpp
Normal file
@@ -0,0 +1,50 @@
|
||||
#include "a.h"
|
||||
#include "index_list.h"
|
||||
|
||||
// Definition of input feature A of NNUE evaluation function
|
||||
namespace Eval::NNUE::Features {
|
||||
|
||||
// Orient a square according to perspective (flip rank for black)
|
||||
inline Square orient(Color perspective, Square s) {
|
||||
return Square(int(s) ^ (bool(perspective) * SQ_A8));
|
||||
}
|
||||
|
||||
// Find the index of the feature quantity from the king position and PieceSquare
|
||||
inline IndexType A::make_index(
|
||||
Color perspective, Square s, Piece pc) {
|
||||
return IndexType(orient(perspective, s) + kpp_board_index[pc][perspective]);
|
||||
}
|
||||
|
||||
// Get a list of indices with a value of 1 among the features
|
||||
void A::append_active_indices(
|
||||
const Position& pos,
|
||||
Color perspective,
|
||||
IndexList* active) {
|
||||
|
||||
Bitboard bb = pos.pieces();
|
||||
while (bb) {
|
||||
Square s = pop_lsb(&bb);
|
||||
active->push_back(make_index(perspective, s, pos.piece_on(s)));
|
||||
}
|
||||
}
|
||||
|
||||
// Get a list of indices whose values have changed from the previous one in the feature quantity
|
||||
void A::append_changed_indices(
|
||||
const Position& pos,
|
||||
Color perspective,
|
||||
IndexList* removed,
|
||||
IndexList* added) {
|
||||
|
||||
const auto& dp = pos.state()->dirtyPiece;
|
||||
for (int i = 0; i < dp.dirty_num; ++i) {
|
||||
Piece pc = dp.piece[i];
|
||||
|
||||
if (dp.from[i] != SQ_NONE)
|
||||
removed->push_back(make_index(perspective, dp.from[i], pc));
|
||||
|
||||
if (dp.to[i] != SQ_NONE)
|
||||
added->push_back(make_index(perspective, dp.to[i], pc));
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace Eval::NNUE::Features
|
||||
54
src/nnue/features/a.h
Normal file
54
src/nnue/features/a.h
Normal file
@@ -0,0 +1,54 @@
|
||||
#ifndef _NNUE_FEATURES_A_H_
|
||||
#define _NNUE_FEATURES_A_H_
|
||||
|
||||
#include "features_common.h"
|
||||
|
||||
#include "evaluate.h"
|
||||
|
||||
// Definition of input feature A of NNUE evaluation function
|
||||
// A is a union of P features and K features, so technically the
|
||||
// same effect can be achieved by including both P and K features
|
||||
// but it would result in slower index appending because
|
||||
// P would conditionally exclude K features and vice versa,
|
||||
// where A doesn't have any conditionals.
|
||||
namespace Eval::NNUE::Features {
|
||||
|
||||
// Feature P: PieceSquare of pieces other than balls
|
||||
class A {
|
||||
public:
|
||||
// feature quantity name
|
||||
static constexpr const char* kName = "A";
|
||||
|
||||
// Hash value embedded in the evaluation function file
|
||||
static constexpr std::uint32_t kHashValue = 0x7A4C414Cu;
|
||||
|
||||
// number of feature dimensions
|
||||
static constexpr IndexType kDimensions = PS_END2;
|
||||
|
||||
// The maximum value of the number of indexes whose value is 1 at the same time among the feature values
|
||||
static constexpr IndexType kMaxActiveDimensions = 32;
|
||||
|
||||
// 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 append_active_indices(
|
||||
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 append_changed_indices(
|
||||
const Position& pos,
|
||||
Color perspective,
|
||||
IndexList* removed,
|
||||
IndexList* added);
|
||||
|
||||
private:
|
||||
// Index of a feature for a given piece on some square
|
||||
static IndexType make_index(Color perspective, Square s, Piece pc);
|
||||
};
|
||||
|
||||
} // namespace Eval::NNUE::Features
|
||||
|
||||
#endif // #ifndef _NNUE_FEATURES_UNION_P_K_H_
|
||||
89
src/nnue/features/half_ka.cpp
Normal file
89
src/nnue/features/half_ka.cpp
Normal file
@@ -0,0 +1,89 @@
|
||||
/*
|
||||
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
|
||||
Copyright (C) 2004-2020 The Stockfish developers (see AUTHORS file)
|
||||
|
||||
Stockfish is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Stockfish is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
//Definition of input features HalfKA of NNUE evaluation function
|
||||
|
||||
#include "half_ka.h"
|
||||
#include "index_list.h"
|
||||
|
||||
namespace Eval::NNUE::Features {
|
||||
|
||||
// Orient a square according to perspective (flip rank for black)
|
||||
inline Square orient(Color perspective, Square s) {
|
||||
return Square(int(s) ^ (bool(perspective) * SQ_A8));
|
||||
}
|
||||
|
||||
// Find the index of the feature quantity from the king position and PieceSquare
|
||||
template <Side AssociatedKing>
|
||||
inline IndexType HalfKA<AssociatedKing>::make_index(
|
||||
Color perspective,
|
||||
Square s,
|
||||
Piece pc,
|
||||
Square ksq) {
|
||||
|
||||
return IndexType(orient(perspective, s) + kpp_board_index[pc][perspective] + PS_END2 * ksq);
|
||||
}
|
||||
|
||||
// Get a list of indices for active features
|
||||
template <Side AssociatedKing>
|
||||
void HalfKA<AssociatedKing>::append_active_indices(
|
||||
const Position& pos,
|
||||
Color perspective,
|
||||
IndexList* active) {
|
||||
|
||||
Square ksq = orient(
|
||||
perspective,
|
||||
pos.square<KING>(
|
||||
AssociatedKing == Side::kFriend ? perspective : ~perspective));
|
||||
|
||||
Bitboard bb = pos.pieces();
|
||||
while (bb) {
|
||||
Square s = pop_lsb(&bb);
|
||||
active->push_back(make_index(perspective, s, pos.piece_on(s), ksq));
|
||||
}
|
||||
}
|
||||
|
||||
// Get a list of indices for recently changed features
|
||||
template <Side AssociatedKing>
|
||||
void HalfKA<AssociatedKing>::append_changed_indices(
|
||||
const Position& pos,
|
||||
Color perspective,
|
||||
IndexList* removed,
|
||||
IndexList* added) {
|
||||
|
||||
Square ksq = orient(
|
||||
perspective,
|
||||
pos.square<KING>(
|
||||
AssociatedKing == Side::kFriend ? perspective : ~perspective));
|
||||
|
||||
const auto& dp = pos.state()->dirtyPiece;
|
||||
for (int i = 0; i < dp.dirty_num; ++i) {
|
||||
Piece pc = dp.piece[i];
|
||||
|
||||
if (dp.from[i] != SQ_NONE)
|
||||
removed->push_back(make_index(perspective, dp.from[i], pc, ksq));
|
||||
|
||||
if (dp.to[i] != SQ_NONE)
|
||||
added->push_back(make_index(perspective, dp.to[i], pc, ksq));
|
||||
}
|
||||
}
|
||||
|
||||
template class HalfKA<Side::kFriend>;
|
||||
template class HalfKA<Side::kEnemy>;
|
||||
|
||||
} // namespace Eval::NNUE::Features
|
||||
75
src/nnue/features/half_ka.h
Normal file
75
src/nnue/features/half_ka.h
Normal file
@@ -0,0 +1,75 @@
|
||||
/*
|
||||
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
|
||||
Copyright (C) 2004-2020 The Stockfish developers (see AUTHORS file)
|
||||
|
||||
Stockfish is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Stockfish is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef NNUE_FEATURES_HALF_KA_H_INCLUDED
|
||||
#define NNUE_FEATURES_HALF_KA_H_INCLUDED
|
||||
|
||||
#include "features_common.h"
|
||||
|
||||
#include "evaluate.h"
|
||||
|
||||
//Definition of input features HalfKPK of NNUE evaluation function
|
||||
namespace Eval::NNUE::Features {
|
||||
|
||||
// Feature HalfKPK: Combination of the position of own king
|
||||
// and the position of pieces other than kings
|
||||
template <Side AssociatedKing>
|
||||
class HalfKA {
|
||||
|
||||
public:
|
||||
// Feature name
|
||||
static constexpr const char* kName = (AssociatedKing == Side::kFriend) ?
|
||||
"HalfKA(Friend)" : "HalfKA(Enemy)";
|
||||
|
||||
// Hash value embedded in the evaluation file
|
||||
static constexpr std::uint32_t kHashValue =
|
||||
0x5F134CB9u ^ (AssociatedKing == Side::kFriend);
|
||||
|
||||
// Number of feature dimensions
|
||||
static constexpr IndexType kDimensions =
|
||||
static_cast<IndexType>(SQUARE_NB) * static_cast<IndexType>(PS_END2);
|
||||
|
||||
// Maximum number of simultaneously active features
|
||||
static constexpr IndexType kMaxActiveDimensions = 32;
|
||||
|
||||
// Trigger for full calculation instead of difference calculation
|
||||
static constexpr TriggerEvent kRefreshTrigger =
|
||||
(AssociatedKing == Side::kFriend) ?
|
||||
TriggerEvent::kFriendKingMoved : TriggerEvent::kEnemyKingMoved;
|
||||
|
||||
// Get a list of indices for active features
|
||||
static void append_active_indices(
|
||||
const Position& pos,
|
||||
Color perspective,
|
||||
IndexList* active);
|
||||
|
||||
// Get a list of indices for recently changed features
|
||||
static void append_changed_indices(
|
||||
const Position& pos,
|
||||
Color perspective,
|
||||
IndexList* removed,
|
||||
IndexList* added);
|
||||
|
||||
private:
|
||||
// Index of a feature for a given king position and another piece on some square
|
||||
static IndexType make_index(Color perspective, Square s, Piece pc, Square sq_k);
|
||||
};
|
||||
|
||||
} // namespace Eval::NNUE::Features
|
||||
|
||||
#endif // #ifndef NNUE_FEATURES_HALF_KA_H_INCLUDED
|
||||
86
src/nnue/features/half_relative_ka.cpp
Normal file
86
src/nnue/features/half_relative_ka.cpp
Normal file
@@ -0,0 +1,86 @@
|
||||
#include "half_relative_ka.h"
|
||||
#include "index_list.h"
|
||||
|
||||
//Definition of input features HalfRelativeKA of NNUE evaluation function
|
||||
namespace Eval::NNUE::Features {
|
||||
|
||||
// Orient a square according to perspective (flip rank for black)
|
||||
inline Square orient(Color perspective, Square s) {
|
||||
return Square(int(s) ^ (bool(perspective) * SQ_A8));
|
||||
}
|
||||
|
||||
// Find the index of the feature quantity from the ball position and PieceSquare
|
||||
template <Side AssociatedKing>
|
||||
inline IndexType HalfRelativeKA<AssociatedKing>::make_index(
|
||||
Color perspective,
|
||||
Square s,
|
||||
Piece pc,
|
||||
Square sq_k) {
|
||||
|
||||
const IndexType p = IndexType(orient(perspective, s) + kpp_board_index[pc][perspective]);
|
||||
return make_index(sq_k, p);
|
||||
}
|
||||
|
||||
// Find the index of the feature quantity from the ball position and PieceSquare
|
||||
template <Side AssociatedKing>
|
||||
inline IndexType HalfRelativeKA<AssociatedKing>::make_index(
|
||||
Square sq_k,
|
||||
IndexType p) {
|
||||
|
||||
constexpr IndexType W = kBoardWidth;
|
||||
constexpr IndexType H = kBoardHeight;
|
||||
const IndexType piece_index = (p - PS_W_PAWN) / SQUARE_NB;
|
||||
const Square sq_p = static_cast<Square>((p - PS_W_PAWN) % 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 a list of indices with a value of 1 among the features
|
||||
template <Side AssociatedKing>
|
||||
void HalfRelativeKA<AssociatedKing>::append_active_indices(
|
||||
const Position& pos,
|
||||
Color perspective,
|
||||
IndexList* active) {
|
||||
|
||||
Square ksq = orient(
|
||||
perspective,
|
||||
pos.square<KING>(
|
||||
AssociatedKing == Side::kFriend ? perspective : ~perspective));
|
||||
|
||||
Bitboard bb = pos.pieces();
|
||||
while (bb) {
|
||||
Square s = pop_lsb(&bb);
|
||||
active->push_back(make_index(perspective, s, pos.piece_on(s), ksq));
|
||||
}
|
||||
}
|
||||
|
||||
// Get a list of indices whose values have changed from the previous one in the feature quantity
|
||||
template <Side AssociatedKing>
|
||||
void HalfRelativeKA<AssociatedKing>::append_changed_indices(
|
||||
const Position& pos,
|
||||
Color perspective,
|
||||
IndexList* removed,
|
||||
IndexList* added) {
|
||||
|
||||
Square ksq = orient(
|
||||
perspective,
|
||||
pos.square<KING>(
|
||||
AssociatedKing == Side::kFriend ? perspective : ~perspective));
|
||||
|
||||
const auto& dp = pos.state()->dirtyPiece;
|
||||
for (int i = 0; i < dp.dirty_num; ++i) {
|
||||
Piece pc = dp.piece[i];
|
||||
|
||||
if (dp.from[i] != SQ_NONE)
|
||||
removed->push_back(make_index(perspective, dp.from[i], pc, ksq));
|
||||
|
||||
if (dp.to[i] != SQ_NONE)
|
||||
added->push_back(make_index(perspective, dp.to[i], pc, ksq));
|
||||
}
|
||||
}
|
||||
|
||||
template class HalfRelativeKA<Side::kFriend>;
|
||||
template class HalfRelativeKA<Side::kEnemy>;
|
||||
|
||||
} // namespace Eval::NNUE::Features
|
||||
68
src/nnue/features/half_relative_ka.h
Normal file
68
src/nnue/features/half_relative_ka.h
Normal file
@@ -0,0 +1,68 @@
|
||||
#ifndef _NNUE_FEATURES_HALF_RELATIVE_KA_H_
|
||||
#define _NNUE_FEATURES_HALF_RELATIVE_KA_H_
|
||||
|
||||
#include "features_common.h"
|
||||
|
||||
#include "evaluate.h"
|
||||
|
||||
// Definition of input features HalfRelativeKA of NNUE evaluation function
|
||||
// K - King
|
||||
// A - Any piece
|
||||
// KA - product of K and A
|
||||
namespace Eval::NNUE::Features {
|
||||
|
||||
// Feature HalfRelativeKA: Relative position of each piece other than the ball based on own ball or enemy ball
|
||||
template <Side AssociatedKing>
|
||||
class HalfRelativeKA {
|
||||
public:
|
||||
// feature quantity name
|
||||
static constexpr const char* kName = (AssociatedKing == Side::kFriend) ?
|
||||
"HalfRelativeKA(Friend)" : "HalfRelativeKA(Enemy)";
|
||||
|
||||
// Hash value embedded in the evaluation function file
|
||||
static constexpr std::uint32_t kHashValue =
|
||||
0xA123051Fu ^ (AssociatedKing == Side::kFriend);
|
||||
|
||||
static constexpr IndexType kNumPieceKinds = 6 * 2;
|
||||
|
||||
// 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 = 32;
|
||||
|
||||
// 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 append_active_indices(
|
||||
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 append_changed_indices(
|
||||
const Position& pos,
|
||||
Color perspective,
|
||||
IndexList* removed,
|
||||
IndexList* added);
|
||||
|
||||
// Find the index of the feature quantity from the ball position and PieceSquare
|
||||
static IndexType make_index(Square s, IndexType p);
|
||||
|
||||
// Find the index of the feature quantity from the ball position and PieceSquare
|
||||
static IndexType make_index(Color perspective, Square s, Piece pc, Square sq_k);
|
||||
};
|
||||
|
||||
} // namespace Eval::NNUE::Features
|
||||
|
||||
#endif // #ifndef _NNUE_FEATURES_HALF_RELATIVE_KA_H_
|
||||
93
src/nnue/trainer/features/factorizer_half_ka.h
Normal file
93
src/nnue/trainer/features/factorizer_half_ka.h
Normal file
@@ -0,0 +1,93 @@
|
||||
#ifndef _NNUE_TRAINER_FEATURES_FACTORIZER_HALF_KA_H_
|
||||
#define _NNUE_TRAINER_FEATURES_FACTORIZER_HALF_KA_H_
|
||||
|
||||
#include "factorizer.h"
|
||||
|
||||
#include "nnue/features/half_ka.h"
|
||||
#include "nnue/features/a.h"
|
||||
#include "nnue/features/half_relative_ka.h"
|
||||
|
||||
// Specialization of NNUE evaluation function feature conversion class template for HalfKA
|
||||
namespace Eval::NNUE::Features {
|
||||
|
||||
// Class template that converts input features into learning features
|
||||
// Specialization for HalfKA
|
||||
template <Side AssociatedKing>
|
||||
class Factorizer<HalfKA<AssociatedKing>> {
|
||||
private:
|
||||
using FeatureType = HalfKA<AssociatedKing>;
|
||||
|
||||
// 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;
|
||||
|
||||
// Type of learning feature
|
||||
enum TrainingFeatureType {
|
||||
kFeaturesHalfKA,
|
||||
kFeaturesA,
|
||||
kFeaturesHalfRelativeKA,
|
||||
kNumTrainingFeatureTypes,
|
||||
};
|
||||
|
||||
// Learning feature information
|
||||
static constexpr FeatureProperties kProperties[] = {
|
||||
// kFeaturesHalfKPK
|
||||
{true, FeatureType::kDimensions},
|
||||
// kFeaturesPK
|
||||
{true, Factorizer<A>::get_dimensions()},
|
||||
// kFeaturesHalfRelativeKPK
|
||||
{true, Factorizer<HalfRelativeKA<AssociatedKing>>::get_dimensions()},
|
||||
};
|
||||
|
||||
static_assert(get_array_length(kProperties) == kNumTrainingFeatureTypes, "");
|
||||
|
||||
public:
|
||||
static constexpr std::string get_name() {
|
||||
return std::string("Factorizer<") + FeatureType::kName + ">";
|
||||
}
|
||||
|
||||
static constexpr std::string get_factorizers_string() {
|
||||
return " - " + get_name();
|
||||
}
|
||||
|
||||
// Get the dimensionality of the learning feature
|
||||
static constexpr IndexType get_dimensions() {
|
||||
return get_active_dimensions(kProperties);
|
||||
}
|
||||
|
||||
// Get index of learning feature and scale of learning rate
|
||||
static void append_training_features(
|
||||
IndexType base_index, std::vector<TrainingFeature>* training_features) {
|
||||
|
||||
// kFeaturesHalfKPK
|
||||
IndexType index_offset = append_base_feature<FeatureType>(
|
||||
kProperties[kFeaturesHalfKA], base_index, training_features);
|
||||
|
||||
const auto sq_k = static_cast<Square>(base_index / PS_END2);
|
||||
const auto a = static_cast<IndexType>(base_index % PS_END2);
|
||||
|
||||
// kFeaturesPK
|
||||
index_offset += inherit_features_if_required<A>(
|
||||
index_offset, kProperties[kFeaturesA], a, training_features);
|
||||
|
||||
// kFeaturesHalfRelativeKPK
|
||||
if (a >= PS_W_PAWN) {
|
||||
index_offset += inherit_features_if_required<HalfRelativeKA<AssociatedKing>>(
|
||||
index_offset, kProperties[kFeaturesHalfRelativeKA],
|
||||
HalfRelativeKA<AssociatedKing>::make_index(sq_k, a),
|
||||
training_features);
|
||||
}
|
||||
else {
|
||||
index_offset += skip_features(kProperties[kFeaturesHalfRelativeKA]);
|
||||
}
|
||||
|
||||
assert(index_offset == get_dimensions());
|
||||
}
|
||||
};
|
||||
|
||||
template <Side AssociatedKing>
|
||||
constexpr FeatureProperties Factorizer<HalfKA<AssociatedKing>>::kProperties[];
|
||||
|
||||
} // namespace Eval::NNUE::Features
|
||||
|
||||
#endif // #ifndef _NNUE_TRAINER_FEATURES_FACTORIZER_HALF_KA_H_
|
||||
Reference in New Issue
Block a user