You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: docs/AlphaDeepChess/Capitulos/AnalysisOfImprovements.tex
+3-3Lines changed: 3 additions & 3 deletions
Original file line number
Diff line number
Diff line change
@@ -9,7 +9,7 @@ \section{Profiling}
9
9
10
10
\noindent We run the engine under \texttt{perf} using the following commands:
11
11
12
-
\begin{lstlisting}[language=bash, caption={Profiling \textit{AlphaDeepChess} with perf}, frame=single, breaklines=true]
12
+
\begin{lstlisting}[language=bash, caption={Profiling \textit{AlphaDeepChess} with perf}, frame=single, breaklines=true, captionpos=b]
13
13
# Record performance data with function stack traces
14
14
sudo perf record -g ./build/release/AlphaDeepChess
15
15
@@ -19,7 +19,7 @@ \section{Profiling}
19
19
20
20
\noindent After recording, \texttt{perf report} opens an interactive terminal interface where functions are sorted by CPU overhead, allowing us to easily identify performance-critical regions.
21
21
22
-
\vspace{2em}
22
+
\vspace{1em}
23
23
24
24
\noindent First, we profile the basic architecture of the engine implemented in~\cref{cap:descripcionTrabajo}, and then evaluate it again after applying the optimizations described in~\cref{cap:ImprovementTechniques}.
\noindent The results show 48 wins, 15 draws, and 37 losses. This outcome is slightly worse than the version without reductions. A likely explanation is that the current move ordering heuristic is not strong enough, leading the search to incorrectly reduce important moves that appear late in the move list. As a result, the potential benefits of LMR are not fully realized and may even degrade search quality in some positions.
264
264
265
-
\vspace{2em}
265
+
\vspace{1em}
266
266
267
267
\noindent We can confirm that \textit{AlphaDeepChess} achieves its maximum skill level with the following configuration:
\noindent A list of twelve bitboards is used, one for each type of chess piece.~\cref{fig:bitboardPositionExample} illustrates this concept with a chess position example.
\caption{List of bitboards data structure example.}\label{fig:bitboardPositionExample}
63
61
\end{figure}
64
62
65
-
\vspace{2em}
66
-
67
63
\noindent The main advantages of bitboards is that we can operate on multiple squares simultaneously using bitwise operations. For example, we can determine if there are any black pawns on the fifth rank by performing a bitwise AND operation with the corresponding mask.
68
64
69
65
\begin{figure}[H]
@@ -104,8 +100,6 @@ \subsection*{Game state}
104
100
\item Fifty-move rule counter (moves since a capture or pawn move) (bits 35-42).
105
101
\end{enumerate}
106
102
107
-
\vspace{2em}
108
-
109
103
\noindent Having described the data structures that represent chess positions, we can now present the engine's core component: the search algorithm.
\caption{Horizon effect position example.}\label{fig:horizonEffectExample}
170
164
\end{figure}
171
165
172
-
\vspace{1em}
173
-
174
166
\noindent To avoid this, when we reach the end of the tree at maximum depth, we must extend the search but only considering capture moves until no captures are available. This is known as quiescence search~\cite{QuiescenceSearch}.
\noindent The basic material evaluation described earlier has a significant limitation, it does not consider the fact that a piece could have more power in different squares of the board. For instance, as illustrated in the following image, a knight placed in the center can control up to eight squares, while a knight positioned in the corner can reach only two.
233
224
234
-
\vspace{1em}
235
-
236
225
\begin{figure}[H]
237
226
\centering
238
227
\newchessgame
@@ -470,16 +459,12 @@ \subsection*{Bitboard of danger squares}
470
459
\caption{Example of a danger bitboard squares attacked by the black side.}\label{fig:BitboardDangers}
471
460
\end{figure}
472
461
473
-
\vspace{1em}
474
-
475
462
\noindent The danger bitboard is constructed by performing a bitwise OR operation across all legal attacks from the opponent's pieces. For non-sliding pieces such as pawns, knights, and kings, their legal attack bitboards match exactly with their precomputed attack patterns.
476
463
477
464
\vspace{1em}
478
465
479
466
\noindent However, sliding pieces as rooks, bishops, and queens require additional handling. Their attacks depend on the presence of blockers in their movement paths.~\cref{fig:blockerExample} shows an example where the attacks of sliding pieces are limited due to blocking pawns. In this case, the rook sliding attack is being blocked by the pawns.
480
467
481
-
\vspace{1em}
482
-
483
468
\begin{figure}[H]
484
469
\centering
485
470
\newchessgame
@@ -500,8 +485,6 @@ \subsection*{Bitboard of pinned pieces}
500
485
501
486
\noindent The next challenging aspect of legal move generation is handling pinned pieces. A pinned piece cannot move freely, as doing so would expose its king to check, making the move illegal. An example of a pinned piece is shown in~\cref{fig:pinnedPiece}.
502
487
503
-
\vspace{1em}
504
-
505
488
\begin{figure}[H]
506
489
\centering
507
490
\newchessgame
@@ -512,8 +495,6 @@ \subsection*{Bitboard of pinned pieces}
512
495
\caption{The black rook pins the white knight. If the knight moves, the white king could be captured, making the move illegal.}\label{fig:pinnedPiece}
513
496
\end{figure}
514
497
515
-
\vspace{1em}
516
-
517
498
\noindent We must compute a bitboard that contains all pinned pieces on the board. This allows us to restrict their movement accordingly during move generation. However, identifying pinned pieces is computationally expensive, as it requires iterating through the attack patterns of sliding pieces and checking for alignment with the king and potential blockers.
518
499
519
500
\subsection*{Capture and push mask}
@@ -590,8 +571,7 @@ \subsection*{Testing the move generator: perft test}
590
571
\caption{Perft results at depth 6: comparison between \textit{Stockfish} and \textit{AlphaDeepChess}~\cite{PerftResults}.}\label{tab:perftResults}
591
572
\end{table}
592
573
593
-
\section{Move ordering}
594
-
\label{cap:moveOrdering}
574
+
\section{Move ordering}\label{cap:moveOrdering}
595
575
Once having explained the move generator function, in this chapter we detail the implementation of the move ordering heuristic.
596
576
597
577
\vspace{1em}
@@ -640,8 +620,6 @@ \subsection*{Killer moves}
640
620
641
621
\noindent A \textit{killer move} is a quiet, non-capturing move which can cause a cutoff in different branches of the tree at the same depth~\cite{KillerMoves}.
Copy file name to clipboardExpand all lines: docs/AlphaDeepChess/Capitulos/EstadoDeLaCuestion.tex
+18-28Lines changed: 18 additions & 28 deletions
Original file line number
Diff line number
Diff line change
@@ -33,7 +33,7 @@ \section{Search algorithms}
33
33
34
34
\vspace{1em}
35
35
36
-
\begin{lstlisting}[caption={Pseudocode of the Depth-First Search algorithm~\cite{CLRS}.}, label={lst:dfs}, frame=single, numbers=left, xleftmargin=15pt]
36
+
\begin{lstlisting}[caption={Pseudocode of the Depth-First Search algorithm~\cite{CLRS}.}, label={lst:dfs}, frame=single, numbers=left, xleftmargin=15pt, captionpos=b]
37
37
Procedure DFS(Graph G, Node v):
38
38
Mark v as visited
39
39
For each neighbor w of v in G.adjacentEdges(v):
@@ -53,7 +53,7 @@ \section{Search algorithms}
53
53
54
54
\vspace{1em}
55
55
56
-
\begin{lstlisting}[caption={Pseudocode of the Best-First Search algorithm~\cite{Pearl1984}.}, frame=single, numbers=left, xleftmargin=10pt, breaklines=true]
56
+
\begin{lstlisting}[caption={Pseudocode of the Best-First Search algorithm~\cite{Pearl1984}.}, frame=single, numbers=left, xleftmargin=10pt, breaklines=true, captionpos=b]
\begin{lstlisting}[caption={Pseudocode of the Minimax algorithm~\cite{Russell2021artificial}.}, label={lst:minimax}, frame=single, numbers=left, xleftmargin=15pt, breaklines=true]
90
+
\begin{lstlisting}[caption={Pseudocode of the Minimax algorithm~\cite{Russell2021artificial}.}, label={lst:minimax}, frame=single, numbers=left, xleftmargin=15pt, breaklines=true, captionpos=b]
\noindent For example, let's say that white always wants the highest value (maximizing the result), while black wants the lowest value (minimizing the result). In~\cref{fig:minimax}, white is represented by square nodes and black by circle nodes. Note that this example is a binary tree, but in a real scenario there would likely be more moves or nodes, because in chess each position usually allows a wide range of legal moves, not just two as in a binary tree. For the leftmost pair of leaf nodes with values of 3 and 5, 3 is chosen because black tries to get the lowest score between them. Then, for the other pair of leaf nodes with values of 2 and 9, 2 is chosen for the same reason. Lastly, at the root node, white selects 3 as the maximum value between 3 and 2.
Minimax has the problem that a lot of the node evaluation is redundant, because we can know beforehand that some branches will not affect the final decision. For that purpose, we can enhance the search with the \textit{alpha-beta pruning} technique.
\noindent Having described the main search algorithms, it is important to explain how the skill of both human and computer chess players is measured. Next, we describe the console communication protocol used by chess engines, and finally, we provide an overview of how \textit{Stockfish} operates internally.
382
380
383
-
\section{ELO rating system}
381
+
\section{Elo rating system}
384
382
385
383
The Elo rating system, developed by \textit{Arpad Elo} in the 1960s, is a method used to calculate the relative skill levels of players in two-player games such as chess~\cite{Elo}. It was adopted by the FIDE in 1970 as the main rating system for all federated players.
386
384
@@ -422,10 +420,7 @@ \section{ELO rating system}
422
420
423
421
This system ensures that a player gains more rating points for defeating a higher-rated opponent and loses fewer points when losing to a stronger player.
424
422
425
-
\newpage
426
-
427
-
\section{UCI}
428
-
\label{sec:uci}
423
+
\section{UCI}\label{sec:uci}
429
424
430
425
\noindent The chess community has developed an standard console protocol for chess engines to facilitate interoperability between engines and external applications. The \textit{Universal Chess Interface} (UCI)~\cite{UciProtocol} makes it possible to organize games and tournaments between different bots, as well as to integrate engines into graphical user interfaces (GUIs) and other software tools.
431
426
@@ -451,33 +446,29 @@ \section{UCI}
451
446
\item\texttt{stop}: stop calculating.
452
447
\end{itemize}
453
448
454
-
\newpage
455
-
456
-
Now that we have covered the fundamental concepts behind chess engines, in the following section we present the most powerful and widely used chess engine.
449
+
\noindent Now that we have covered the fundamental concepts behind chess engines, in the following section we present the most powerful and widely used chess engine.
457
450
458
-
\section{\textit{Stockfish}}
459
-
\label{sec:stockfish}
451
+
\section{\textit{Stockfish}}\label{sec:stockfish}
460
452
461
-
\par\textit{Stockfish} is an open-source chess engine that has consistently ranked among the strongest in the world~\cite{Stockfish}. It is written in C++ and released under the GNU General Public License (GPL). \textit{Stockfish} has been developed and refined by a large community of contributors.
453
+
\noindent\textit{Stockfish} is an open-source chess engine that has consistently ranked among the strongest in the world~\cite{Stockfish}. It is written in C++ and released under the GNU General Public License (GPL). \textit{Stockfish} has been developed and refined by a large community of contributors.
462
454
463
455
\vspace{1em}
464
456
465
-
\par\textit{Stockfish} has an estimated Elo rating of around 3644~\cite{StockfishElo}, placing it far above the best human player, Magnus Carlsen, whose peak Elo rating was 2882 in May 2014~\cite{MagnusCarlsenElo}.
457
+
\noindent\textit{Stockfish} has an estimated Elo rating of around 3644~\cite{StockfishElo}, placing it far above the best human player, Magnus Carlsen, whose peak Elo rating was 2882 in May 2014~\cite{MagnusCarlsenElo}.
466
458
467
459
\vspace{1em}
468
460
469
-
\par It is based on the minimax search algorithm, enhanced with alpha-beta pruning. In addition, it incorporates several of the techniques described in later chapters (see Chapter~\cref{cap:descripcionTrabajo}).
461
+
\noindent It is based on the minimax search algorithm, enhanced with alpha-beta pruning. In addition, it incorporates several of the techniques described in later chapters (see Chapter~\cref{cap:descripcionTrabajo}).
470
462
471
463
\vspace{1em}
472
464
473
465
\par The key component of \textit{Stockfish}'s strength is its use of machine learning algorithms to evaluate chess positions more accurately, in particular, \textit{Stockfish} uses NNUE (Efficiently Updatable Neural Network), a neural network architecture originally developed for shogi engines and later adapted for chess~\cite{NNUE}. NNUE efficiently evaluates positions by finding and learning complex piece patterns. It is optimized to run quickly even on CPUs and significantly improves move ordering (see Chapter~\cref{cap:moveOrdering}), allowing the engine to explore the most promising lines first and prune large parts of the search tree.
474
466
475
-
\vspace{2em}
467
+
\vspace{1em}
476
468
477
469
In the following section, we describe one of the most popular platforms where both humans and chess engines play competitively.
478
470
479
-
\section{\textit{Lichess}}
480
-
\label{sec:lichess}
471
+
\section{\textit{Lichess}}\label{sec:lichess}
481
472
482
473
\textit{Lichess} is a free and open-source online chess platform that offers a wide range of features for both casual and competitive players. It was created by Thibault Duplessis in 2010 and has since grown into one of the most popular chess websites in the world, hosting millions of games each day~\cite{Lichess}.
483
474
@@ -493,12 +484,11 @@ \section{\textit{Lichess}}
493
484
494
485
\noindent\textit{Lichess} also supports chess engines and bots through the \textit{Lichess} Bot API, enabling integration with engines like \textit{Stockfish}. It is often used for engine testing, AI competitions, and research purposes. Many developers and researchers use the \textit{Lichess} platform as a benchmark or interface for evaluating engine performance.
495
486
496
-
\vspace{2em}
487
+
\vspace{1em}
497
488
498
-
Finally, the chess community uses specialized tools to evaluate the relative playing strength of chess engines. One of the most widely used tools for this purpose is \textit{Cutechess}.
489
+
\noindentFinally, the chess community uses specialized tools to evaluate the relative playing strength of chess engines. One of the most widely used tools for this purpose is \textit{Cutechess}.
499
490
500
-
\section{\textit{Cutechess}}
501
-
\label{sec:cutechess}
491
+
\section{\textit{Cutechess}}\label{sec:cutechess}
502
492
503
493
\noindent\textit{Cutechess} is an open-source tool widely adopted in the chess programming community. It allows users to run automated matches between engines, compare their performance, and analyze gameplay~\cite{CuteChess}.
504
494
@@ -512,9 +502,9 @@ \section{\textit{Cutechess}}
512
502
513
503
\vspace{1em}
514
504
515
-
\noindent Then, it checks the active status of each engine and manages the start of the games by setting up the board on both engines with the \texttt{position} command. Afterwards, it sends the \texttt{go} command and stops the search with \texttt{stop} when the search time or depth is reached, extracting the best move provided by the engine whose turn it is. This move is then passed to the other engine, alternating turns so that both engines play against each other automatically.~\cref{lst:cutechess-example} we show a \textit{Cutechess} log file, we directly configured the starting positions from a list of FENs in the \texttt{positions.fen} file:
505
+
\noindent Then, it manages the games by setting up the board with the \texttt{position} command, sending \texttt{go} to start the search, and stopping when the search time or depth is reached. Moves are alternated between engines so they play against each other automatically. In~\cref{lst:cutechess-example}, we show a \textit{Cutechess} log file, where the starting positions are taken directly from a list of FENs in the \texttt{positions.fen} file.
516
506
517
-
\begin{lstlisting}[basicstyle=\ttfamily\scriptsize, breaklines=true, frame=single, caption={Example of \textit{Cutechess}}, label={lst:cutechess-example}]
507
+
\begin{lstlisting}[basicstyle=\ttfamily\scriptsize, breaklines=true, frame=single, captionpos=b, caption={Example of \textit{Cutechess}}, label={lst:cutechess-example}]
518
508
Running test (8) with the following configuration:
>AlphaDeepChess(0): position fen rnbqkb1r/1p2pppp/p2p1n2/8/3NP3/2N5/PPP2PPP/R1BQKB1R w KQkq - 0 6 moves c1g5 e7e6
557
547
\end{lstlisting}
558
548
559
-
\noindent In~\cref{lst:cutechess-example}, in addition to setting the number of games to $1$, the search time to $5$ seconds, and the search depth to $5$, we provided a list of starting positions, from which one is chosen at random. Each line starting with \texttt{position fen \ldots} establishes the FEN position and continues by adding the moves played.
549
+
\noindent In~\cref{lst:cutechess-example}, we set the number of games to $1$, the search time to $5$ seconds, and the search depth to $5$. We also provided a list of starting positions, from which one is chosen at random. Each line starting with \texttt{position fen \ldots} sets the FEN position and adds the moves played.
\noindent Taking advantage of dynamic programming, we create a look-up table of chess positions and its evaluation. So if we encounter the same position again, the evaluation is already precalculated. However, we ask ourselves the following question: how much space does the look-up table take up if there are an astronomical amount of chess positions? What we can do is assign a hash to each position and make the table index the last bits of the hash. The larger the table, the less likely access collisions will be. We also want a hash that is fast to calculate and has collision-reducing properties.
36
36
~\cite{TranspositionTable}
37
37
38
-
\vspace{2em}
38
+
\vspace{1em}
39
39
40
40
\noindent\parbox{\textwidth}{The complete implementation can be found in\\\texttt{include\textbackslash{}utilities\textbackslash{}transposition\_table.hpp}.}
0 commit comments