mirror of
https://github.com/HChaZZY/Stockfish.git
synced 2025-12-24 19:16:49 +08:00
Cleanup trainer features.
This commit is contained in:
@@ -1,106 +1,109 @@
|
||||
// NNUE evaluation function feature conversion class template
|
||||
|
||||
#ifndef _NNUE_TRAINER_FEATURES_FACTORIZER_H_
|
||||
#ifndef _NNUE_TRAINER_FEATURES_FACTORIZER_H_
|
||||
#define _NNUE_TRAINER_FEATURES_FACTORIZER_H_
|
||||
|
||||
#include "../../nnue_common.h"
|
||||
#include "../trainer.h"
|
||||
#include "nnue/nnue_common.h"
|
||||
|
||||
namespace Eval {
|
||||
#include "nnue/trainer/trainer.h"
|
||||
|
||||
namespace NNUE {
|
||||
// NNUE evaluation function feature conversion class template
|
||||
namespace Eval::NNUE::Features {
|
||||
|
||||
namespace Features {
|
||||
// Class template that converts input features into learning features
|
||||
// By default, the learning feature is the same as the original input feature, and specialized as necessary
|
||||
template <typename FeatureType>
|
||||
class Factorizer {
|
||||
public:
|
||||
// Get the dimensionality of the learning feature
|
||||
static constexpr IndexType GetDimensions() {
|
||||
return FeatureType::kDimensions;
|
||||
}
|
||||
|
||||
// Class template that converts input features into learning features
|
||||
// By default, the learning feature is the same as the original input feature, and specialized as necessary
|
||||
template <typename FeatureType>
|
||||
class Factorizer {
|
||||
public:
|
||||
// Get the dimensionality of the learning feature
|
||||
static constexpr IndexType GetDimensions() {
|
||||
return FeatureType::kDimensions;
|
||||
}
|
||||
// Get index of learning feature and scale of learning rate
|
||||
static void AppendTrainingFeatures(
|
||||
IndexType base_index, std::vector<TrainingFeature>* training_features) {
|
||||
|
||||
// Get index of learning feature and scale of learning rate
|
||||
static void AppendTrainingFeatures(
|
||||
IndexType base_index, std::vector<TrainingFeature>* training_features) {
|
||||
assert(base_index <FeatureType::kDimensions);
|
||||
training_features->emplace_back(base_index);
|
||||
}
|
||||
};
|
||||
assert(base_index <FeatureType::kDimensions);
|
||||
training_features->emplace_back(base_index);
|
||||
}
|
||||
};
|
||||
|
||||
// Learning feature information
|
||||
struct FeatureProperties {
|
||||
bool active;
|
||||
IndexType dimensions;
|
||||
};
|
||||
// Learning feature information
|
||||
struct FeatureProperties {
|
||||
bool active;
|
||||
IndexType dimensions;
|
||||
};
|
||||
|
||||
// Add the original input features to the learning features
|
||||
template <typename FeatureType>
|
||||
IndexType AppendBaseFeature(
|
||||
FeatureProperties properties, IndexType base_index,
|
||||
std::vector<TrainingFeature>* training_features) {
|
||||
assert(properties.dimensions == FeatureType::kDimensions);
|
||||
assert(base_index < FeatureType::kDimensions);
|
||||
training_features->emplace_back(base_index);
|
||||
return properties.dimensions;
|
||||
}
|
||||
// Add the original input features to the learning features
|
||||
template <typename FeatureType>
|
||||
IndexType AppendBaseFeature(
|
||||
FeatureProperties properties, IndexType base_index,
|
||||
std::vector<TrainingFeature>* training_features) {
|
||||
|
||||
// If the learning rate scale is not 0, inherit other types of learning features
|
||||
template <typename FeatureType>
|
||||
IndexType InheritFeaturesIfRequired(
|
||||
IndexType index_offset, FeatureProperties properties, IndexType base_index,
|
||||
std::vector<TrainingFeature>* training_features) {
|
||||
if (!properties.active) {
|
||||
return 0;
|
||||
}
|
||||
assert(properties.dimensions == Factorizer<FeatureType>::GetDimensions());
|
||||
assert(base_index < FeatureType::kDimensions);
|
||||
const auto start = training_features->size();
|
||||
Factorizer<FeatureType>::AppendTrainingFeatures(
|
||||
base_index, training_features);
|
||||
for (auto i = start; i < training_features->size(); ++i) {
|
||||
auto& feature = (*training_features)[i];
|
||||
assert(feature.GetIndex() < Factorizer<FeatureType>::GetDimensions());
|
||||
feature.ShiftIndex(index_offset);
|
||||
}
|
||||
return properties.dimensions;
|
||||
}
|
||||
|
||||
// Return the index difference as needed, without adding learning features
|
||||
// Call instead of InheritFeaturesIfRequired() if there are no corresponding features
|
||||
IndexType SkipFeatures(FeatureProperties properties) {
|
||||
if (!properties.active) {
|
||||
return 0;
|
||||
}
|
||||
return properties.dimensions;
|
||||
}
|
||||
|
||||
// Get the dimensionality of the learning feature
|
||||
template <std::size_t N>
|
||||
constexpr IndexType GetActiveDimensions(
|
||||
const FeatureProperties (&properties)[N]) {
|
||||
static_assert(N > 0, "");
|
||||
IndexType dimensions = properties[0].dimensions;
|
||||
for (std::size_t i = 1; i < N; ++i) {
|
||||
if (properties[i].active) {
|
||||
dimensions += properties[i].dimensions;
|
||||
assert(properties.dimensions == FeatureType::kDimensions);
|
||||
assert(base_index < FeatureType::kDimensions);
|
||||
training_features->emplace_back(base_index);
|
||||
return properties.dimensions;
|
||||
}
|
||||
}
|
||||
return dimensions;
|
||||
}
|
||||
|
||||
// get the number of elements in the array
|
||||
template <typename T, std::size_t N>
|
||||
constexpr std::size_t GetArrayLength(const T (&/*array*/)[N]) {
|
||||
return N;
|
||||
}
|
||||
// If the learning rate scale is not 0, inherit other types of learning features
|
||||
template <typename FeatureType>
|
||||
IndexType InheritFeaturesIfRequired(
|
||||
IndexType index_offset, FeatureProperties properties, IndexType base_index,
|
||||
std::vector<TrainingFeature>* training_features) {
|
||||
|
||||
} // namespace Features
|
||||
if (!properties.active) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
} // namespace NNUE
|
||||
assert(properties.dimensions == Factorizer<FeatureType>::GetDimensions());
|
||||
assert(base_index < FeatureType::kDimensions);
|
||||
|
||||
} // namespace Eval
|
||||
const auto start = training_features->size();
|
||||
Factorizer<FeatureType>::AppendTrainingFeatures(
|
||||
base_index, training_features);
|
||||
|
||||
for (auto i = start; i < training_features->size(); ++i) {
|
||||
auto& feature = (*training_features)[i];
|
||||
assert(feature.GetIndex() < Factorizer<FeatureType>::GetDimensions());
|
||||
feature.ShiftIndex(index_offset);
|
||||
}
|
||||
|
||||
return properties.dimensions;
|
||||
}
|
||||
|
||||
// Return the index difference as needed, without adding learning features
|
||||
// Call instead of InheritFeaturesIfRequired() if there are no corresponding features
|
||||
IndexType SkipFeatures(FeatureProperties properties) {
|
||||
if (!properties.active)
|
||||
return 0;
|
||||
|
||||
return properties.dimensions;
|
||||
}
|
||||
|
||||
// Get the dimensionality of the learning feature
|
||||
template <std::size_t N>
|
||||
constexpr IndexType GetActiveDimensions(
|
||||
const FeatureProperties (&properties)[N]) {
|
||||
|
||||
static_assert(N > 0, "");
|
||||
|
||||
IndexType dimensions = properties[0].dimensions;
|
||||
|
||||
for (std::size_t i = 1; i < N; ++i) {
|
||||
if (properties[i].active) {
|
||||
dimensions += properties[i].dimensions;
|
||||
}
|
||||
}
|
||||
|
||||
return dimensions;
|
||||
}
|
||||
|
||||
// get the number of elements in the array
|
||||
template <typename T, std::size_t N>
|
||||
constexpr std::size_t GetArrayLength(const T (&/*array*/)[N]) {
|
||||
return N;
|
||||
}
|
||||
|
||||
} // namespace Eval::NNUE::Features
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,100 +1,105 @@
|
||||
// Specialization for feature set of feature conversion class template of NNUE evaluation function
|
||||
|
||||
#ifndef _NNUE_TRAINER_FEATURES_FACTORIZER_FEATURE_SET_H_
|
||||
#ifndef _NNUE_TRAINER_FEATURES_FACTORIZER_FEATURE_SET_H_
|
||||
#define _NNUE_TRAINER_FEATURES_FACTORIZER_FEATURE_SET_H_
|
||||
|
||||
#include "../../features/feature_set.h"
|
||||
#include "factorizer.h"
|
||||
|
||||
namespace Eval {
|
||||
#include "nnue/features/feature_set.h"
|
||||
|
||||
namespace NNUE {
|
||||
// Specialization for feature set of feature conversion class template of NNUE evaluation function
|
||||
namespace Eval::NNUE::Features {
|
||||
|
||||
namespace Features {
|
||||
// Class template that converts input features into learning features
|
||||
// Specialization for FeatureSet
|
||||
template <typename FirstFeatureType, typename... RemainingFeatureTypes>
|
||||
class Factorizer<FeatureSet<FirstFeatureType, RemainingFeatureTypes...>> {
|
||||
private:
|
||||
using Head = Factorizer<FeatureSet<FirstFeatureType>>;
|
||||
using Tail = Factorizer<FeatureSet<RemainingFeatureTypes...>>;
|
||||
|
||||
// Class template that converts input features into learning features
|
||||
// Specialization for FeatureSet
|
||||
template <typename FirstFeatureType, typename... RemainingFeatureTypes>
|
||||
class Factorizer<FeatureSet<FirstFeatureType, RemainingFeatureTypes...>> {
|
||||
private:
|
||||
using Head = Factorizer<FeatureSet<FirstFeatureType>>;
|
||||
using Tail = Factorizer<FeatureSet<RemainingFeatureTypes...>>;
|
||||
public:
|
||||
// number of dimensions of original input features
|
||||
static constexpr IndexType kBaseDimensions =
|
||||
FeatureSet<FirstFeatureType, RemainingFeatureTypes...>::kDimensions;
|
||||
|
||||
public:
|
||||
// number of dimensions of original input features
|
||||
static constexpr IndexType kBaseDimensions =
|
||||
FeatureSet<FirstFeatureType, RemainingFeatureTypes...>::kDimensions;
|
||||
|
||||
// Get the dimensionality of the learning feature
|
||||
static constexpr IndexType GetDimensions() {
|
||||
return Head::GetDimensions() + Tail::GetDimensions();
|
||||
}
|
||||
|
||||
// Get index of learning feature and scale of learning rate
|
||||
static void AppendTrainingFeatures(
|
||||
IndexType base_index, std::vector<TrainingFeature>* training_features,
|
||||
IndexType base_dimensions = kBaseDimensions) {
|
||||
assert(base_index < kBaseDimensions);
|
||||
constexpr auto boundary = FeatureSet<RemainingFeatureTypes...>::kDimensions;
|
||||
if (base_index < boundary) {
|
||||
Tail::AppendTrainingFeatures(
|
||||
base_index, training_features, base_dimensions);
|
||||
} else {
|
||||
const auto start = training_features->size();
|
||||
Head::AppendTrainingFeatures(
|
||||
base_index - boundary, training_features, base_dimensions);
|
||||
for (auto i = start; i < training_features->size(); ++i) {
|
||||
auto& feature = (*training_features)[i];
|
||||
const auto index = feature.GetIndex();
|
||||
assert(index < Head::GetDimensions() ||
|
||||
(index >= base_dimensions &&
|
||||
index < base_dimensions +
|
||||
Head::GetDimensions() - Head::kBaseDimensions));
|
||||
if (index < Head::kBaseDimensions) {
|
||||
feature.ShiftIndex(Tail::kBaseDimensions);
|
||||
} else {
|
||||
feature.ShiftIndex(Tail::GetDimensions() - Tail::kBaseDimensions);
|
||||
// Get the dimensionality of the learning feature
|
||||
static constexpr IndexType GetDimensions() {
|
||||
return Head::GetDimensions() + Tail::GetDimensions();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// Class template that converts input features into learning features
|
||||
// Specialization when FeatureSet has one template argument
|
||||
template <typename FeatureType>
|
||||
class Factorizer<FeatureSet<FeatureType>> {
|
||||
public:
|
||||
// number of dimensions of original input features
|
||||
static constexpr IndexType kBaseDimensions = FeatureType::kDimensions;
|
||||
// Get index of learning feature and scale of learning rate
|
||||
static void AppendTrainingFeatures(
|
||||
IndexType base_index, std::vector<TrainingFeature>* training_features,
|
||||
IndexType base_dimensions = kBaseDimensions) {
|
||||
|
||||
// Get the dimensionality of the learning feature
|
||||
static constexpr IndexType GetDimensions() {
|
||||
return Factorizer<FeatureType>::GetDimensions();
|
||||
}
|
||||
assert(base_index < kBaseDimensions);
|
||||
|
||||
// Get index of learning feature and scale of learning rate
|
||||
static void AppendTrainingFeatures(
|
||||
IndexType base_index, std::vector<TrainingFeature>* training_features,
|
||||
IndexType base_dimensions = kBaseDimensions) {
|
||||
assert(base_index < kBaseDimensions);
|
||||
const auto start = training_features->size();
|
||||
Factorizer<FeatureType>::AppendTrainingFeatures(
|
||||
base_index, training_features);
|
||||
for (auto i = start; i < training_features->size(); ++i) {
|
||||
auto& feature = (*training_features)[i];
|
||||
assert(feature.GetIndex() < Factorizer<FeatureType>::GetDimensions());
|
||||
if (feature.GetIndex() >= kBaseDimensions) {
|
||||
feature.ShiftIndex(base_dimensions - kBaseDimensions);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
constexpr auto boundary = FeatureSet<RemainingFeatureTypes...>::kDimensions;
|
||||
|
||||
} // namespace Features
|
||||
if (base_index < boundary) {
|
||||
Tail::AppendTrainingFeatures(
|
||||
base_index, training_features, base_dimensions);
|
||||
}
|
||||
else {
|
||||
const auto start = training_features->size();
|
||||
|
||||
} // namespace NNUE
|
||||
Head::AppendTrainingFeatures(
|
||||
base_index - boundary, training_features, base_dimensions);
|
||||
|
||||
} // namespace Eval
|
||||
for (auto i = start; i < training_features->size(); ++i) {
|
||||
auto& feature = (*training_features)[i];
|
||||
const auto index = feature.GetIndex();
|
||||
|
||||
assert(index < Head::GetDimensions() ||
|
||||
(index >= base_dimensions &&
|
||||
index < base_dimensions +
|
||||
Head::GetDimensions() - Head::kBaseDimensions));
|
||||
|
||||
if (index < Head::kBaseDimensions) {
|
||||
feature.ShiftIndex(Tail::kBaseDimensions);
|
||||
}
|
||||
else {
|
||||
feature.ShiftIndex(Tail::GetDimensions() - Tail::kBaseDimensions);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// Class template that converts input features into learning features
|
||||
// Specialization when FeatureSet has one template argument
|
||||
template <typename FeatureType>
|
||||
class Factorizer<FeatureSet<FeatureType>> {
|
||||
public:
|
||||
// number of dimensions of original input features
|
||||
static constexpr IndexType kBaseDimensions = FeatureType::kDimensions;
|
||||
|
||||
// Get the dimensionality of the learning feature
|
||||
static constexpr IndexType GetDimensions() {
|
||||
return Factorizer<FeatureType>::GetDimensions();
|
||||
}
|
||||
|
||||
// Get index of learning feature and scale of learning rate
|
||||
static void AppendTrainingFeatures(
|
||||
IndexType base_index, std::vector<TrainingFeature>* training_features,
|
||||
IndexType base_dimensions = kBaseDimensions) {
|
||||
|
||||
assert(base_index < kBaseDimensions);
|
||||
|
||||
const auto start = training_features->size();
|
||||
|
||||
Factorizer<FeatureType>::AppendTrainingFeatures(
|
||||
base_index, training_features);
|
||||
|
||||
for (auto i = start; i < training_features->size(); ++i) {
|
||||
auto& feature = (*training_features)[i];
|
||||
assert(feature.GetIndex() < Factorizer<FeatureType>::GetDimensions());
|
||||
if (feature.GetIndex() >= kBaseDimensions) {
|
||||
feature.ShiftIndex(base_dimensions - kBaseDimensions);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace Eval::NNUE::Features
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,99 +1,96 @@
|
||||
// Specialization of NNUE evaluation function feature conversion class template for HalfKP
|
||||
|
||||
#ifndef _NNUE_TRAINER_FEATURES_FACTORIZER_HALF_KP_H_
|
||||
#ifndef _NNUE_TRAINER_FEATURES_FACTORIZER_HALF_KP_H_
|
||||
#define _NNUE_TRAINER_FEATURES_FACTORIZER_HALF_KP_H_
|
||||
|
||||
#include "../../features/half_kp.h"
|
||||
#include "../../features/p.h"
|
||||
#include "../../features/half_relative_kp.h"
|
||||
#include "factorizer.h"
|
||||
|
||||
namespace Eval {
|
||||
#include "nnue/features/half_kp.h"
|
||||
#include "nnue/features/p.h"
|
||||
#include "nnue/features/half_relative_kp.h"
|
||||
|
||||
namespace NNUE {
|
||||
// Specialization of NNUE evaluation function feature conversion class template for HalfKP
|
||||
namespace Eval::NNUE::Features {
|
||||
|
||||
namespace Features {
|
||||
// Class template that converts input features into learning features
|
||||
// Specialization for HalfKP
|
||||
template <Side AssociatedKing>
|
||||
class Factorizer<HalfKP<AssociatedKing>> {
|
||||
private:
|
||||
using FeatureType = HalfKP<AssociatedKing>;
|
||||
|
||||
// Class template that converts input features into learning features
|
||||
// Specialization for HalfKP
|
||||
template <Side AssociatedKing>
|
||||
class Factorizer<HalfKP<AssociatedKing>> {
|
||||
private:
|
||||
using FeatureType = HalfKP<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;
|
||||
|
||||
// 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 {
|
||||
kFeaturesHalfKP,
|
||||
kFeaturesHalfK,
|
||||
kFeaturesP,
|
||||
kFeaturesHalfRelativeKP,
|
||||
kNumTrainingFeatureTypes,
|
||||
};
|
||||
|
||||
// Type of learning feature
|
||||
enum TrainingFeatureType {
|
||||
kFeaturesHalfKP,
|
||||
kFeaturesHalfK,
|
||||
kFeaturesP,
|
||||
kFeaturesHalfRelativeKP,
|
||||
kNumTrainingFeatureTypes,
|
||||
};
|
||||
// Learning feature information
|
||||
static constexpr FeatureProperties kProperties[] = {
|
||||
// kFeaturesHalfKP
|
||||
{true, FeatureType::kDimensions},
|
||||
// kFeaturesHalfK
|
||||
{true, SQUARE_NB},
|
||||
// kFeaturesP
|
||||
{true, Factorizer<P>::GetDimensions()},
|
||||
// kFeaturesHalfRelativeKP
|
||||
{true, Factorizer<HalfRelativeKP<AssociatedKing>>::GetDimensions()},
|
||||
};
|
||||
|
||||
// Learning feature information
|
||||
static constexpr FeatureProperties kProperties[] = {
|
||||
// kFeaturesHalfKP
|
||||
{true, FeatureType::kDimensions},
|
||||
// kFeaturesHalfK
|
||||
{true, SQUARE_NB},
|
||||
// kFeaturesP
|
||||
{true, Factorizer<P>::GetDimensions()},
|
||||
// kFeaturesHalfRelativeKP
|
||||
{true, Factorizer<HalfRelativeKP<AssociatedKing>>::GetDimensions()},
|
||||
};
|
||||
static_assert(GetArrayLength(kProperties) == kNumTrainingFeatureTypes, "");
|
||||
static_assert(GetArrayLength(kProperties) == kNumTrainingFeatureTypes, "");
|
||||
|
||||
public:
|
||||
// Get the dimensionality of the learning feature
|
||||
static constexpr IndexType GetDimensions() {
|
||||
return GetActiveDimensions(kProperties);
|
||||
}
|
||||
public:
|
||||
// Get the dimensionality of the learning feature
|
||||
static constexpr IndexType GetDimensions() {
|
||||
return GetActiveDimensions(kProperties);
|
||||
}
|
||||
|
||||
// Get index of learning feature and scale of learning rate
|
||||
static void AppendTrainingFeatures(
|
||||
IndexType base_index, std::vector<TrainingFeature>* training_features) {
|
||||
// kFeaturesHalfKP
|
||||
IndexType index_offset = AppendBaseFeature<FeatureType>(
|
||||
kProperties[kFeaturesHalfKP], base_index, training_features);
|
||||
// Get index of learning feature and scale of learning rate
|
||||
static void AppendTrainingFeatures(
|
||||
IndexType base_index, std::vector<TrainingFeature>* training_features) {
|
||||
|
||||
const auto sq_k = static_cast<Square>(base_index / PS_END);
|
||||
const auto p = static_cast<IndexType>(base_index % PS_END);
|
||||
// kFeaturesHalfK
|
||||
{
|
||||
const auto& properties = kProperties[kFeaturesHalfK];
|
||||
if (properties.active) {
|
||||
training_features->emplace_back(index_offset + sq_k);
|
||||
index_offset += properties.dimensions;
|
||||
}
|
||||
}
|
||||
// kFeaturesP
|
||||
index_offset += InheritFeaturesIfRequired<P>(
|
||||
index_offset, kProperties[kFeaturesP], p, training_features);
|
||||
// kFeaturesHalfRelativeKP
|
||||
if (p >= PS_W_PAWN) {
|
||||
index_offset += InheritFeaturesIfRequired<HalfRelativeKP<AssociatedKing>>(
|
||||
index_offset, kProperties[kFeaturesHalfRelativeKP],
|
||||
HalfRelativeKP<AssociatedKing>::MakeIndex(sq_k, p),
|
||||
training_features);
|
||||
} else {
|
||||
index_offset += SkipFeatures(kProperties[kFeaturesHalfRelativeKP]);
|
||||
}
|
||||
// kFeaturesHalfKP
|
||||
IndexType index_offset = AppendBaseFeature<FeatureType>(
|
||||
kProperties[kFeaturesHalfKP], base_index, training_features);
|
||||
|
||||
assert(index_offset == GetDimensions());
|
||||
}
|
||||
};
|
||||
const auto sq_k = static_cast<Square>(base_index / PS_END);
|
||||
const auto p = static_cast<IndexType>(base_index % PS_END);
|
||||
|
||||
template <Side AssociatedKing>
|
||||
constexpr FeatureProperties Factorizer<HalfKP<AssociatedKing>>::kProperties[];
|
||||
// kFeaturesHalfK
|
||||
{
|
||||
const auto& properties = kProperties[kFeaturesHalfK];
|
||||
if (properties.active) {
|
||||
training_features->emplace_back(index_offset + sq_k);
|
||||
index_offset += properties.dimensions;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace Features
|
||||
// kFeaturesP
|
||||
index_offset += InheritFeaturesIfRequired<P>(
|
||||
index_offset, kProperties[kFeaturesP], p, training_features);
|
||||
// kFeaturesHalfRelativeKP
|
||||
if (p >= PS_W_PAWN) {
|
||||
index_offset += InheritFeaturesIfRequired<HalfRelativeKP<AssociatedKing>>(
|
||||
index_offset, kProperties[kFeaturesHalfRelativeKP],
|
||||
HalfRelativeKP<AssociatedKing>::MakeIndex(sq_k, p),
|
||||
training_features);
|
||||
}
|
||||
else {
|
||||
index_offset += SkipFeatures(kProperties[kFeaturesHalfRelativeKP]);
|
||||
}
|
||||
|
||||
} // namespace NNUE
|
||||
assert(index_offset == GetDimensions());
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace Eval
|
||||
template <Side AssociatedKing>
|
||||
constexpr FeatureProperties Factorizer<HalfKP<AssociatedKing>>::kProperties[];
|
||||
|
||||
} // namespace Eval::NNUE::Features
|
||||
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user