From 6724aeb3ba98c1b9f042344734c2d683e79dfc64 Mon Sep 17 00:00:00 2001 From: InigoGutierrez Date: Wed, 29 Jun 2022 23:23:09 +0200 Subject: Made full class diagram. --- .gitignore | 1 + doc/Makefile | 8 +- doc/diagrams/ASTNode.pumlc | 12 ++- doc/diagrams/ConvNeuralNetwork.pumlc | 7 ++ doc/diagrams/DecisionAlgorithm.pumlc | 5 +- doc/diagrams/DenseNeuralNetwork.pumlc | 7 ++ doc/diagrams/GameBoard.pumlc | 37 ++++---- doc/diagrams/GameEngine.pumlc | 18 ++++ doc/diagrams/GameMove.pumlc | 29 ++++--- doc/diagrams/GameState.pumlc | 18 ++-- doc/diagrams/ImagoIO.pumlc | 10 +++ doc/diagrams/Keras.pumlc | 3 + doc/diagrams/MCTS.pumlc | 11 +++ doc/diagrams/MCTSNode.pumlc | 18 ++++ doc/diagrams/NeuralNetwork.pumlc | 9 +- doc/diagrams/Property.pumlc | 10 +++ doc/diagrams/SGF.pumlc | 5 +- doc/diagrams/analysisClasses.puml | 2 +- doc/diagrams/engineModule.puml | 32 +++++++ doc/diagrams/fullClasses.puml | 16 ++++ doc/diagrams/gameModule.puml | 18 ++++ doc/diagrams/gtpEngine.puml | 36 -------- doc/diagrams/skinparams.puml | 7 ++ doc/diagrams/trainingModule.puml | 20 +++++ doc/tex/biber.bib | 18 ++++ doc/tex/implementation.tex | 140 +++++++++++-------------------- doc/tex/systemDesign.tex | 93 ++++++++++++++++++++ doc/tex/tfg.tex | 10 ++- go.py | 2 - imago/data/enums.py | 5 ++ imago/engine/decisionAlgorithmFactory.py | 5 -- imago/engine/keras/neuralNetwork.py | 10 +-- imago/gameLogic/gameState.py | 4 +- 33 files changed, 429 insertions(+), 197 deletions(-) create mode 100644 doc/diagrams/ConvNeuralNetwork.pumlc create mode 100644 doc/diagrams/DenseNeuralNetwork.pumlc create mode 100644 doc/diagrams/GameEngine.pumlc create mode 100644 doc/diagrams/ImagoIO.pumlc create mode 100644 doc/diagrams/MCTS.pumlc create mode 100644 doc/diagrams/MCTSNode.pumlc create mode 100644 doc/diagrams/Property.pumlc create mode 100644 doc/diagrams/engineModule.puml create mode 100644 doc/diagrams/fullClasses.puml create mode 100644 doc/diagrams/gameModule.puml delete mode 100644 doc/diagrams/gtpEngine.puml create mode 100644 doc/diagrams/trainingModule.puml diff --git a/.gitignore b/.gitignore index 46fefef..47e0340 100644 --- a/.gitignore +++ b/.gitignore @@ -9,6 +9,7 @@ *.pdf doc/out/ doc/diagrams/*.png +_minted-tfg/ # src __pycache__/ diff --git a/doc/Makefile b/doc/Makefile index e849a01..497e9b1 100644 --- a/doc/Makefile +++ b/doc/Makefile @@ -3,17 +3,17 @@ docName = tfg outputFolder = out -texFiles = tex/tfg.tex tex/introduction.tex tex/planification.tex tex/implementation.tex tex/systemAnalysis.tex tex/systemDesign.tex tex/biber.bib +texFiles = tex/tfg.tex tex/introduction.tex tex/planification.tex tex/implementation.tex tex/systemAnalysis.tex tex/biber.bib Makefile -diagramImgs = diagrams/gameRepresentation.png diagrams/gtpEngine.png diagrams/modules.png diagrams/planificationWorkPlanEngine.png diagrams/planificationWorkPlanGame.png diagrams/sgfModule.png diagrams/useCases.png diagrams/analysisClasses.png diagrams/useCase_generateAMove.png diagrams/useCase_useAsBackend.png diagrams/useCase_playAMatch.png diagrams/interfaces.png +diagramImgs = diagrams/gameRepresentation.png diagrams/planificationWorkPlanEngine.png diagrams/planificationWorkPlanGame.png diagrams/sgfModule.png diagrams/useCases.png diagrams/analysisClasses.png diagrams/useCase_generateAMove.png diagrams/useCase_useAsBackend.png diagrams/useCase_playAMatch.png diagrams/interfaces.png diagrams/engineModule.png diagrams/modules.png diagrams/fullClasses.png all: $(docName).pdf $(docName).pdf: $(texFiles) $(diagramImgs) [ -d $(outputFolder) ] || mkdir $(outputFolder) - xelatex -output-directory $(outputFolder) tex/$(docName).tex + xelatex -shell-escape -output-directory $(outputFolder) tex/$(docName).tex biber $(outputFolder)/$(docName) - xelatex -output-directory $(outputFolder) tex/$(docName).tex + xelatex -shell-escape -output-directory $(outputFolder) tex/$(docName).tex mv $(outputFolder)/$(docName).pdf . .puml.png: diff --git a/doc/diagrams/ASTNode.pumlc b/doc/diagrams/ASTNode.pumlc index 05c13ac..945b24d 100644 --- a/doc/diagrams/ASTNode.pumlc +++ b/doc/diagrams/ASTNode.pumlc @@ -1,10 +1,14 @@ @startuml class ASTNode { - ASTNode[] children - Property properties - void addtoSequence() - GameTree toGameTree() + ASTNode[] children + Property[] props + + addtoSequence() + toGameTree() + toGameMoveTree(previousMove) + hasProperty(propertyName) + getPropertyValue(propertyName) } @enduml diff --git a/doc/diagrams/ConvNeuralNetwork.pumlc b/doc/diagrams/ConvNeuralNetwork.pumlc new file mode 100644 index 0000000..2254e5d --- /dev/null +++ b/doc/diagrams/ConvNeuralNetwork.pumlc @@ -0,0 +1,7 @@ +@startuml + +class ConvNeuralNetwork { + +} + +@enduml diff --git a/doc/diagrams/DecisionAlgorithm.pumlc b/doc/diagrams/DecisionAlgorithm.pumlc index aada4f0..c3e9e8a 100644 --- a/doc/diagrams/DecisionAlgorithm.pumlc +++ b/doc/diagrams/DecisionAlgorithm.pumlc @@ -1,8 +1,9 @@ @startuml interface DecisionAlgorithm { - {abstract} forceNextMove(self, coords) - {abstract} pickMove(self) + {abstract} forceNextMove(coords) + {abstract} pickMove() + {abstract} clearBoard() } @enduml diff --git a/doc/diagrams/DenseNeuralNetwork.pumlc b/doc/diagrams/DenseNeuralNetwork.pumlc new file mode 100644 index 0000000..a9e7d1c --- /dev/null +++ b/doc/diagrams/DenseNeuralNetwork.pumlc @@ -0,0 +1,7 @@ +@startuml + +class DenseNeuralNetwork { + +} + +@enduml diff --git a/doc/diagrams/GameBoard.pumlc b/doc/diagrams/GameBoard.pumlc index 7a57b2d..ebeedd7 100644 --- a/doc/diagrams/GameBoard.pumlc +++ b/doc/diagrams/GameBoard.pumlc @@ -5,24 +5,25 @@ class GameBoard { int capturesBlack int capturesWhite - getBoard(self) - getBoardHeight(self) - getBoardWidth(self) - getDeepCopy(self) - getGroupLiberties(self, row, col) - getGroupLibertiesCount(self, row, col) - getGroupCells(self, row, col) - getGroupCellsCount(self, row, col) - moveAndCapture(self, row, col, player) - isMoveInBoardBounds(self, row, col) - isCellEmpty(self, row, col) - isCellEye(self, row, col) - isMoveSuicidal(self, row, col, player) - isMoveKoIllegal(self, row, col, player, prevBoards) - isPlayable(self, row, col, player, prevBoards) - score(self) - equals(self, otherBoard) - printBoard(self) + getBoard() + getBoardHeight() + getBoardWidth() + getDeepCopy() + getGroupLiberties(row, col) + getGroupLibertiesCount(row, col) + getGroupVertices(row, col) + getGroupVerticesCount(row, col) + moveAndCapture(row, col, player) + isMoveInBoardBounds(row, col) + isCellEmpty(row, col) + isCellEye(row, col) + isMoveSuicidal(row, col, player) + isMoveKoIllegal(row, col, player, prevBoards) + isPlayable(row, col, player, prevBoards) + isSensible(row, col, player, prevBoards) + score() + equals(otherBoard) + printBoard() } @enduml diff --git a/doc/diagrams/GameEngine.pumlc b/doc/diagrams/GameEngine.pumlc new file mode 100644 index 0000000..62b892e --- /dev/null +++ b/doc/diagrams/GameEngine.pumlc @@ -0,0 +1,18 @@ +@startuml + +class GameEngine { + int komi + GameState gameState + Enum daId + DecisionAlgorithm da + + setBoardsize(newSize) + clearBoard() + setKomi(komi) + setFixedHandicap(stones) + play(color, vertex) + genmove(color) + undo() +} + +@enduml diff --git a/doc/diagrams/GameMove.pumlc b/doc/diagrams/GameMove.pumlc index 0f75edd..a1d0d73 100644 --- a/doc/diagrams/GameMove.pumlc +++ b/doc/diagrams/GameMove.pumlc @@ -5,19 +5,24 @@ class GameMove { GameMove[] nextMoves GameMove previousMove boolean isPass - int[2] coords + int[] coords + Player playerWhoPassed - getRow(self) - getCol(self) - getPlayer(self) - getNextPlayer(self) - getGameLength(self) - getThisAndPrevBoards(self) - getPlayableVertices(self) - addMove(self, row, col) - addMoveForPlayer(self, row, col, player) - addPass(self) - printBoard(self) + getRow() + getCol() + getPlayer() + getNextPlayer() + getGameLength() + getThisAndPrevBoards() + getPlayableVertices() + getSensibleVertices() + addMove(row, col) + addMoveBcoords(coords) + addMoveForPlayer(row, col, player) + addPass() + addPassForPlayer() + getMainLineOfPlay() + printBoard() } @enduml diff --git a/doc/diagrams/GameState.pumlc b/doc/diagrams/GameState.pumlc index 38e1397..a913855 100644 --- a/doc/diagrams/GameState.pumlc +++ b/doc/diagrams/GameState.pumlc @@ -2,17 +2,17 @@ class GameState { int size - GameTree gameTree GameMove lastMove - 'GameData gameData - getCurrentPlayer(self) - getPlayerCode(self) - getBoard(self) - playMove(self, row, col) - playMoveForPlayer(self, row, col, player) - playPass(self) - undo(self) + getCurrentPlayer() + getPlayerCode() + getBoard() + clearBoard() + playMove(row, col) + playMoveForPlayer(row, col, player) + playPass() + playPassForPlayer(player) + undo() } @enduml diff --git a/doc/diagrams/ImagoIO.pumlc b/doc/diagrams/ImagoIO.pumlc new file mode 100644 index 0000000..848a173 --- /dev/null +++ b/doc/diagrams/ImagoIO.pumlc @@ -0,0 +1,10 @@ +@startuml + +class ImagoIO { + function[] commands_set + GameEngine gameEngine + + start() +} + +@enduml diff --git a/doc/diagrams/Keras.pumlc b/doc/diagrams/Keras.pumlc index daca149..1fa40b2 100644 --- a/doc/diagrams/Keras.pumlc +++ b/doc/diagrams/Keras.pumlc @@ -1,6 +1,9 @@ @startuml class Keras { + GameMove currentMove + NeuralNetwork neuralNetwork + forceNextMove(self, coords) pickMove(self) loadNetwork(self) diff --git a/doc/diagrams/MCTS.pumlc b/doc/diagrams/MCTS.pumlc new file mode 100644 index 0000000..ff00c62 --- /dev/null +++ b/doc/diagrams/MCTS.pumlc @@ -0,0 +1,11 @@ +@startuml + +class MCTS { + MCTSNode root + + forceNextMove(coords) + pickMove() + clearBoard() +} + +@enduml diff --git a/doc/diagrams/MCTSNode.pumlc b/doc/diagrams/MCTSNode.pumlc new file mode 100644 index 0000000..6ae8f35 --- /dev/null +++ b/doc/diagrams/MCTSNode.pumlc @@ -0,0 +1,18 @@ +@startuml + +class MCTSNode { + int visits + int score + GameMove move + MCTSNode parent + MCTSNode[] children + (int, int)[] unexploredVertices + + ucbForPlayer() + selection() + expansion() + expansionForCoords(coords) + simulation(nMatches, scoreDiffHeur) +} + +@enduml diff --git a/doc/diagrams/NeuralNetwork.pumlc b/doc/diagrams/NeuralNetwork.pumlc index 30f783e..f6c0e1c 100644 --- a/doc/diagrams/NeuralNetwork.pumlc +++ b/doc/diagrams/NeuralNetwork.pumlc @@ -1,8 +1,13 @@ @startuml class NeuralNetwork { - load(self, path) - save(self, path) + int boardSize + string path + + trainModel(games) + saveModel(modelPath) + pickMove(gameMove, player) + saveModelPlot(path) } @enduml diff --git a/doc/diagrams/Property.pumlc b/doc/diagrams/Property.pumlc new file mode 100644 index 0000000..bb06b47 --- /dev/null +++ b/doc/diagrams/Property.pumlc @@ -0,0 +1,10 @@ +@startuml + +class Property { + string name + object value + + addValue(value) +} + +@enduml diff --git a/doc/diagrams/SGF.pumlc b/doc/diagrams/SGF.pumlc index 2c30202..5ab248a 100644 --- a/doc/diagrams/SGF.pumlc +++ b/doc/diagrams/SGF.pumlc @@ -1,8 +1,7 @@ @startuml -class SGF { - GameTree loadGameTree(file) - void saveGameTree(file) +object SGF { + loadGameTree(file) } @enduml diff --git a/doc/diagrams/analysisClasses.puml b/doc/diagrams/analysisClasses.puml index 8273930..7685ea1 100644 --- a/doc/diagrams/analysisClasses.puml +++ b/doc/diagrams/analysisClasses.puml @@ -1,6 +1,6 @@ @startuml -'!include skinparams.puml +!include skinparams.puml () Player package "Game module" { diff --git a/doc/diagrams/engineModule.puml b/doc/diagrams/engineModule.puml new file mode 100644 index 0000000..c6f3a3e --- /dev/null +++ b/doc/diagrams/engineModule.puml @@ -0,0 +1,32 @@ +@startuml + +!include skinparams.puml + +package "Engine module" { + + !include ImagoIO.pumlc + !include GameEngine.pumlc + !include DecisionAlgorithm.pumlc + !include MCTS.pumlc + !include MCTSNode.pumlc + !include Keras.pumlc + !include NeuralNetwork.pumlc + !include DenseNeuralNetwork.pumlc + !include ConvNeuralNetwork.pumlc + + ImagoIO ..> GameEngine + GameEngine ..> DecisionAlgorithm + + DecisionAlgorithm <|.. MCTS + MCTSNode <. MCTS + MCTSNode -> MCTSNode + MCTSNode o--> MCTSNode + + DecisionAlgorithm <|.. Keras + Keras ..> NeuralNetwork + NeuralNetwork <|-- DenseNeuralNetwork + NeuralNetwork <|-- ConvNeuralNetwork + +} + +@enduml diff --git a/doc/diagrams/fullClasses.puml b/doc/diagrams/fullClasses.puml new file mode 100644 index 0000000..d7fe4d8 --- /dev/null +++ b/doc/diagrams/fullClasses.puml @@ -0,0 +1,16 @@ +@startuml + +!include skinparams.puml + +!include gameModule.puml +!include engineModule.puml +!include trainingModule.puml + +GameEngine --> GameState + +MCTSNode --> GameMove +Keras --> GameMove + +ASTNode --> GameMove + +@enduml diff --git a/doc/diagrams/gameModule.puml b/doc/diagrams/gameModule.puml new file mode 100644 index 0000000..9a60d3f --- /dev/null +++ b/doc/diagrams/gameModule.puml @@ -0,0 +1,18 @@ +@startuml + +!include skinparams.puml + +package "Game module" { + + !include GameState.pumlc + !include GameMove.pumlc + !include GameBoard.pumlc + + GameState ..> GameMove + GameMove -> GameMove : Previous move + GameMove o--> GameMove : Next moves + GameMove ..> GameBoard + +} + +@enduml diff --git a/doc/diagrams/gtpEngine.puml b/doc/diagrams/gtpEngine.puml deleted file mode 100644 index 5b098da..0000000 --- a/doc/diagrams/gtpEngine.puml +++ /dev/null @@ -1,36 +0,0 @@ -@startuml - -!include skinparams.puml - -class IO { - processComand() -} - -class EngineCore { - setBoardsize() - clearBoard() - setKomi() - setFixedHandicap() - play() - genmove() - undo() -} - -!include GameState.pumlc - -'class EngineBoard { -' setSize() -' setKomi() -' play() -' undo() -'} - -class EngineAI { - genmove(board) -} - -IO --> EngineCore -EngineCore --> GameState -EngineCore --> EngineAI - -@enduml diff --git a/doc/diagrams/skinparams.puml b/doc/diagrams/skinparams.puml index 2a9e58e..c94ad2d 100644 --- a/doc/diagrams/skinparams.puml +++ b/doc/diagrams/skinparams.puml @@ -9,4 +9,11 @@ skinparam { linetype polyline } +'skinparam { +' shadowing false +' ActorBorderColor #339933 +' ActorBackgroundColor #88FF88 +' linetype polyline +'} + @enduml diff --git a/doc/diagrams/trainingModule.puml b/doc/diagrams/trainingModule.puml new file mode 100644 index 0000000..81d5d72 --- /dev/null +++ b/doc/diagrams/trainingModule.puml @@ -0,0 +1,20 @@ +@startuml + +!include skinparams.puml + +package "Training module" { + + !include SGF.pumlc + !include sgflex.pumlc + !include sgfyacc.pumlc + !include ASTNode.pumlc + !include Property.pumlc + + SGF ..> sgfyacc + sgfyacc .> sgflex + sgfyacc ..> ASTNode + ASTNode .> Property + +} + +@enduml diff --git a/doc/tex/biber.bib b/doc/tex/biber.bib index f22e058..8884962 100644 --- a/doc/tex/biber.bib +++ b/doc/tex/biber.bib @@ -109,8 +109,26 @@ url = {http://www.dabeaz.com/ply} } +@online{vim, + title = {welcome home : vim online}, + urldate = {2022}, + url = {https://www.vim.org} +} + @online{neovim, title = {Home - Neovim}, urldate = {2022}, url = {http://neovim.io} } + +@online{latex, + title = {LaTeX - A document preparation system}, + urldate = {2022}, + url = {https://www.latex-project.org} +} + +@online{puml, + title = {Open-source tool that uses simple textual descriptions to draw beautiful UML diagrams.}, + urldate = {2022}, + url = {https://plantuml.com} +} diff --git a/doc/tex/implementation.tex b/doc/tex/implementation.tex index 40dfb93..f88d57f 100644 --- a/doc/tex/implementation.tex +++ b/doc/tex/implementation.tex @@ -22,20 +22,20 @@ layouts. \paragraph{NumPy\cite{numpy}} -NumPy is a scientific package for python providing a lot of mathematical tools. -The most interesting for this project are its capabilities to create and -transform matrices. +A scientific package for python providing a lot of mathematical tools. The most +interesting for this project are its capabilities to create and transform +matrices. \paragraph{Matplotlib\cite{matplotlib}} -Matplotlib is a python library for creating graphs and other visualizations. It -is used to show the likelihood of moves the neural networks of the project -create from a board configuration. +A python library for creating graphs and other visualizations. It is used to +show the likelihood of moves the neural networks of the project create from a +board configuration. \paragraph{PLY\cite{ply}} -PLY is a tool for generating compilers in Python. It is an implementation of the -lex and yacc utilities, allowing to create lexers and parsers. It is used in the +A tool for generating compilers in Python. It is an implementation of the lex +and yacc utilities, allowing to create lexers and parsers. It is used in the project to create the SGF parser which transform SGF files to internal representations of Go matches. @@ -44,103 +44,61 @@ representations of Go matches. These are some utility libraries commonly used for frequent programming tasks: \begin{itemize} - \item \textbf{sys}, to stop the execution of the program or access system info such + \item \textbf{sys}: to stop the execution of the program or access system info such as primitives maximum values. - \item \textbf{os}, to interact with files. - \item \textbf{re}, to check strings with regular expressions. - \item \textbf{random}, to get random values, for example to obtain a random + \item \textbf{os}: to interact with files. + \item \textbf{re}: to check strings with regular expressions. + \item \textbf{random}: to get random values, for example to obtain a random item from a list. - \item \textbf{copy}, to obtain deep copies of multidimensional arrays. + \item \textbf{copy}: to obtain deep copies of multidimensional arrays. \end{itemize} \subsubsection{Development tools} \paragraph{Neovim\cite{neovim}} -\begin{itemize} +A text editor based on Vim\cite{vim}, providing its same functionality with +useful additions and defaults for modern computers and terminal emulators. With +some extensions and configuration it can become a powerful development +environment with a very fluid usage experience. That, and the fact that the +developer considers Vim's modal editing the best writing experience possible on +a computer, have made Neovim the editor of choice. - \item Extensions +\begin{itemize} + %TODO: Write about neovim extensions + \item FZF \item Extensions \end{itemize} -% Old stuff starts here +\subsubsection{Documentation tools} -\subsection{Engine} +\paragraph{\LaTeX\cite{latex}} -An implementation of GTP, that is, the piece of software which offers the GTP -interface to other applications.\@ It is designed to be used by a software -controller but can also be directly run, mostly for debugging purposes. Its -design is shown in \fref{fig:engine}. The core of the engine is related with -three components, each with a separate responsibility: +A typesetting system widely used in the investigation field, among others. It +allows for documentation like this text to be written in plain text and then +compiled to PDF or other formats, which permits keeping the source files of the +documentation small and organized plus other benefits of plain text such as +being able to use version control. -\begin{itemize} - \item The IO component is the one called from other applications and offers - the text interface. It reads and processes input and calls corresponding - commands from the core of the engine. - \item The EngineBoard component stores the state of the match, recording - information such as the history of boards positions and whose turn goes - next. The engine core uses it for these state-storing purposes. - \item The EngineAI component is responsible of analyzing the match and - generate moves. The engine core uses it when a decision has to be made - by the AI, such as when a move needs to be generated by the engine. -\end{itemize} +\paragraph{PlantUML\cite{puml}} + +A program which creates diagrams from plain text files. PlantUML supports syntax +for many different sorts of diagrams, mainly but not only UML. It has been used +to generate the diagrams used in this text. + +\paragraph{Make} + +A tool for specifying and handling dependencies on a build system. It reads a +file, typically named ``Makefile'', containing which files are needed and on +which other files each of them depends, and then generates those files or +updates them if they already exist but their source files are newer than them. + +It has been used to generate this text from \LaTeX{} and PlantUML source files. +The contents of the Makefile with which this document has been compiled are +shown in \flist{code:makefile}. -\begin{figure}[h] - \begin{center} - \includegraphics[width=\textwidth]{diagrams/gtpEngine.png} - \caption{Design of the GTP engine.}\label{fig:engine} - \end{center} -\end{figure} - -\subsection{Modules} - -One module to store the state of the game and the game tree. One module to parse -moves. One module to read and write SGF files. Modules are shown in -\fref{fig:modules}. - -\begin{figure}[h] - \begin{center} - \includegraphics[width=\textwidth]{diagrams/modules.png} - \caption{Modules.}\label{fig:modules} - \end{center} -\end{figure} - -\subsection{Representation of a match} - -A regular Go match is composed of a list of moves. But since game review and -variants exploration is an important part of Go learning, \program{} allows for -navigation back and forth through the board states of a match and for new -variants to be created from each of these board states. Therefore, a match is -represented as a tree of moves. The state of the board at any given move must -also be stored so liberties, captures count and legality of moves can be -addressed, so it is represented with its own class, which holds a reference both -to the game tree and the current move. Moves depend on a representation of the -game board to have access to its current layout and count of captured stones. -These classes and their relationships can be seen in -\fref{fig:gameRepresentation}. - -\begin{figure}[h] - \begin{center} - \includegraphics[width=0.7\textwidth]{diagrams/gameRepresentation.png} - \caption{A game is represented as a tree of moves.}\label{fig:gameRepresentation} - \end{center} -\end{figure} - -\subsection{SGF} - -To parse SGF files a lexer and parser have been implemented using PLY.\@ The -result of the parsing is an AST (Annotated Syntax Tree) reflecting the contents -of the text input, each node with zero or more properties, and with the ability -to convert themselves and their corresponding subtree into a GameTree. This is -done for the root node, since from the SGF specification there are some -properties only usable in the root node, like those which specify general game -information and properties such as rank of players or komi. These components are -shown in \fref{fig:sgfModule}. - -\begin{figure}[h] - \begin{center} - \includegraphics[width=\textwidth]{diagrams/sgfModule.png} - \caption{Components of the SGF file parsing module.}\label{fig:sgfModule} - \end{center} -\end{figure} +\begin{listing}[h] + \inputminted{make}{Makefile} + \caption{Documentation Makefile}\label{code:makefile} +\end{listing} diff --git a/doc/tex/systemDesign.tex b/doc/tex/systemDesign.tex index 5988ae0..ccd1c48 100644 --- a/doc/tex/systemDesign.tex +++ b/doc/tex/systemDesign.tex @@ -1,2 +1,95 @@ \section{System Design} +\subsection{Class diagram} + +The full class diagram is shown in \fref{fig:fullClasses} + +\begin{figure}[h] + \begin{center} + \includegraphics[width=\textwidth]{diagrams/fullClasses.png} + \caption{Full class diagram.} + \label{fig:fullClasses} + \end{center} +\end{figure} + +% From here + + +\subsection{Engine} + +An implementation of GTP, that is, the piece of software which offers the GTP +interface to other applications.\@ It is designed to be used by a software +controller but can also be directly run, mostly for debugging purposes. Its +design is shown in \fref{fig:engine}. The core of the engine is related with +three components, each with a separate responsibility: + +\begin{itemize} + \item The IO component is the one called from other applications and offers + the text interface. It reads and processes input and calls corresponding + commands from the core of the engine. + \item The EngineBoard component stores the state of the match, recording + information such as the history of boards positions and whose turn goes + next. The engine core uses it for these state-storing purposes. + \item The EngineAI component is responsible of analyzing the match and + generate moves. The engine core uses it when a decision has to be made + by the AI, such as when a move needs to be generated by the engine. +\end{itemize} + +\begin{figure}[h] + \begin{center} + \includegraphics[width=\textwidth]{diagrams/engineModule.png} + \caption{Design of the GTP engine.}\label{fig:engine} + \end{center} +\end{figure} + +\subsection{Modules} + +One module to store the state of the game and the game tree. One module to parse +moves. One module to read and write SGF files. Modules are shown in +\fref{fig:modules}. + +\begin{figure}[h] + \begin{center} + \includegraphics[width=\textwidth]{diagrams/modules.png} + \caption{Modules.}\label{fig:modules} + \end{center} +\end{figure} + +\subsection{Representation of a match} + +A regular Go match is composed of a list of moves. But since game review and +variants exploration is an important part of Go learning, \program{} allows for +navigation back and forth through the board states of a match and for new +variants to be created from each of these board states. Therefore, a match is +represented as a tree of moves. The state of the board at any given move must +also be stored so liberties, captures count and legality of moves can be +addressed, so it is represented with its own class, which holds a reference both +to the game tree and the current move. Moves depend on a representation of the +game board to have access to its current layout and count of captured stones. +These classes and their relationships can be seen in +\fref{fig:gameRepresentation}. + +\begin{figure}[h] + \begin{center} + \includegraphics[width=0.7\textwidth]{diagrams/gameRepresentation.png} + \caption{A game is represented as a tree of moves.}\label{fig:gameRepresentation} + \end{center} +\end{figure} + +\subsection{SGF} + +To parse SGF files a lexer and parser have been implemented using PLY.\@ The +result of the parsing is an AST (Annotated Syntax Tree) reflecting the contents +of the text input, each node with zero or more properties, and with the ability +to convert themselves and their corresponding subtree into a GameTree. This is +done for the root node, since from the SGF specification there are some +properties only usable in the root node, like those which specify general game +information and properties such as rank of players or komi. These components are +shown in \fref{fig:sgfModule}. + +\begin{figure}[h] + \begin{center} + \includegraphics[width=\textwidth]{diagrams/sgfModule.png} + \caption{Components of the SGF file parsing module.}\label{fig:sgfModule} + \end{center} +\end{figure} diff --git a/doc/tex/tfg.tex b/doc/tex/tfg.tex index f387064..4c64bb2 100644 --- a/doc/tex/tfg.tex +++ b/doc/tex/tfg.tex @@ -13,6 +13,9 @@ \usepackage[backend=biber, style=numeric, sorting=none]{biblatex} \addbibresource{tex/biber.bib} +\usepackage{minted} % Code importing and formatting +\setminted{linenos, breaklines} + \geometry{left=4cm,top=2cm,bottom=2cm,right=4cm} \hypersetup{colorlinks=false, @@ -27,6 +30,7 @@ \newcommand{\program}{Imago} \newcommand{\fref}[1]{Fig.~\ref{#1}} +\newcommand{\flist}[1]{Listing~\ref{#1}} %\newcommand{\uurl}[1]{\underline{\url{#1}}} \newcommand{\tabitem}{~~\llap{\textbullet}~~} @@ -110,10 +114,14 @@ inclusion to use this template is included here. \clearpage +\setcounter{secnumdepth}{3} +\setcounter{tocdepth}{4} \tableofcontents \listoffigures +\listoflistings + \clearpage \input{tex/introduction.tex} @@ -122,7 +130,7 @@ inclusion to use this template is included here. \input{tex/systemAnalysis.tex} -%\input{tex/systemDesign.tex} +\input{tex/systemDesign.tex} \input{tex/implementation.tex} diff --git a/go.py b/go.py index d4efc1b..7cb8555 100755 --- a/go.py +++ b/go.py @@ -24,8 +24,6 @@ if __name__ == "__main__": print() - player = str(GAMESTATE.getPlayerCode()) - moveRow = move[0] moveCol = move[1] diff --git a/imago/data/enums.py b/imago/data/enums.py index 9d963ec..56fe2cc 100644 --- a/imago/data/enums.py +++ b/imago/data/enums.py @@ -16,3 +16,8 @@ class Player(Enum): if player == cls.WHITE: return cls.BLACK return cls.EMPTY + +class DecisionAlgorithms(Enum): + #RANDOM = enumAuto() + MONTECARLO = enumAuto() + KERAS = enumAuto() diff --git a/imago/engine/decisionAlgorithmFactory.py b/imago/engine/decisionAlgorithmFactory.py index 094a816..25517fa 100644 --- a/imago/engine/decisionAlgorithmFactory.py +++ b/imago/engine/decisionAlgorithmFactory.py @@ -4,11 +4,6 @@ from enum import Enum, auto as enumAuto from imago.engine.monteCarlo import MCTS from imago.engine.keras.keras import Keras -class DecisionAlgorithms(Enum): - #RANDOM = enumAuto() - MONTECARLO = enumAuto() - KERAS = enumAuto() - class DecisionAlgorithmFactory: def create(self, algorithm, move): diff --git a/imago/engine/keras/neuralNetwork.py b/imago/engine/keras/neuralNetwork.py index 7eddb9d..c414a78 100644 --- a/imago/engine/keras/neuralNetwork.py +++ b/imago/engine/keras/neuralNetwork.py @@ -28,7 +28,7 @@ class NeuralNetwork: self.model = self._loadModel(self.path) except FileNotFoundError: self.model = self._initModel(boardSize) - self.saveModelPlot() + self.saveModelPlot("model.png") def _initModel(self, boardSize=DEF_BOARD_SIZE): raise NotImplementedError("Tried to directly use NeuralNetwork class. Use one of the subclasses instead.") @@ -120,7 +120,7 @@ class NeuralNetwork: for col in range(self.boardSize): predictionBoard[row][col] = predictionVector[row * self.boardSize + col] predictionPass = predictionVector[-1] - self.saveHeatmap(predictionBoard, predictionPass) + self._saveHeatmap(predictionBoard, predictionPass) # Search the highest valued vertex which is also playable playableVertices = gameMove.getPlayableVertices() @@ -147,7 +147,7 @@ class NeuralNetwork: batch_size = 1, verbose = 2) - def saveHeatmap(self, data, passChance): + def _saveHeatmap(self, data, passChance): rows = len(data) cols = len(data[0]) @@ -202,10 +202,10 @@ class NeuralNetwork: letter = 'J' return labels - def saveModelPlot(self): + def saveModelPlot(self, path): plot_model( self.model, - to_file="model.png", + to_file=path, show_shapes=True, show_dtype=True, show_layer_names=True, diff --git a/imago/gameLogic/gameState.py b/imago/gameLogic/gameState.py index 5232a43..72b91b4 100644 --- a/imago/gameLogic/gameState.py +++ b/imago/gameLogic/gameState.py @@ -43,7 +43,7 @@ class GameState: prevBoards = self.lastMove.getThisAndPrevBoards() playable, message = self.lastMove.board.isPlayable(row, col, player, prevBoards) if playable: - self.__addMove(player, row, col) + self._addMove(player, row, col) return True print("Invalid Move! %s" % message) return False @@ -60,7 +60,7 @@ class GameState: """Sets the move before the last move as the new last move.""" self.lastMove = self.lastMove.previousMove - def __addMove(self, player, row, col): + def _addMove(self, player, row, col): # Check a last move already exists if self.lastMove is None: -- cgit v1.2.1