mirror of
https://github.com/opelly27/Stockfish.git
synced 2026-05-20 09:47:46 +00:00
Merge branch 'master' of github.com:official-stockfish/Stockfish into nnue-player-merge
# Conflicts: # README.md # Readme.md # src/Makefile # src/evaluate.cpp # src/evaluate.h # src/misc.cpp # src/nnue/architectures/halfkp_256x2-32-32.h # src/nnue/evaluate_nnue.cpp # src/nnue/evaluate_nnue.h # src/nnue/features/feature_set.h # src/nnue/features/features_common.h # src/nnue/features/half_kp.cpp # src/nnue/features/half_kp.h # src/nnue/features/index_list.h # src/nnue/layers/affine_transform.h # src/nnue/layers/clipped_relu.h # src/nnue/layers/input_slice.h # src/nnue/nnue_accumulator.h # src/nnue/nnue_architecture.h # src/nnue/nnue_common.h # src/nnue/nnue_feature_transformer.h # src/position.cpp # src/position.h # src/types.h # src/ucioption.cpp # stockfish.md
This commit is contained in:
@@ -23,7 +23,7 @@ namespace Eval {
|
||||
}
|
||||
|
||||
if (perspective == BLACK) {
|
||||
epSquare = Inv(epSquare);
|
||||
epSquare = rotate180(epSquare);
|
||||
}
|
||||
|
||||
auto file = file_of(epSquare);
|
||||
|
||||
+199
-199
@@ -1,249 +1,249 @@
|
||||
// A class template that represents the input feature set of the NNUE evaluation function
|
||||
/*
|
||||
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
|
||||
Copyright (C) 2004-2020 The Stockfish developers (see AUTHORS file)
|
||||
|
||||
#ifndef _NNUE_FEATURE_SET_H_
|
||||
#define _NNUE_FEATURE_SET_H_
|
||||
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.
|
||||
|
||||
#if defined(EVAL_NNUE)
|
||||
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/>.
|
||||
*/
|
||||
|
||||
// A class template that represents the input feature set of the NNUE evaluation function
|
||||
|
||||
#ifndef NNUE_FEATURE_SET_H_INCLUDED
|
||||
#define NNUE_FEATURE_SET_H_INCLUDED
|
||||
|
||||
#include "features_common.h"
|
||||
#include <array>
|
||||
|
||||
namespace Eval {
|
||||
namespace Eval::NNUE::Features {
|
||||
|
||||
namespace NNUE {
|
||||
// Class template that represents a list of values
|
||||
template <typename T, T... Values>
|
||||
struct CompileTimeList;
|
||||
|
||||
namespace Features {
|
||||
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...}};
|
||||
};
|
||||
|
||||
// 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>
|
||||
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 = {{}};
|
||||
};
|
||||
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 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<
|
||||
// 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>;
|
||||
};
|
||||
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]);
|
||||
}
|
||||
}
|
||||
// Base class of feature set
|
||||
template <typename Derived>
|
||||
class FeatureSetBase {
|
||||
|
||||
// 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;
|
||||
public:
|
||||
// Get a list of indices for active features
|
||||
template <typename IndexListType>
|
||||
static void AppendActiveIndices(
|
||||
const Position& pos, TriggerEvent trigger, IndexListType active[2]) {
|
||||
|
||||
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]) {
|
||||
for (Color perspective : { WHITE, BLACK }) {
|
||||
Derived::CollectActiveIndices(
|
||||
pos, trigger, perspective, &added[perspective]);
|
||||
} else {
|
||||
Derived::CollectChangedIndices(
|
||||
pos, trigger, perspective,
|
||||
&removed[perspective], &added[perspective]);
|
||||
pos, trigger, perspective, &active[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...> :
|
||||
// Get a list of indices for recently changed features
|
||||
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 (Color perspective : { WHITE, BLACK }) {
|
||||
reset[perspective] = false;
|
||||
switch (trigger) {
|
||||
case TriggerEvent::kFriendKingMoved:
|
||||
reset[perspective] =
|
||||
dp.pieceId[0] == PIECE_ID_KING + perspective;
|
||||
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...>;
|
||||
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 =
|
||||
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 =
|
||||
// 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 =
|
||||
// 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,
|
||||
// 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;
|
||||
static constexpr auto kRefreshTriggers = SortedTriggerSet::kValues;
|
||||
|
||||
// Get the feature quantity name
|
||||
static std::string GetName() {
|
||||
return std::string(Head::kName) + "+" + Tail::GetName();
|
||||
}
|
||||
// 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(
|
||||
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;
|
||||
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(
|
||||
// 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;
|
||||
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;
|
||||
};
|
||||
// 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;
|
||||
// Class template that represents the feature set
|
||||
template <typename FeatureType>
|
||||
class FeatureSet<FeatureType> : public FeatureSetBase<FeatureSet<FeatureType>> {
|
||||
|
||||
// Get the feature quantity name
|
||||
static std::string GetName() {
|
||||
return FeatureType::kName;
|
||||
}
|
||||
public:
|
||||
// Hash value embedded in the evaluation file
|
||||
static constexpr std::uint32_t kHashValue = FeatureType::kHashValue;
|
||||
// Number of feature dimensions
|
||||
static constexpr IndexType kDimensions = FeatureType::kDimensions;
|
||||
// Maximum number of simultaneously active features
|
||||
static constexpr IndexType kMaxActiveDimensions =
|
||||
FeatureType::kMaxActiveDimensions;
|
||||
// Trigger for full calculation instead of difference calculation
|
||||
using SortedTriggerSet =
|
||||
CompileTimeList<TriggerEvent, FeatureType::kRefreshTrigger>;
|
||||
static constexpr auto kRefreshTriggers = SortedTriggerSet::kValues;
|
||||
|
||||
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 the feature quantity name
|
||||
static std::string GetName() {
|
||||
return FeatureType::kName;
|
||||
}
|
||||
}
|
||||
|
||||
// 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);
|
||||
private:
|
||||
// Get a list of indices for active 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Make the base class and the class template that recursively uses itself a friend
|
||||
friend class FeatureSetBase<FeatureSet>;
|
||||
template <typename... FeatureTypes>
|
||||
friend class FeatureSet;
|
||||
};
|
||||
// Get a list of indices for recently changed features
|
||||
static void CollectChangedIndices(
|
||||
const Position& pos, const TriggerEvent trigger, const Color perspective,
|
||||
IndexList* const removed, IndexList* const added) {
|
||||
|
||||
} // namespace Features
|
||||
if (FeatureType::kRefreshTrigger == trigger) {
|
||||
FeatureType::AppendChangedIndices(pos, perspective, removed, added);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace NNUE
|
||||
// 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 Eval
|
||||
} // namespace Eval::NNUE::Features
|
||||
|
||||
#endif // defined(EVAL_NNUE)
|
||||
|
||||
#endif
|
||||
#endif // #ifndef NNUE_FEATURE_SET_H_INCLUDED
|
||||
|
||||
@@ -1,47 +1,50 @@
|
||||
//Common header of input features of NNUE evaluation function
|
||||
/*
|
||||
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
|
||||
Copyright (C) 2004-2020 The Stockfish developers (see AUTHORS file)
|
||||
|
||||
#ifndef _NNUE_FEATURES_COMMON_H_
|
||||
#define _NNUE_FEATURES_COMMON_H_
|
||||
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.
|
||||
|
||||
#if defined(EVAL_NNUE)
|
||||
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/>.
|
||||
*/
|
||||
|
||||
//Common header of input features of NNUE evaluation function
|
||||
|
||||
#ifndef NNUE_FEATURES_COMMON_H_INCLUDED
|
||||
#define NNUE_FEATURES_COMMON_H_INCLUDED
|
||||
|
||||
#include "../../evaluate.h"
|
||||
#include "../nnue_common.h"
|
||||
|
||||
namespace Eval {
|
||||
namespace Eval::NNUE::Features {
|
||||
|
||||
namespace NNUE {
|
||||
class IndexList;
|
||||
|
||||
namespace Features {
|
||||
template <typename... FeatureTypes>
|
||||
class FeatureSet;
|
||||
|
||||
// Index list type
|
||||
class IndexList;
|
||||
// Trigger to perform full calculations instead of difference only
|
||||
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
|
||||
};
|
||||
|
||||
// Class template that represents the feature set
|
||||
template <typename... FeatureTypes>
|
||||
class FeatureSet;
|
||||
enum class Side {
|
||||
kFriend, // side to move
|
||||
kEnemy, // opponent
|
||||
};
|
||||
|
||||
// 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
|
||||
};
|
||||
} // namespace Eval::NNUE::Features
|
||||
|
||||
// turn side or other side
|
||||
enum class Side {
|
||||
kFriend, // turn side
|
||||
kEnemy, // opponent
|
||||
};
|
||||
|
||||
} // namespace Features
|
||||
|
||||
} // namespace NNUE
|
||||
|
||||
} // namespace Eval
|
||||
|
||||
#endif // defined(EVAL_NNUE)
|
||||
|
||||
#endif
|
||||
#endif // #ifndef NNUE_FEATURES_COMMON_H_INCLUDED
|
||||
|
||||
@@ -1,84 +1,92 @@
|
||||
//Definition of input features HalfKP of NNUE evaluation function
|
||||
/*
|
||||
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
|
||||
Copyright (C) 2004-2020 The Stockfish developers (see AUTHORS file)
|
||||
|
||||
#if defined(EVAL_NNUE)
|
||||
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 HalfKP of NNUE evaluation function
|
||||
|
||||
#include "half_kp.h"
|
||||
#include "index_list.h"
|
||||
|
||||
namespace Eval {
|
||||
namespace Eval::NNUE::Features {
|
||||
|
||||
namespace NNUE {
|
||||
// Find the index of the feature quantity from the king position and PieceSquare
|
||||
template <Side AssociatedKing>
|
||||
inline IndexType HalfKP<AssociatedKing>::MakeIndex(Square sq_k, PieceSquare p) {
|
||||
return static_cast<IndexType>(PS_END) * static_cast<IndexType>(sq_k) + p;
|
||||
}
|
||||
|
||||
namespace Features {
|
||||
// Get pieces information
|
||||
template <Side AssociatedKing>
|
||||
inline void HalfKP<AssociatedKing>::GetPieces(
|
||||
const Position& pos, Color perspective,
|
||||
PieceSquare** pieces, Square* sq_target_k) {
|
||||
|
||||
// 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;
|
||||
}
|
||||
*pieces = (perspective == BLACK) ?
|
||||
pos.eval_list()->piece_list_fb() :
|
||||
pos.eval_list()->piece_list_fw();
|
||||
const PieceId target = (AssociatedKing == Side::kFriend) ?
|
||||
static_cast<PieceId>(PIECE_ID_KING + perspective) :
|
||||
static_cast<PieceId>(PIECE_ID_KING + ~perspective);
|
||||
*sq_target_k = static_cast<Square>(((*pieces)[target] - PS_W_KING) % SQUARE_NB);
|
||||
}
|
||||
|
||||
// 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 for active features
|
||||
template <Side AssociatedKing>
|
||||
void HalfKP<AssociatedKing>::AppendActiveIndices(
|
||||
const Position& pos, Color perspective, IndexList* active) {
|
||||
|
||||
// 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;
|
||||
// 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]));
|
||||
PieceSquare* pieces;
|
||||
Square sq_target_k;
|
||||
GetPieces(pos, perspective, &pieces, &sq_target_k);
|
||||
for (PieceId i = PIECE_ID_ZERO; i < PIECE_ID_KING; ++i) {
|
||||
if (pieces[i] != PS_NONE) {
|
||||
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));
|
||||
// Get a list of indices for recently changed features
|
||||
template <Side AssociatedKing>
|
||||
void HalfKP<AssociatedKing>::AppendChangedIndices(
|
||||
const Position& pos, Color perspective,
|
||||
IndexList* removed, IndexList* added) {
|
||||
|
||||
PieceSquare* 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.pieceId[i] >= PIECE_ID_KING) continue;
|
||||
const auto old_p = static_cast<PieceSquare>(
|
||||
dp.old_piece[i].from[perspective]);
|
||||
if (old_p != PS_NONE) {
|
||||
removed->push_back(MakeIndex(sq_target_k, old_p));
|
||||
}
|
||||
const auto new_p = static_cast<PieceSquare>(
|
||||
dp.new_piece[i].from[perspective]);
|
||||
if (new_p != PS_NONE) {
|
||||
added->push_back(MakeIndex(sq_target_k, new_p));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template class HalfKP<Side::kFriend>;
|
||||
template class HalfKP<Side::kEnemy>;
|
||||
template class HalfKP<Side::kFriend>;
|
||||
|
||||
} // namespace Features
|
||||
|
||||
} // namespace NNUE
|
||||
|
||||
} // namespace Eval
|
||||
|
||||
#endif // defined(EVAL_NNUE)
|
||||
} // namespace Eval::NNUE::Features
|
||||
|
||||
+53
-48
@@ -1,62 +1,67 @@
|
||||
//Definition of input features HalfKP of NNUE evaluation function
|
||||
/*
|
||||
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
|
||||
Copyright (C) 2004-2020 The Stockfish developers (see AUTHORS file)
|
||||
|
||||
#ifndef _NNUE_FEATURES_HALF_KP_H_
|
||||
#define _NNUE_FEATURES_HALF_KP_H_
|
||||
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.
|
||||
|
||||
#if defined(EVAL_NNUE)
|
||||
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 HalfKP of NNUE evaluation function
|
||||
|
||||
#ifndef NNUE_FEATURES_HALF_KP_H_INCLUDED
|
||||
#define NNUE_FEATURES_HALF_KP_H_INCLUDED
|
||||
|
||||
#include "../../evaluate.h"
|
||||
#include "features_common.h"
|
||||
|
||||
namespace Eval {
|
||||
namespace Eval::NNUE::Features {
|
||||
|
||||
namespace NNUE {
|
||||
// Feature HalfKP: Combination of the position of own king
|
||||
// and the position of pieces other than kings
|
||||
template <Side AssociatedKing>
|
||||
class HalfKP {
|
||||
|
||||
namespace Features {
|
||||
public:
|
||||
// Feature name
|
||||
static constexpr const char* kName = "HalfKP(Friend)";
|
||||
// Hash value embedded in the evaluation 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>(PS_END);
|
||||
// Maximum number of simultaneously active features
|
||||
static constexpr IndexType kMaxActiveDimensions = PIECE_ID_KING;
|
||||
// Trigger for full calculation instead of difference calculation
|
||||
static constexpr TriggerEvent kRefreshTrigger = TriggerEvent::kFriendKingMoved;
|
||||
|
||||
// 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 for active features
|
||||
static void AppendActiveIndices(const Position& pos, Color perspective,
|
||||
IndexList* active);
|
||||
|
||||
// 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 for recently changed features
|
||||
static void AppendChangedIndices(const Position& pos, Color perspective,
|
||||
IndexList* removed, IndexList* added);
|
||||
|
||||
// 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);
|
||||
// Index of a feature for a given king position and another piece on some square
|
||||
static IndexType MakeIndex(Square sq_k, PieceSquare p);
|
||||
|
||||
// Find the index of the feature quantity from the ball position and BonaPiece
|
||||
static IndexType MakeIndex(Square sq_k, BonaPiece p);
|
||||
private:
|
||||
// Get pieces information
|
||||
static void GetPieces(const Position& pos, Color perspective,
|
||||
PieceSquare** pieces, Square* sq_target_k);
|
||||
};
|
||||
|
||||
private:
|
||||
// Get the piece information
|
||||
static void GetPieces(const Position& pos, Color perspective,
|
||||
BonaPiece** pieces, Square* sq_target_k);
|
||||
};
|
||||
} // namespace Eval::NNUE::Features
|
||||
|
||||
} // namespace Features
|
||||
|
||||
} // namespace NNUE
|
||||
|
||||
} // namespace Eval
|
||||
|
||||
#endif // defined(EVAL_NNUE)
|
||||
|
||||
#endif
|
||||
#endif // #ifndef NNUE_FEATURES_HALF_KP_H_INCLUDED
|
||||
|
||||
@@ -11,14 +11,14 @@ namespace NNUE {
|
||||
|
||||
namespace Features {
|
||||
|
||||
// Find the index of the feature quantity from the ball position and BonaPiece
|
||||
// Find the index of the feature quantity from the ball position and PieceSquare
|
||||
template <Side AssociatedKing>
|
||||
inline IndexType HalfRelativeKP<AssociatedKing>::MakeIndex(
|
||||
Square sq_k, BonaPiece p) {
|
||||
Square sq_k, PieceSquare 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 piece_index = (p - PieceSquare::PS_W_PAWN) / SQUARE_NB;
|
||||
const Square sq_p = static_cast<Square>((p - PieceSquare::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;
|
||||
@@ -28,14 +28,14 @@ inline IndexType HalfRelativeKP<AssociatedKing>::MakeIndex(
|
||||
template <Side AssociatedKing>
|
||||
inline void HalfRelativeKP<AssociatedKing>::GetPieces(
|
||||
const Position& pos, Color perspective,
|
||||
BonaPiece** pieces, Square* sq_target_k) {
|
||||
PieceSquare** 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);
|
||||
const PieceId target = (AssociatedKing == Side::kFriend) ?
|
||||
static_cast<PieceId>(PieceId::PIECE_ID_KING + perspective) :
|
||||
static_cast<PieceId>(PieceId::PIECE_ID_KING + ~perspective);
|
||||
*sq_target_k = static_cast<Square>(((*pieces)[target] - PieceSquare::PS_W_KING) % SQUARE_NB);
|
||||
}
|
||||
|
||||
// Get a list of indices with a value of 1 among the features
|
||||
@@ -45,12 +45,12 @@ void HalfRelativeKP<AssociatedKing>::AppendActiveIndices(
|
||||
// do nothing if array size is small to avoid compiler warning
|
||||
if (RawFeatures::kMaxActiveDimensions < kMaxActiveDimensions) return;
|
||||
|
||||
BonaPiece* pieces;
|
||||
PieceSquare* 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) {
|
||||
for (PieceId i = PieceId::PIECE_ID_ZERO; i < PieceId::PIECE_ID_KING; ++i) {
|
||||
if (pieces[i] >= PieceSquare::PS_W_PAWN) {
|
||||
if (pieces[i] != PieceSquare::PS_NONE) {
|
||||
active->push_back(MakeIndex(sq_target_k, pieces[i]));
|
||||
}
|
||||
}
|
||||
@@ -62,23 +62,23 @@ template <Side AssociatedKing>
|
||||
void HalfRelativeKP<AssociatedKing>::AppendChangedIndices(
|
||||
const Position& pos, Color perspective,
|
||||
IndexList* removed, IndexList* added) {
|
||||
BonaPiece* pieces;
|
||||
PieceSquare* 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) {
|
||||
if (dp.pieceId[i] >= PieceId::PIECE_ID_KING) continue;
|
||||
const auto old_p = static_cast<PieceSquare>(
|
||||
dp.old_piece[i].from[perspective]);
|
||||
if (old_p >= PieceSquare::PS_W_PAWN) {
|
||||
if (old_p != PieceSquare::PS_NONE) {
|
||||
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) {
|
||||
const auto new_p = static_cast<PieceSquare>(
|
||||
dp.new_piece[i].from[perspective]);
|
||||
if (new_p >= PieceSquare::PS_W_PAWN) {
|
||||
if (new_p != PieceSquare::PS_NONE) {
|
||||
added->push_back(MakeIndex(sq_target_k, new_p));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,7 +25,7 @@ class HalfRelativeKP {
|
||||
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;
|
||||
static constexpr IndexType kNumPieceKinds = (PieceSquare::PS_END - PieceSquare::PS_W_PAWN) / 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
|
||||
@@ -34,7 +34,7 @@ class HalfRelativeKP {
|
||||
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;
|
||||
static constexpr IndexType kMaxActiveDimensions = PieceId::PIECE_ID_KING;
|
||||
// Timing of full calculation instead of difference calculation
|
||||
static constexpr TriggerEvent kRefreshTrigger =
|
||||
(AssociatedKing == Side::kFriend) ?
|
||||
@@ -48,13 +48,13 @@ class HalfRelativeKP {
|
||||
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);
|
||||
// Find the index of the feature quantity from the ball position and PieceSquare
|
||||
static IndexType MakeIndex(Square sq_k, PieceSquare p);
|
||||
|
||||
private:
|
||||
// Get the piece information
|
||||
static void GetPieces(const Position& pos, Color perspective,
|
||||
BonaPiece** pieces, Square* sq_target_k);
|
||||
PieceSquare** pieces, Square* sq_target_k);
|
||||
};
|
||||
|
||||
} // namespace Features
|
||||
|
||||
@@ -1,55 +1,64 @@
|
||||
// Definition of index list of input features
|
||||
/*
|
||||
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
|
||||
Copyright (C) 2004-2020 The Stockfish developers (see AUTHORS file)
|
||||
|
||||
#ifndef _NNUE_FEATURES_INDEX_LIST_H_
|
||||
#define _NNUE_FEATURES_INDEX_LIST_H_
|
||||
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.
|
||||
|
||||
#if defined(EVAL_NNUE)
|
||||
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 index list of input features
|
||||
|
||||
#ifndef NNUE_FEATURES_INDEX_LIST_H_INCLUDED
|
||||
#define NNUE_FEATURES_INDEX_LIST_H_INCLUDED
|
||||
|
||||
#include "../../position.h"
|
||||
#include "../nnue_architecture.h"
|
||||
|
||||
namespace Eval {
|
||||
namespace Eval::NNUE::Features {
|
||||
|
||||
namespace NNUE {
|
||||
// Class template used for feature index list
|
||||
template <typename T, std::size_t MaxSize>
|
||||
class ValueList {
|
||||
|
||||
namespace Features {
|
||||
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_; }
|
||||
|
||||
// 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]);
|
||||
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_);
|
||||
}
|
||||
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> {
|
||||
};
|
||||
private:
|
||||
T values_[MaxSize];
|
||||
std::size_t size_ = 0;
|
||||
};
|
||||
|
||||
} // namespace Features
|
||||
//Type of feature index list
|
||||
class IndexList
|
||||
: public ValueList<IndexType, RawFeatures::kMaxActiveDimensions> {
|
||||
};
|
||||
|
||||
} // namespace NNUE
|
||||
} // namespace Eval::NNUE::Features
|
||||
|
||||
} // namespace Eval
|
||||
|
||||
#endif // defined(EVAL_NNUE)
|
||||
|
||||
#endif
|
||||
#endif // NNUE_FEATURES_INDEX_LIST_H_INCLUDED
|
||||
|
||||
@@ -17,13 +17,13 @@ void K::AppendActiveIndices(
|
||||
// do nothing if array size is small to avoid compiler warning
|
||||
if (RawFeatures::kMaxActiveDimensions < kMaxActiveDimensions) return;
|
||||
|
||||
const BonaPiece* pieces = (perspective == BLACK) ?
|
||||
const PieceSquare* 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);
|
||||
assert(pieces[PieceId::PIECE_ID_BKING] != PieceSquare::PS_NONE);
|
||||
assert(pieces[PieceId::PIECE_ID_WKING] != PieceSquare::PS_NONE);
|
||||
for (PieceId i = PieceId::PIECE_ID_KING; i < PieceId::PIECE_ID_NONE; ++i) {
|
||||
active->push_back(pieces[i] - PieceSquare::PS_END);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -32,11 +32,11 @@ 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) {
|
||||
if (dp.pieceId[0] >= PieceId::PIECE_ID_KING) {
|
||||
removed->push_back(
|
||||
dp.changed_piece[0].old_piece.from[perspective] - fe_end);
|
||||
dp.old_piece[0].from[perspective] - PieceSquare::PS_END);
|
||||
added->push_back(
|
||||
dp.changed_piece[0].new_piece.from[perspective] - fe_end);
|
||||
dp.new_piece[0].from[perspective] - PieceSquare::PS_END);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -17,11 +17,11 @@ void P::AppendActiveIndices(
|
||||
// do nothing if array size is small to avoid compiler warning
|
||||
if (RawFeatures::kMaxActiveDimensions < kMaxActiveDimensions) return;
|
||||
|
||||
const BonaPiece* pieces = (perspective == BLACK) ?
|
||||
const PieceSquare* 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) {
|
||||
for (PieceId i = PieceId::PIECE_ID_ZERO; i < PieceId::PIECE_ID_KING; ++i) {
|
||||
if (pieces[i] != PieceSquare::PS_NONE) {
|
||||
active->push_back(pieces[i]);
|
||||
}
|
||||
}
|
||||
@@ -33,12 +33,12 @@ void P::AppendChangedIndices(
|
||||
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.pieceId[i] >= PieceId::PIECE_ID_KING) continue;
|
||||
if (dp.old_piece[i].from[perspective] != PieceSquare::PS_NONE) {
|
||||
removed->push_back(dp.old_piece[i].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]);
|
||||
if (dp.new_piece[i].from[perspective] != PieceSquare::PS_NONE) {
|
||||
added->push_back(dp.new_piece[i].from[perspective]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,7 +14,7 @@ namespace NNUE {
|
||||
|
||||
namespace Features {
|
||||
|
||||
// Feature P: BonaPiece of pieces other than balls
|
||||
// Feature P: PieceSquare of pieces other than balls
|
||||
class P {
|
||||
public:
|
||||
// feature quantity name
|
||||
@@ -22,9 +22,9 @@ class 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;
|
||||
static constexpr IndexType kDimensions = PieceSquare::PS_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;
|
||||
static constexpr IndexType kMaxActiveDimensions = PieceId::PIECE_ID_KING;
|
||||
// Timing of full calculation instead of difference calculation
|
||||
static constexpr TriggerEvent kRefreshTrigger = TriggerEvent::kNone;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user