1
0
Fork 0
mirror of https://github.com/sockspls/badfish synced 2025-05-01 17:19:36 +00:00

Fixed compile errors.

This commit is contained in:
Hisayori Noda 2019-06-15 17:08:47 +09:00
parent 9964fbbe25
commit b330602cdc
18 changed files with 336 additions and 22 deletions

View file

@ -1,10 +1,12 @@
// NNUE評価関数の計算に関するコード
#include <fstream>
#include <iostream>
#include "../../evaluate.h"
#include "../../position.h"
#include "../../misc.h"
#include "../../uci.h"
#include "evaluate_nnue.h"
@ -263,7 +265,7 @@ Value compute_eval(const Position& pos) {
}
// 評価関数
Value evaluate(const Position& pos) {
Value NNUE::evaluate(const Position& pos) {
const auto& accumulator = pos.state()->accumulator;
if (accumulator.computed_score) {
return accumulator.score;

View file

@ -55,6 +55,8 @@ bool ReadParameters(std::istream& stream);
// 評価関数パラメータを書き込む
bool WriteParameters(std::ostream& stream);
Value evaluate(const Position& pos);
} // namespace NNUE
} // namespace Eval

View file

@ -71,7 +71,7 @@ class FeatureSetBase {
template <typename IndexListType>
static void AppendActiveIndices(
const Position& pos, TriggerEvent trigger, IndexListType active[2]) {
for (const auto perspective : COLOR) {
for (const auto perspective : Colors) {
Derived::CollectActiveIndices(
pos, trigger, perspective, &active[perspective]);
}
@ -85,7 +85,7 @@ class FeatureSetBase {
const auto& dp = pos.state()->dirtyPiece;
if (dp.dirty_num == 0) return;
for (const auto perspective : COLOR) {
for (const auto perspective : Colors) {
reset[perspective] = false;
switch (trigger) {
case TriggerEvent::kNone:
@ -105,7 +105,7 @@ class FeatureSetBase {
reset[perspective] = true;
break;
default:
ASSERT_LV5(false);
assert(false);
break;
}
if (reset[perspective]) {

View file

@ -28,7 +28,7 @@ inline void HalfKP<AssociatedKing>::GetPieces(
const PieceNumber target = (AssociatedKing == Side::kFriend) ?
static_cast<PieceNumber>(PIECE_NUMBER_KING + perspective) :
static_cast<PieceNumber>(PIECE_NUMBER_KING + ~perspective);
*sq_target_k = static_cast<Square>(((*pieces)[target] - f_king) % SQ_NB);
*sq_target_k = static_cast<Square>(((*pieces)[target] - f_king) % SQUARE_NB);
}
// 特徴量のうち、値が1であるインデックスのリストを取得する

View file

@ -26,7 +26,7 @@ class HalfKP {
0x5D69D5B9u ^ (AssociatedKing == Side::kFriend);
// 特徴量の次元数
static constexpr IndexType kDimensions =
static_cast<IndexType>(SQ_NB) * static_cast<IndexType>(fe_end);
static_cast<IndexType>(SQUARE_NB) * static_cast<IndexType>(fe_end);
// 特徴量のうち、同時に値が1となるインデックスの数の最大値
static constexpr IndexType kMaxActiveDimensions = PIECE_NUMBER_KING;
// 差分計算の代わりに全計算を行うタイミング

View file

@ -17,8 +17,8 @@ inline IndexType HalfRelativeKP<AssociatedKing>::MakeIndex(
Square sq_k, BonaPiece p) {
constexpr IndexType W = kBoardWidth;
constexpr IndexType H = kBoardHeight;
const IndexType piece_index = (p - fe_hand_end) / SQ_NB;
const Square sq_p = static_cast<Square>((p - fe_hand_end) % SQ_NB);
const IndexType piece_index = (p - fe_hand_end) / SQUARE_NB;
const Square sq_p = static_cast<Square>((p - fe_hand_end) % SQUARE_NB);
const IndexType relative_file = file_of(sq_p) - file_of(sq_k) + (W / 2);
const IndexType relative_rank = rank_of(sq_p) - rank_of(sq_k) + (H / 2);
return H * W * piece_index + H * relative_file + relative_rank;
@ -35,7 +35,7 @@ inline void HalfRelativeKP<AssociatedKing>::GetPieces(
const PieceNumber target = (AssociatedKing == Side::kFriend) ?
static_cast<PieceNumber>(PIECE_NUMBER_KING + perspective) :
static_cast<PieceNumber>(PIECE_NUMBER_KING + ~perspective);
*sq_target_k = static_cast<Square>(((*pieces)[target] - f_king) % SQ_NB);
*sq_target_k = static_cast<Square>(((*pieces)[target] - f_king) % SQUARE_NB);
}
// 特徴量のうち、値が1であるインデックスのリストを取得する

View file

@ -25,7 +25,7 @@ class HalfRelativeKP {
static constexpr std::uint32_t kHashValue =
0xF9180919u ^ (AssociatedKing == Side::kFriend);
// 玉を除いた駒種
static constexpr IndexType kNumPieceKinds = (fe_end - fe_hand_end) / SQ_NB;
static constexpr IndexType kNumPieceKinds = (fe_end - fe_hand_end) / SQUARE_NB;
// 玉を中央に置いた仮想的な盤の幅
static constexpr IndexType kBoardWidth = FILE_NB * 2 - 1;
// 玉を中央に置いた仮想的な盤の高さ

View file

@ -20,8 +20,8 @@ void K::AppendActiveIndices(
const BonaPiece* pieces = (perspective == BLACK) ?
pos.eval_list()->piece_list_fb() :
pos.eval_list()->piece_list_fw();
ASSERT_LV5(pieces[PIECE_NUMBER_BKING] != BONA_PIECE_ZERO);
ASSERT_LV5(pieces[PIECE_NUMBER_WKING] != BONA_PIECE_ZERO);
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);
}

View file

@ -22,7 +22,7 @@ class K {
// 評価関数ファイルに埋め込むハッシュ値
static constexpr std::uint32_t kHashValue = 0xD3CEE169u;
// 特徴量の次元数
static constexpr IndexType kDimensions = SQ_NB * 2;
static constexpr IndexType kDimensions = SQUARE_NB * 2;
// 特徴量のうち、同時に値が1となるインデックスの数の最大値
static constexpr IndexType kMaxActiveDimensions = 2;
// 差分計算の代わりに全計算を行うタイミング

View file

@ -3,8 +3,6 @@
#ifndef _NNUE_ACCUMULATOR_H_
#define _NNUE_ACCUMULATOR_H_
#include "../../config.h"
#if defined(EVAL_NNUE)
#include "nnue_architecture.h"

View file

@ -8,6 +8,7 @@
// 入力特徴量とネットワーク構造が定義されたヘッダをincludeする
// KP256型を使いたいときは、これを事前にdefineする。
#define EVAL_NNUE_KP256
#if defined(EVAL_NNUE_KP256)
#include "architectures/k-p_256x2-32-32.h"
#else // #if defined(EVAL_NNUE_HALFKP256)

View file

@ -142,9 +142,9 @@ class FeatureTransformer {
}
#else
for (IndexType j = 0; j < kHalfDimensions; ++j) {
BiasType sum = accumulation[perspectives[p]][0][j];
BiasType sum = accumulation[static_cast<int>(perspectives[p])][0][j];
for (IndexType i = 1; i < kRefreshTriggers.size(); ++i) {
sum += accumulation[perspectives[p]][i][j];
sum += accumulation[static_cast<int>(perspectives[p])][i][j];
}
output[offset + j] = static_cast<OutputType>(
std::max<int>(0, std::min<int>(127, sum)));
@ -161,7 +161,7 @@ class FeatureTransformer {
Features::IndexList active_indices[2];
RawFeatures::AppendActiveIndices(pos, kRefreshTriggers[i],
active_indices);
for (const auto perspective : COLOR) {
for (const auto perspective : Colors) {
if (i == 0) {
std::memcpy(accumulator.accumulation[perspective][i], biases_,
kHalfDimensions * sizeof(BiasType));
@ -217,7 +217,7 @@ class FeatureTransformer {
bool reset[2];
RawFeatures::AppendChangedIndices(pos, kRefreshTriggers[i],
removed_indices, added_indices, reset);
for (const auto perspective : COLOR) {
for (const auto perspective : Colors) {
#if defined(USE_AVX2)
constexpr IndexType kNumChunks = kHalfDimensions / (kSimdWidth / 2);
auto accumulation = reinterpret_cast<__m256i*>(

View file

@ -43,7 +43,7 @@ class Factorizer<HalfKP<AssociatedKing>> {
// kFeaturesHalfKP
{true, FeatureType::kDimensions},
// kFeaturesHalfK
{true, SQ_NB},
{true, SQUARE_NB},
// kFeaturesP
{true, Factorizer<P>::GetDimensions()},
// kFeaturesHalfRelativeKP

View file

@ -34,6 +34,181 @@ constexpr Value Tempo = Value(28); // Must be visible to search
std::string trace(const Position& pos);
Value evaluate(const Position& pos);
// --- 評価関数で使う定数 KPP(玉と任意2駒)のPに相当するenum
// (評価関数の実験のときには、BonaPieceは自由に定義したいのでここでは定義しない。)
// BonanzaでKKP/KPPと言うときのP(Piece)を表現する型。
// Σ KPPを求めるときに、39の地点の歩のように、升×駒種に対して一意な番号が必要となる。
enum BonaPiece : int32_t
{
// f = friend(≒先手)の意味。e = enemy(≒後手)の意味
// 未初期化の時の値
BONA_PIECE_NOT_INIT = -1,
// 無効な駒。駒落ちのときなどは、不要な駒をここに移動させる。
BONA_PIECE_ZERO = 0,
fe_hand_end = BONA_PIECE_ZERO + 1,
// Bonanzaのように盤上のありえない升の歩や香の番号を詰めない。
// 理由1) 学習のときに相対PPで1段目に香がいるときがあって、それを逆変換において正しく表示するのが難しい。
// 理由2) 縦型BitboardだとSquareからの変換に困る。
// --- 盤上の駒
f_pawn = fe_hand_end,
e_pawn = f_pawn + SQUARE_NB,
f_knight = e_pawn + SQUARE_NB,
e_knight = f_knight + SQUARE_NB,
f_bishop = e_knight + SQUARE_NB,
e_bishop = f_bishop + SQUARE_NB,
f_rook = e_bishop + SQUARE_NB,
e_rook = f_rook + SQUARE_NB,
f_queen = e_rook + SQUARE_NB,
e_queen = f_queen + SQUARE_NB,
fe_end = e_queen + SQUARE_NB,
f_king = fe_end,
e_king = f_king + SQUARE_NB,
fe_end2 = e_king + SQUARE_NB, // 玉も含めた末尾の番号。
};
// BonaPieceを後手から見たとき(先手の39の歩を後手から見ると後手の71の歩)の番号とを
// ペアにしたものをExtBonaPiece型と呼ぶことにする。
union ExtBonaPiece
{
struct {
BonaPiece fw; // from white
BonaPiece fb; // from black
};
BonaPiece from[2];
ExtBonaPiece() {}
ExtBonaPiece(BonaPiece fw_, BonaPiece fb_) : fw(fw_), fb(fb_) {}
};
// 駒が今回の指し手によってどこからどこに移動したのかの情報。
// 駒はExtBonaPiece表現であるとする。
struct ChangedBonaPiece
{
ExtBonaPiece old_piece;
ExtBonaPiece new_piece;
};
// KPPテーブルの盤上の駒pcに対応するBonaPieceを求めるための配列。
// 例)
// BonaPiece fb = kpp_board_index[pc].fb + sq; // 先手から見たsqにあるpcに対応するBonaPiece
// BonaPiece fw = kpp_board_index[pc].fw + sq; // 後手から見たsqにあるpcに対応するBonaPiece
extern ExtBonaPiece kpp_board_index[PIECE_NB];
// 評価関数で用いる駒リスト。どの駒(PieceNumber)がどこにあるのか(BonaPiece)を保持している構造体
struct EvalList
{
// 評価関数(FV38型)で用いる駒番号のリスト
BonaPiece* piece_list_fw() const { return const_cast<BonaPiece*>(pieceListFw); }
BonaPiece* piece_list_fb() const { return const_cast<BonaPiece*>(pieceListFb); }
// 指定されたpiece_noの駒をExtBonaPiece型に変換して返す。
ExtBonaPiece bona_piece(PieceNumber piece_no) const
{
ExtBonaPiece bp;
bp.fw = pieceListFw[piece_no];
bp.fb = pieceListFb[piece_no];
return bp;
}
// 盤上のsqの升にpiece_noのpcの駒を配置する
void put_piece(PieceNumber piece_no, Square sq, Piece pc) {
set_piece_on_board(piece_no, BonaPiece(kpp_board_index[pc].fw + sq), BonaPiece(kpp_board_index[pc].fb + inverse(sq)), sq);
}
// 盤上のある升sqに対応するPieceNumberを返す。
PieceNumber piece_no_of_board(Square sq) const { return piece_no_list_board[sq]; }
// pieceListを初期化する。
// 駒落ちに対応させる時のために、未使用の駒の値はBONA_PIECE_ZEROにしておく。
// 通常の評価関数を駒落ちの評価関数として流用できる。
// piece_no_listのほうはデバッグが捗るようにPIECE_NUMBER_NBで初期化。
void clear()
{
for (auto& p : pieceListFw)
p = BONA_PIECE_ZERO;
for (auto& p : pieceListFb)
p = BONA_PIECE_ZERO;
for (auto& v : piece_no_list_board)
v = PIECE_NUMBER_NB;
}
// list長が可変のときは、add()/remove()をサポートする。
// DirtyPieceのほうから呼び出される。
// listにadd()する。
void add(BonaPiece fb);
// listからremoveする。
void remove(BonaPiece fb);
// 内部で保持しているpieceListFb[]が正しいBonaPieceであるかを検査する。
// 注 : デバッグ用。遅い。
bool is_valid(const Position& pos);
protected:
// 盤上sqにあるpiece_noの駒のBonaPieceがfb,fwであることを設定する。
inline void set_piece_on_board(PieceNumber piece_no, BonaPiece fw, BonaPiece fb, Square sq)
{
assert(is_ok(piece_no));
pieceListFw[piece_no] = fw;
pieceListFb[piece_no] = fb;
piece_no_list_board[sq] = piece_no;
}
// 駒リスト。駒番号(PieceNumber)いくつの駒がどこにあるのか(BonaPiece)を示す。FV38などで用いる。
// 駒リストの長さ
// 38固定
public:
int length() const { return PIECE_NUMBER_KING; }
// VPGATHERDDを使う都合、4の倍数でなければならない。
// また、KPPT型評価関数などは、39,40番目の要素がゼロであることを前提とした
// アクセスをしている箇所があるので注意すること。
static const int MAX_LENGTH = 40;
private:
BonaPiece pieceListFw[MAX_LENGTH];
BonaPiece pieceListFb[MAX_LENGTH];
// 盤上の駒に対して、その駒番号(PieceNumber)を保持している配列
// 玉がSQ_NBに移動しているとき用に+1まで保持しておくが、
// SQ_NBの玉を移動させないので、この値を使うことはないはず。
PieceNumber piece_no_list_board[SQUARE_NB_PLUS1];
};
// 評価値の差分計算の管理用
// 前の局面から移動した駒番号を管理するための構造体
// 動く駒は、最大で2個。
struct DirtyPiece
{
// その駒番号の駒が何から何に変わったのか
Eval::ChangedBonaPiece changed_piece[2];
// dirtyになった駒番号
PieceNumber pieceNo[2];
// dirtyになった個数。
// null moveだと0ということもありうる。
// 動く駒と取られる駒とで最大で2つ。
int dirty_num;
};
}
#endif // #ifndef EVALUATE_H_INCLUDED

View file

@ -315,3 +315,19 @@ void bindThisThread(size_t idx) {
#endif
} // namespace WinProcGroup
void sleep(int ms)
{
std::this_thread::sleep_for(std::chrono::milliseconds(ms));
}
void* aligned_malloc(size_t size, size_t align)
{
void* p = _mm_malloc(size, align);
if (p == nullptr)
{
std::cout << "info string can't allocate memory. sise = " << size << std::endl;
exit(1);
}
return p;
}

View file

@ -21,6 +21,7 @@
#ifndef MISC_H_INCLUDED
#define MISC_H_INCLUDED
#include <algorithm>
#include <cassert>
#include <chrono>
#include <ostream>
@ -110,4 +111,69 @@ namespace WinProcGroup {
void bindThisThread(size_t idx);
}
// 指定されたミリ秒だけsleepする。
extern void sleep(int ms);
// 途中での終了処理のためのwrapper
static void my_exit()
{
sleep(3000); // エラーメッセージが出力される前に終了するのはまずいのでwaitを入れておく。
exit(EXIT_FAILURE);
}
// --------------------
// Math
// --------------------
// 進行度の計算や学習で用いる数学的な関数
namespace Math {
// シグモイド関数
// = 1.0 / (1.0 + std::exp(-x))
double sigmoid(double x);
// シグモイド関数の微分
// = sigmoid(x) * (1.0 - sigmoid(x))
double dsigmoid(double x);
// vを[lo,hi]の間に収まるようにクリップする。
// ※ Stockfishではこの関数、bitboard.hに書いてある。
template<class T> constexpr const T& clamp(const T& v, const T& lo, const T& hi) {
return v < lo ? lo : v > hi ? hi : v;
}
}
// --------------------
// Path
// --------------------
// C#にあるPathクラス的なもの。ファイル名の操作。
// C#のメソッド名に合わせておく。
struct Path
{
// path名とファイル名を結合して、それを返す。
// folder名のほうは空文字列でないときに、末尾に'/'か'\\'がなければそれを付与する。
static std::string Combine(const std::string& folder, const std::string& filename)
{
if (folder.length() >= 1 && *folder.rbegin() != '/' && *folder.rbegin() != '\\')
return folder + "/" + filename;
return folder + filename;
}
// full path表現から、(フォルダ名を除いた)ファイル名の部分を取得する。
static std::string GetFileName(const std::string& path)
{
// "\"か"/"か、どちらを使ってあるかはわからない。
auto path_index1 = path.find_last_of("\\") + 1;
auto path_index2 = path.find_last_of("/") + 1;
auto path_index = std::max(path_index1, path_index2);
return path.substr(path_index);
}
};
extern void* aligned_malloc(size_t size, size_t align);
static void aligned_free(void* ptr) { _mm_free(ptr); }
#endif // #ifndef MISC_H_INCLUDED

View file

@ -29,6 +29,8 @@
#include "bitboard.h"
#include "types.h"
#include "eval/nnue/nnue_accumulator.h"
/// StateInfo struct stores information needed to restore a Position object to
/// its previous state when we retract a move. Whenever a move is made on the
@ -54,6 +56,11 @@ struct StateInfo {
Bitboard blockersForKing[COLOR_NB];
Bitboard pinners[COLOR_NB];
Bitboard checkSquares[PIECE_TYPE_NB];
Eval::NNUE::Accumulator accumulator;
// 評価値の差分計算の管理用
Eval::DirtyPiece dirtyPiece;
};
/// A list to keep track of the position states along the setup moves (from the
@ -165,6 +172,15 @@ public:
bool pos_is_ok() const;
void flip();
// --- StateInfo
// 現在の局面に対応するStateInfoを返す。
// たとえば、state()->capturedPieceであれば、前局面で捕獲された駒が格納されている。
StateInfo* state() const { return st; }
// 評価関数で使うための、どの駒番号の駒がどこにあるかなどの情報。
const Eval::EvalList* eval_list() const { return &evalList; }
private:
// Initialization helpers (used while setting up a position)
void set_castling_right(Color c, Square rfrom);
@ -194,6 +210,9 @@ private:
Thread* thisThread;
StateInfo* st;
bool chess960;
// 評価関数で用いる駒のリスト
Eval::EvalList evalList;
};
namespace PSQT {

View file

@ -131,6 +131,8 @@ enum Color {
WHITE, BLACK, COLOR_NB = 2
};
constexpr Color Colors[2] = { WHITE, BLACK };
enum CastlingSide {
KING_SIDE, QUEEN_SIDE, CASTLING_SIDE_NB = 2
};
@ -186,7 +188,10 @@ enum Value : int {
RookValueMg = 1289, RookValueEg = 1378,
QueenValueMg = 2529, QueenValueEg = 2687,
MidgameLimit = 15258, EndgameLimit = 3915
MidgameLimit = 15258, EndgameLimit = 3915,
// 評価関数の返す値の最大値(2**14ぐらいに収まっていて欲しいところだが..)
VALUE_MAX_EVAL = 27000,
};
enum PieceType {
@ -230,7 +235,8 @@ enum Square : int {
SQ_A8, SQ_B8, SQ_C8, SQ_D8, SQ_E8, SQ_F8, SQ_G8, SQ_H8,
SQ_NONE,
SQUARE_NB = 64
SQUARE_NB = 64,
SQUARE_NB_PLUS1 = SQUARE_NB + 1, // 玉がいない場合、SQ_NBに移動したものとして扱うため、配列をSQ_NB+1で確保しないといけないときがあるのでこの定数を用いる。
};
enum Direction : int {
@ -356,6 +362,10 @@ constexpr Square operator~(Square s) {
return Square(s ^ SQ_A8); // Vertical flip SQ_A1 -> SQ_A8
}
constexpr Square inverse(Square s) {
return static_cast<Square>(static_cast<int>(SQUARE_NB) - s - 1);
}
constexpr File operator~(File f) {
return File(f ^ FILE_H); // Horizontal flip FILE_A -> FILE_H
}
@ -454,4 +464,29 @@ constexpr bool is_ok(Move m) {
return from_sq(m) != to_sq(m); // Catch MOVE_NULL and MOVE_NONE
}
// --------------------
// 駒箱
// --------------------
// Positionクラスで用いる、駒リスト(どの駒がどこにあるのか)を管理するときの番号。
enum PieceNumber : int8_t
{
PIECE_NUMBER_PAWN = 0,
PIECE_NUMBER_KNIGHT = 16,
PIECE_NUMBER_BISHOP = 20,
PIECE_NUMBER_ROOK = 24,
PIECE_NUMBER_QUEEN = 28,
PIECE_NUMBER_KING = 30,
PIECE_NUMBER_WKING = 30,
PIECE_NUMBER_BKING = 31, // 先手、後手の玉の番号が必要な場合はこっちを用いる
PIECE_NUMBER_ZERO = 0,
PIECE_NUMBER_NB = 32,
};
inline PieceNumber& operator++(PieceNumber& d) { return d = PieceNumber(int(d) + 1); } \
inline PieceNumber& operator--(PieceNumber& d) { return d = PieceNumber(int(d) - 1); }
// PieceNumberの整合性の検査。assert用。
constexpr bool is_ok(PieceNumber pn) { return pn < PIECE_NUMBER_NB; }
#endif // #ifndef TYPES_H_INCLUDED